oyvindberg / typo

Typed Postgresql integration for Scala. Hopes to avoid typos
https://oyvindberg.github.io/typo/
MIT License
99 stars 9 forks source link

Add support for generating code into a build with multiple projects #73

Closed oyvindberg closed 9 months ago

oyvindberg commented 9 months ago

It's very common that you don't want to expose all the tables in one place in your system. You also don't want duplication of generated code or more than one script to generate database code.

The solution is to pass a ProjectGraph structure to generateFromDb instead, in which you encode the structure of the (relevant) projects in your build.

Dependencies between projects are encoded by nesting in the tree you pass (each node has a downstream member), with the root being the uppermost one.

If multiple downstream projects want to generate the same code, it'll be pulled up to the level necessary to become visible for all of them.

sample:

import typo.*
import java.nio.file.Path
import java.sql.Connection

def generate(implicit c: Connection): String = {
  val cwd: Path = Path.of(sys.props("user.dir"))

  val generated = generateFromDb(
    Options(
      pkg = "org.mypkg",
      jsonLibs = Nil,
      dbLib = Some(DbLibName.ZioJdbc)
    ),
    // setup a project graph. this outer-most project is the root project.
    // if multiple downstream projects need the same relation, it'll be pulled up until it's visible for all.
    // in this simple example it means `a.bicycle` will be pulled up here
    ProjectGraph(
      name = "a",
      target = cwd.resolve("a/src/main/typo"),
      value = Selector.None,
      scripts = Nil,
      downstream = List(
        ProjectGraph(
          name = "b",
          target = cwd.resolve("b/src/main/typo"),
          value = Selector.fullRelationNames(
            "a.bicycle",
            "b.person"
          ),
          // where to find sql files
          scripts = List(cwd.resolve("b/src/main/sql")),
          downstream = Nil
        ),
        ProjectGraph(
          name = "c",
          target = cwd.resolve("b/src/main/typo"),
          value = Selector.fullRelationNames(
            "a.bicycle",
            "c.animal"
          ),
          scripts = List(cwd.resolve("b/src/main/sql")),
          downstream = Nil
        )
      )
    )
  )

  generated.foreach(_.overwriteFolder())

  import scala.sys.process.*

  (List("git", "add") ++ generated.map(_.folder.toString)).!!
}

todo: