Newer
Older
support / build.sbt
import org.scalajs.linker.interface.ModuleSplitStyle
import scala.sys.process._
import sbt.nio.file.FileTreeView
import com.typesafe.sbt.packager.docker._
import NativePackagerHelper._
import sbtcrossproject.CrossPlugin.autoImport.{CrossType, crossProject}

ThisBuild / version := "0.1.0-SNAPSHOT"

ThisBuild / scalaVersion := scala3Version

// TODO: integrate vite build and Docker publishing
// Taken from mdr-app, moving to plugin would be nice
lazy val viteBuild = taskKey[File]("Vite build")
lazy val viteMonitoredFiles =
  taskKey[Seq[File]]("Files monitored for vite build")
lazy val viteDist = settingKey[File]("Vite dist directory")
lazy val caddyFile = settingKey[File]("Caddyfile for caddy docker image")

lazy val core = crossProject(JSPlatform, JVMPlatform)
  .crossType(CrossType.Pure)
  .in(file("core"))

lazy val app = (project in file("app"))
  .enablePlugins(ScalaJSPlugin, MockDataExport, DockerPlugin)
  .settings(
    IWDeps.useZIO(Test),
    IWDeps.laminar,
    IWDeps.zioJson,
    libraryDependencies ++= Seq(
      "com.raquo" %%% "waypoint" % "0.5.0",
      "be.doeraene" %%% "url-dsl" % "0.4.0",
      "io.laminext" %%% "core" % IWVersions.laminar,
      "io.laminext" %%% "ui" % IWVersions.laminar,
      "io.laminext" %%% "tailwind" % IWVersions.laminar,
      "io.laminext" %%% "validation-core" % IWVersions.laminar
    )
  )
  .settings(
    scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.ESModule) },
    scalaJSLinkerConfig ~= {
      _.withModuleSplitStyle(ModuleSplitStyle.FewestModules)
    },
    scalaJSLinkerConfig ~= { _.withSourceMap(false) },
    scalaJSUseMainModuleInitializer := true
  )
  .settings(
    caddyFile := baseDirectory.value / "Caddyfile",
    dockerRepository := Some("docker.e-bs.cz"),
    dockerUsername := Some("cmi/posuzovani-mdr-pdb"),
    dockerExposedPorts += 80,
    Docker / mappings ++= directory(viteBuild.value),
    Docker / mappings += caddyFile.value -> "Caddyfile",
    dockerCommands := Seq(
      Cmd("FROM", "caddy:2.4.6"),
      Cmd("COPY", "Caddyfile", "/etc/caddy/Caddyfile"),
      Cmd("COPY", "vite", "/srv/mdr/pdb")
    ),
    viteDist := target.value / "vite",
    viteMonitoredFiles := {
      val baseGlob = baseDirectory.value.toGlob
      def baseFiles(pattern: String): Glob = baseGlob / pattern
      val viteConfigs =
        FileTreeView.default.list(
          List(baseFiles("*.json"), baseFiles("*.js"), baseFiles("*.html"))
        )
      val linkerDirectory =
        (Compile / fullLinkJS / scalaJSLinkerOutputDirectory).value
      val viteInputs = FileTreeView.default.list(
        linkerDirectory.toGlob / "*.js"
      )
      (viteConfigs ++ viteInputs).map(_._1.toFile)
    },
    viteBuild := {
      val s = streams.value
      val dist = viteDist.value
      val files = viteMonitoredFiles.value
      // We depend on fullLinkJS
      val _ = (Compile / fullLinkJS).value
      def doBuild() = Process(
        "yarn" :: "build" :: "--outDir" :: dist.toString :: Nil,
        baseDirectory.value
      ) ! s.log
      val cachedFun = FileFunction.cached(s.cacheDirectory / "vite") { _ =>
        doBuild()
        Set(dist)
      }
      cachedFun(files.toSet).head
    }
  )
  .dependsOn(core.js)

lazy val root = (project in file("."))
  .settings(name := "mdr-personnel-db", publish / skip := true)
  // Auto activates for all projects, but make sure we have required dependencies
  .enablePlugins(IWScalaProjectPlugin)
  .aggregate(app)