diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0815ed3..27c9b67 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: pull_request: branches: ['**', '!update/**', '!pr/**'] push: - branches: ['**', '!update/**', '!pr/**'] + branches: ['main'] tags: [v*] env: @@ -22,7 +22,7 @@ jobs: matrix: os: [ubuntu-latest] scala: [3] - java: [temurin@17] + java: [temurin@21] project: [jvm] runs-on: ${{ matrix.os }} timeout-minutes: 60 @@ -30,7 +30,7 @@ jobs: - uses: taiki-e/install-action@just - uses: coursier/setup-action@main with: - jvm: temurin@17 + jvm: temurin@21 apps: scala-cli - name: Checkout current branch (full) uses: actions/checkout@main @@ -58,11 +58,8 @@ jobs: - name: compile run: ./mill __.compile - # Sometimes the tests will timeout if they have to fetch all the transitive scala-js deps the first time... let's have coursier put them in the cache - - name: cache test deps - run: | - cs fetch com.raquo:laminar_sjs1_3:17.2.0 - cs fetch org.scala-js:scalajs-dom_sjs1_3:2.8.0 + - name: scala-cli version + run: scala-cli compile -e "()" --platform js && scala-cli run -e "()" - name: Test run: ./mill __.test @@ -79,7 +76,7 @@ jobs: - uses: coursier/setup-action@main with: - jvm: temurin@17 + jvm: temurin@21 apps: scala-cli - name: Import GPG key @@ -112,7 +109,7 @@ jobs: steps: - uses: coursier/setup-action@main with: - jvm: temurin@17 + jvm: temurin@21 apps: scala-cli - uses: actions/checkout@main with: diff --git a/.mill-version b/.mill-version deleted file mode 100644 index f5f40dc..0000000 --- a/.mill-version +++ /dev/null @@ -1 +0,0 @@ -0.12.10 \ No newline at end of file diff --git a/.scalafmt.conf b/.scalafmt.conf index 1568b8f..4a0d6b7 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,4 +1,4 @@ -version = "3.8.3" +version = "3.9.7" project.git = true runner.dialect = scala3 @@ -14,5 +14,4 @@ rewrite.scala3.insertEndMarkerMinLines = 1 newlines.beforeCurlyLambdaParams = multiline newlines.avoidForSimpleOverflow = [tooLong] newlines.selectChains = "unfold" -maxColumn = 120 -project.excludeFilters = [ ".*/build\\.sc" ] \ No newline at end of file +maxColumn = 120 \ No newline at end of file diff --git a/build.mill b/build.mill index 658f76d..0071b54 100644 --- a/build.mill +++ b/build.mill @@ -1,34 +1,41 @@ -import os.copy.over -import $ivy.`io.github.quafadas::millSite::0.0.24` -import $ivy.`de.tototec::de.tobiasroeser.mill.vcs.version::0.4.0` -import $ivy.`com.goyeau::mill-scalafix::0.4.0` -import $file.playwrightVersion // used to cache in GHA +//| mill-version: 1.0.3 +//| mill-jvm-version: 21 +//| mvnDeps: +//| - com.goyeau::mill-scalafix::0.6.0 +//| - com.lihaoyi::mill-contrib-buildinfo:$MILL_VERSION + -import io.github.quafadas.millSite._ +import os.copy.over +// import io.github.quafadas.millSite._ import mill._, scalalib._, publish._, scalanativelib._ import mill.scalalib.scalafmt.ScalafmtModule -import de.tobiasroeser.mill.vcs.version._ +import mill.util.* import com.goyeau.mill.scalafix.ScalafixModule import java.text.Format -object V{ - val scalaLts = "3.3.5" +object V{ + val scalaLts = "3.3.6" + val pwV = build.pwV val http4sVersion = "0.23.30" val circeVersion = "0.14.10" + val scalaVersion = "3.7.2" + val laminar = "17.2.1" + val scalaJsDom = "2.8.1" + val scalaJs = "1.19.0" } trait FormatFix extends ScalafmtModule with ScalafixModule with ScalaModule trait FormatFixPublish extends ScalaModule with FormatFix with PublishModule{ - override def scalaVersion = "3.6.4" + override def scalaVersion = V.scalaVersion - override def scalacOptions: Target[Seq[String]] = super.scalacOptions() ++ Seq("-Wunused:all") + override def scalacOptions = super.scalacOptions() ++ Seq("-Wunused:all") def publishVersion = VcsVersion.vcsState().format() - override def pomSettings = T { + override def pomSettings = Task { PomSettings( description = "An experimental live server for scala JS projects", organization = "io.github.quafadas", @@ -46,79 +53,33 @@ trait FormatFixPublish extends ScalaModule with FormatFix with PublishModule{ trait Testy extends TestModule.Munit with FormatFix { - override def defaultCommandName(): String = "test" + override def defaultTask(): String = "testForked" - def ivyDeps = super.ivyDeps() ++ sjsls.ivyDeps() ++ Seq( - ivy"org.typelevel::munit-cats-effect::2.0.0", - ivy"org.scalameta::munit::1.1.0", - ivy"com.lihaoyi::os-lib:0.11.4" + def mvnDeps = super.mvnDeps() ++ sjsls.mvnDeps() ++ Seq( + mvn"org.typelevel::munit-cats-effect::2.0.0", + mvn"org.scalameta::munit::1.1.0", + mvn"com.lihaoyi::os-lib:0.11.4" ) } -object routes extends FormatFixPublish { - - def scalaVersion: T[String] = V.scalaLts - - def ivyDeps = Agg( - ivy"org.http4s::http4s-core:${V.http4sVersion}", - ivy"org.http4s::http4s-client:${V.http4sVersion}", - ivy"org.http4s::http4s-server:${V.http4sVersion}", - ivy"org.http4s::http4s-dsl::${V.http4sVersion}", - ivy"com.outr::scribe-cats::3.15.0" - ) - - override def artifactName = "frontend-routes" - - object test extends Testy with ScalaTests{ - def ivyDeps = super.ivyDeps() ++ sjsls.ivyDeps() - } - -} - -object sjsls extends FormatFixPublish { - - override def scalaVersion = V.scalaLts +object SiteUnidoc extends ScalaModule, UnidocModule : + def scalaVersion = V.scalaVersion + def moduleDeps = Seq(build.sjsls, build.routes) - def ivyDeps = super.ivyDeps() ++ Seq( - ivy"org.http4s::http4s-ember-server::${V.http4sVersion}", - ivy"org.http4s::http4s-ember-client::${V.http4sVersion}", - ivy"org.http4s::http4s-scalatags::0.25.2", - ivy"io.circe::circe-core::${V.circeVersion}", - ivy"io.circe::circe-generic::${V.circeVersion}", - ivy"co.fs2::fs2-io::3.11.0", - ivy"com.lihaoyi::scalatags::0.13.1", - ivy"com.monovore::decline::2.5.0", - ivy"com.monovore::decline-effect::2.5.0", - - ) + def unidocDocumentTitle = Task { "Scala JS Live Server Docs" } + def unidocVersion = Some(VcsVersion.vcsState().format()) - def moduleDeps = Seq(routes) - def artifactName = "sjsls" +// def scalaVersion = sjsls.scalaVersion - object test extends Testy with ScalaTests { - def ivyDeps = super.ivyDeps() ++ sjsls.ivyDeps() ++ Seq( - - ivy"com.microsoft.playwright:playwright:${playwrightVersion.pwV}", - ivy"com.microsoft.playwright:driver-bundle:${playwrightVersion.pwV}" - ) - } - //def scalaNativeVersion = "0.4.17" // aspirational :-) - -} - -object site extends SiteModule { - - def scalaVersion = sjsls.scalaVersion - - override def moduleDeps = Seq(sjsls) -} +// override def moduleDeps = Seq(sjsls) +// } // SN deps which aren't yet there. /** 1 targets failed -project.resolvedIvyDeps +project.resolvedmvnDeps Resolution failed for 2 modules: -------------------------------------------- com.outr:scribe-cats_native0.4_3:3.13.5 diff --git a/justfile b/justfile index d128cfc..6ae0038 100644 --- a/justfile +++ b/justfile @@ -59,4 +59,7 @@ format: fix: ./mill __.fix +serveUnidoc: + cs launch io.github.quafadas::sjsls:0.2.8 -- --path-to-index-html C:\live-server-scala-cli-js\out\SiteUnidoc\unidocLocal.dest --build-tool none + gha: setupMill setupPlaywright test diff --git a/mill b/mill index 8eda811..eb70f46 100755 --- a/mill +++ b/mill @@ -1,20 +1,45 @@ #!/usr/bin/env sh -# This is a wrapper script, that automatically download mill from GitHub release pages -# You can give the required mill version with --mill-version parameter -# If no version is given, it falls back to the value of DEFAULT_MILL_VERSION +# This is a wrapper script, that automatically selects or downloads Mill from Maven Central or GitHub release pages. # -# Original Project page: https://github.com/lefou/millw -# Script Version: 0.4.12 +# This script determines the Mill version to use by trying these sources +# - env-variable `MILL_VERSION` +# - local file `.mill-version` +# - local file `.config/mill-version` +# - `mill-version` from YAML fronmatter of current buildfile +# - if accessible, find the latest stable version available on Maven Central (https://repo1.maven.org/maven2) +# - env-variable `DEFAULT_MILL_VERSION` +# +# If a version has the suffix '-native' a native binary will be used. +# If a version has the suffix '-jvm' an executable jar file will be used, requiring an already installed Java runtime. +# If no such suffix is found, the script will pick a default based on version and platform. +# +# Once a version was determined, it tries to use either +# - a system-installed mill, if found and it's version matches +# - an already downloaded version under ~/.cache/mill/download +# +# If no working mill version was found on the system, +# this script downloads a binary file from Maven Central or Github Pages (this is version dependent) +# into a cache location (~/.cache/mill/download). +# +# Mill Project URL: https://github.com/com-lihaoyi/mill +# Script Version: 1.0.0-M1-21-7b6fae-DIRTY892b63e8 # # If you want to improve this script, please also contribute your changes back! +# This script was generated from: dist/scripts/src/mill.sh # # Licensed under the Apache License, Version 2.0 set -e +if [ "$1" = "--setup-completions" ] ; then + # Need to preserve the first position of those listed options + MILL_FIRST_ARG=$1 + shift +fi + if [ -z "${DEFAULT_MILL_VERSION}" ] ; then - DEFAULT_MILL_VERSION=0.12.5 + DEFAULT_MILL_VERSION=1.0.3 fi @@ -31,16 +56,17 @@ fi # Explicit commandline argument takes precedence over all other methods if [ "$1" = "--mill-version" ] ; then - shift - if [ "x$1" != "x" ] ; then - MILL_VERSION="$1" - shift - else - echo "You specified --mill-version without a version." 1>&2 - echo "Please provide a version that matches one provided on" 1>&2 - echo "${MILL_REPO_URL}/releases" 1>&2 - false - fi + echo "The --mill-version option is no longer supported." 1>&2 +fi + +MILL_BUILD_SCRIPT="" + +if [ -f "build.mill" ] ; then + MILL_BUILD_SCRIPT="build.mill" +elif [ -f "build.mill.scala" ] ; then + MILL_BUILD_SCRIPT="build.mill.scala" +elif [ -f "build.sc" ] ; then + MILL_BUILD_SCRIPT="build.sc" fi # Please note, that if a MILL_VERSION is already set in the environment, @@ -52,6 +78,8 @@ if [ -z "${MILL_VERSION}" ] ; then MILL_VERSION="$(tr '\r' '\n' < .mill-version | head -n 1 2> /dev/null)" elif [ -f ".config/mill-version" ] ; then MILL_VERSION="$(tr '\r' '\n' < .config/mill-version | head -n 1 2> /dev/null)" + elif [ -n "${MILL_BUILD_SCRIPT}" ] ; then + MILL_VERSION="$(cat ${MILL_BUILD_SCRIPT} | grep '//[|] *mill-version: *' | sed 's;//| *mill-version: *;;')" fi fi @@ -65,7 +93,7 @@ fi if [ -z "${MILL_VERSION}" ] ; then # TODO: try to load latest version from release page echo "No mill version specified." 1>&2 - echo "You should provide a version via '.mill-version' file or --mill-version option." 1>&2 + echo "You should provide a version via a '//| mill-version: ' comment or a '.mill-version' file." 1>&2 mkdir -p "${MILL_DOWNLOAD_PATH}" LANG=C touch -d '1 hour ago' "${MILL_DOWNLOAD_PATH}/.expire_latest" 2>/dev/null || ( @@ -101,7 +129,60 @@ if [ -z "${MILL_VERSION}" ] ; then fi fi -MILL="${MILL_DOWNLOAD_PATH}/${MILL_VERSION}" +MILL_NATIVE_SUFFIX="-native" +MILL_JVM_SUFFIX="-jvm" +FULL_MILL_VERSION=$MILL_VERSION +ARTIFACT_SUFFIX="" +set_artifact_suffix(){ + if [ "$(expr substr $(uname -s) 1 5 2>/dev/null)" = "Linux" ]; then + if [ "$(uname -m)" = "aarch64" ]; then + ARTIFACT_SUFFIX="-native-linux-aarch64" + else + ARTIFACT_SUFFIX="-native-linux-amd64" + fi + elif [ "$(uname)" = "Darwin" ]; then + if [ "$(uname -m)" = "arm64" ]; then + ARTIFACT_SUFFIX="-native-mac-aarch64" + else + ARTIFACT_SUFFIX="-native-mac-amd64" + fi + else + echo "This native mill launcher supports only Linux and macOS." 1>&2 + exit 1 + fi +} + +case "$MILL_VERSION" in + *"$MILL_NATIVE_SUFFIX") + MILL_VERSION=${MILL_VERSION%"$MILL_NATIVE_SUFFIX"} + set_artifact_suffix + ;; + + *"$MILL_JVM_SUFFIX") + MILL_VERSION=${MILL_VERSION%"$MILL_JVM_SUFFIX"} + ;; + + *) + case "$MILL_VERSION" in + 0.1.*) ;; + 0.2.*) ;; + 0.3.*) ;; + 0.4.*) ;; + 0.5.*) ;; + 0.6.*) ;; + 0.7.*) ;; + 0.8.*) ;; + 0.9.*) ;; + 0.10.*) ;; + 0.11.*) ;; + 0.12.*) ;; + *) + set_artifact_suffix + esac + ;; +esac + +MILL="${MILL_DOWNLOAD_PATH}/$MILL_VERSION$ARTIFACT_SUFFIX" try_to_use_system_mill() { if [ "$(uname)" != "Linux" ]; then @@ -174,49 +255,59 @@ EOF try_to_use_system_mill # If not already downloaded, download it -if [ ! -s "${MILL}" ] ; then - - # support old non-XDG download dir - MILL_OLD_DOWNLOAD_PATH="${HOME}/.mill/download" - OLD_MILL="${MILL_OLD_DOWNLOAD_PATH}/${MILL_VERSION}" - if [ -x "${OLD_MILL}" ] ; then - MILL="${OLD_MILL}" +if [ ! -s "${MILL}" ] || [ "$MILL_TEST_DRY_RUN_LAUNCHER_SCRIPT" = "1" ] ; then + case $MILL_VERSION in + 0.0.* | 0.1.* | 0.2.* | 0.3.* | 0.4.* ) + DOWNLOAD_SUFFIX="" + DOWNLOAD_FROM_MAVEN=0 + ;; + 0.5.* | 0.6.* | 0.7.* | 0.8.* | 0.9.* | 0.10.* | 0.11.0-M* ) + DOWNLOAD_SUFFIX="-assembly" + DOWNLOAD_FROM_MAVEN=0 + ;; + *) + DOWNLOAD_SUFFIX="-assembly" + DOWNLOAD_FROM_MAVEN=1 + ;; + esac + case $MILL_VERSION in + 0.12.0 | 0.12.1 | 0.12.2 | 0.12.3 | 0.12.4 | 0.12.5 | 0.12.6 | 0.12.7 | 0.12.8 | 0.12.9 | 0.12.10 | 0.12.11 ) + DOWNLOAD_EXT="jar" + ;; + 0.12.* ) + DOWNLOAD_EXT="exe" + ;; + 0.* ) + DOWNLOAD_EXT="jar" + ;; + *) + DOWNLOAD_EXT="exe" + ;; + esac + + DOWNLOAD_FILE=$(mktemp mill.XXXXXX) + if [ "$DOWNLOAD_FROM_MAVEN" = "1" ] ; then + DOWNLOAD_URL="https://repo1.maven.org/maven2/com/lihaoyi/mill-dist${ARTIFACT_SUFFIX}/${MILL_VERSION}/mill-dist${ARTIFACT_SUFFIX}-${MILL_VERSION}.${DOWNLOAD_EXT}" else - case $MILL_VERSION in - 0.0.* | 0.1.* | 0.2.* | 0.3.* | 0.4.* ) - DOWNLOAD_SUFFIX="" - DOWNLOAD_FROM_MAVEN=0 - ;; - 0.5.* | 0.6.* | 0.7.* | 0.8.* | 0.9.* | 0.10.* | 0.11.0-M* ) - DOWNLOAD_SUFFIX="-assembly" - DOWNLOAD_FROM_MAVEN=0 - ;; - *) - DOWNLOAD_SUFFIX="-assembly" - DOWNLOAD_FROM_MAVEN=1 - ;; - esac - - DOWNLOAD_FILE=$(mktemp mill.XXXXXX) - - if [ "$DOWNLOAD_FROM_MAVEN" = "1" ] ; then - DOWNLOAD_URL="https://repo1.maven.org/maven2/com/lihaoyi/mill-dist/${MILL_VERSION}/mill-dist-${MILL_VERSION}.jar" - else - MILL_VERSION_TAG=$(echo "$MILL_VERSION" | sed -E 's/([^-]+)(-M[0-9]+)?(-.*)?/\1\2/') - DOWNLOAD_URL="${GITHUB_RELEASE_CDN}${MILL_REPO_URL}/releases/download/${MILL_VERSION_TAG}/${MILL_VERSION}${DOWNLOAD_SUFFIX}" - unset MILL_VERSION_TAG - fi - - # TODO: handle command not found - echo "Downloading mill ${MILL_VERSION} from ${DOWNLOAD_URL} ..." 1>&2 - ${CURL_CMD} -f -L -o "${DOWNLOAD_FILE}" "${DOWNLOAD_URL}" - chmod +x "${DOWNLOAD_FILE}" - mkdir -p "${MILL_DOWNLOAD_PATH}" - mv "${DOWNLOAD_FILE}" "${MILL}" + MILL_VERSION_TAG=$(echo "$MILL_VERSION" | sed -E 's/([^-]+)(-M[0-9]+)?(-.*)?/\1\2/') + DOWNLOAD_URL="${GITHUB_RELEASE_CDN}${MILL_REPO_URL}/releases/download/${MILL_VERSION_TAG}/${MILL_VERSION}${DOWNLOAD_SUFFIX}" + unset MILL_VERSION_TAG + fi - unset DOWNLOAD_FILE - unset DOWNLOAD_SUFFIX + if [ "$MILL_TEST_DRY_RUN_LAUNCHER_SCRIPT" = "1" ] ; then + echo $DOWNLOAD_URL + echo $MILL + exit 0 fi + # TODO: handle command not found + echo "Downloading mill ${MILL_VERSION} from ${DOWNLOAD_URL} ..." 1>&2 + ${CURL_CMD} -f -L -o "${DOWNLOAD_FILE}" "${DOWNLOAD_URL}" + chmod +x "${DOWNLOAD_FILE}" + mkdir -p "${MILL_DOWNLOAD_PATH}" + mv "${DOWNLOAD_FILE}" "${MILL}" + + unset DOWNLOAD_FILE + unset DOWNLOAD_SUFFIX fi if [ -z "$MILL_MAIN_CLI" ] ; then @@ -224,7 +315,7 @@ if [ -z "$MILL_MAIN_CLI" ] ; then fi MILL_FIRST_ARG="" -if [ "$1" = "--bsp" ] || [ "$1" = "-i" ] || [ "$1" = "--interactive" ] || [ "$1" = "--no-server" ] || [ "$1" = "--repl" ] || [ "$1" = "--help" ] ; then +if [ "$1" = "--bsp" ] || [ "${1#"-i"}" != "$1" ] || [ "$1" = "--interactive" ] || [ "$1" = "--no-server" ] || [ "$1" = "--no-daemon" ] || [ "$1" = "--repl" ] || [ "$1" = "--help" ] ; then # Need to preserve the first position of those listed options MILL_FIRST_ARG=$1 shift @@ -236,6 +327,7 @@ unset OLD_MILL unset MILL_VERSION unset MILL_REPO_URL +# -D mill.main.cli is for compatibility with Mill 0.10.9 - 0.13.0-M2 # We don't quote MILL_FIRST_ARG on purpose, so we can expand the empty value without quotes # shellcheck disable=SC2086 -exec "${MILL}" $MILL_FIRST_ARG -D "mill.main.cli=${MILL_MAIN_CLI}" "$@" \ No newline at end of file +exec "${MILL}" $MILL_FIRST_ARG -D "mill.main.cli=${MILL_MAIN_CLI}" "$@" diff --git a/routes/package.mill b/routes/package.mill new file mode 100644 index 0000000..a29a1e3 --- /dev/null +++ b/routes/package.mill @@ -0,0 +1,26 @@ +package build.routes + +import build.* +import mill._ +import mill.scalalib._ +import mill.scalalib.publish._ + +object `package` extends FormatFixPublish { + + def scalaVersion: T[String] = V.scalaLts + + def mvnDeps = Seq( + mvn"org.http4s::http4s-core:${V.http4sVersion}", + mvn"org.http4s::http4s-client:${V.http4sVersion}", + mvn"org.http4s::http4s-server:${V.http4sVersion}", + mvn"org.http4s::http4s-dsl::${V.http4sVersion}", + mvn"com.outr::scribe-cats::3.15.0" + ) + + override def artifactName = "frontend-routes" + + object test extends Testy with ScalaTests{ + def mvnDeps = super.mvnDeps() ++ sjsls.mvnDeps() + } + +} \ No newline at end of file diff --git a/routes/src/app.route.scala b/routes/src/appRoute.scala similarity index 100% rename from routes/src/app.route.scala rename to routes/src/appRoute.scala diff --git a/routes/src/proxy.config.scala b/routes/src/proxyConfig.scala similarity index 100% rename from routes/src/proxy.config.scala rename to routes/src/proxyConfig.scala diff --git a/routes/src/proxy.http.scala b/routes/src/proxyHttp.scala similarity index 100% rename from routes/src/proxy.http.scala rename to routes/src/proxyHttp.scala diff --git a/routes/src/proxy.routes.scala b/routes/src/proxyRoutes.scala similarity index 100% rename from routes/src/proxy.routes.scala rename to routes/src/proxyRoutes.scala diff --git a/sjsls/package.mill b/sjsls/package.mill new file mode 100644 index 0000000..8b08ecb --- /dev/null +++ b/sjsls/package.mill @@ -0,0 +1,62 @@ +package build.sjsls + +import build.* +import mill.* +import mill.scalalib.* +import mill.scalajslib.* +import mill.scalalib.publish.* +import mill.contrib.buildinfo.BuildInfo +object `package` extends FormatFixPublish: + + override def scalaVersion = V.scalaLts + + def mvnDeps = super.mvnDeps() ++ Seq( + mvn"org.http4s::http4s-ember-server::${V.http4sVersion}", + mvn"org.http4s::http4s-ember-client::${V.http4sVersion}", + mvn"org.http4s::http4s-scalatags::0.25.2", + mvn"io.circe::circe-core::${V.circeVersion}", + mvn"io.circe::circe-generic::${V.circeVersion}", + mvn"co.fs2::fs2-io::3.11.0", + mvn"com.lihaoyi::scalatags::0.13.1", + mvn"com.monovore::decline::2.5.0", + mvn"com.monovore::decline-effect::2.5.0" + ) + + def moduleDeps = Seq(routes) + + def artifactName = "sjsls" + + object test extends Testy with ScalaTests with BuildInfo: + val name = "sjsls" + val buildInfoPackageName = "sjsls" + def buildInfoMembers = Seq( + BuildInfo.Value("laminar", V.laminar), + BuildInfo.Value("scalaJsDom", V.scalaJsDom), + BuildInfo.Value("scalaJsVersion", V.scalaJs), + BuildInfo.Value("scalaVersion", V.scalaLts) + ) + def mvnDeps = super.mvnDeps() ++ sjsls.mvnDeps() ++ Seq( + mvn"com.microsoft.playwright:playwright:${V.pwV}", + mvn"com.microsoft.playwright:driver-bundle:${V.pwV}" + ) + override def resources = super.resources + + override def runClasspath = Task { + sjsls.cacheJsLibs.resolvedMvnDeps() + super.runClasspath() + } + end test + + object cacheJsLibs extends ScalaJSModule: + def scalaVersion = V.scalaVersion + def scalaJSVersion = V.scalaJs + def testFramework = "munit.Framework" + def mvnDeps = super.mvnDeps() ++ Seq( + mvn"org.scala-js::scalajs-dom::${V.scalaJsDom}", + mvn"com.raquo::laminar::${V.laminar}" + ) + end cacheJsLibs + + + // def scalaNativeVersion = "0.4.17" // aspirational :-) +end `package` diff --git a/sjsls/src/build.runner.scala b/sjsls/src/buildRunner.scala similarity index 100% rename from sjsls/src/build.runner.scala rename to sjsls/src/buildRunner.scala diff --git a/sjsls/src/live.server.scala b/sjsls/src/liveServer.scala similarity index 94% rename from sjsls/src/live.server.scala rename to sjsls/src/liveServer.scala index b89ded1..483da60 100644 --- a/sjsls/src/live.server.scala +++ b/sjsls/src/liveServer.scala @@ -41,7 +41,7 @@ http: weight: 5 """ -case class CliValidationError(message: String) extends NoStackTrace +private case class CliValidationError(message: String) extends NoStackTrace object LiveServer extends IOApp: private val logger = scribe.cats[IO] @@ -53,7 +53,7 @@ object LiveServer extends IOApp: .withHost(host"localhost") .withPort(port) .withHttpApp(httpApp) - .withShutdownTimeout(10.milli) + .withShutdownTimeout(1.milli) .build val logLevelOpt: Opts[String] = Opts @@ -197,7 +197,8 @@ object LiveServer extends IOApp: stylesDir: Option[String] = None, indexHtmlTemplate: Option[String] = None, buildToolInvocation: Option[String] = None, - injectPreloads: Boolean = false + injectPreloads: Boolean = false, + customRefresh: Option[Topic[IO, Unit]] = None ) def parseOpts = ( @@ -216,7 +217,8 @@ object LiveServer extends IOApp: stylesDirOpt, indexHtmlTemplateOpt, buildToolInvocation, - injectPreloadsOpt + injectPreloadsOpt, + None.pure[Opts] ).mapN(LiveServerConfig.apply) def main(lsc: LiveServerConfig): Resource[IO, Server] = @@ -237,7 +239,7 @@ object LiveServer extends IOApp: .toResource fileToHashRef <- Ref[IO].of(Map.empty[String, String]).toResource - refreshTopic <- Topic[IO, Unit].toResource + refreshTopic <- lsc.customRefresh.fold(Topic[IO, Unit])(IO(_)).toResource linkingTopic <- Topic[IO, Unit].toResource client <- EmberClientBuilder.default[IO].build baseDirPath <- lsc.baseDir.fold(Files[IO].currentWorkingDirectory.toResource)(toDirectoryPath) @@ -320,17 +322,14 @@ object LiveServer extends IOApp: end main - def runServerHandleErrors: Opts[IO[ExitCode]] = parseOpts.map( - ops => - main(ops) - .useForever - .as(ExitCode.Success) - .handleErrorWith { - case CliValidationError(message) => - IO.println(s"${command.showHelp} \n $message \n see help above").as(ExitCode.Error) - case error => IO.raiseError(error) - } - ) + def runServerHandleErrors(lsc: LiveServerConfig): IO[ExitCode] = + main(lsc).useForever.as(ExitCode.Success) + + def runServerHandleErrors: Opts[IO[ExitCode]] = parseOpts.map(runServerHandleErrors(_).handleErrorWith { + case CliValidationError(message) => + IO.println(s"${command.showHelp} \n $message \n see help above").as(ExitCode.Error) + case error => IO.raiseError(error) + }) val command = val versionFlag = Opts.flag( diff --git a/sjsls/src/middleware/static.file.middleware.scala b/sjsls/src/middleware/staticFileMiddleware.scala similarity index 100% rename from sjsls/src/middleware/static.file.middleware.scala rename to sjsls/src/middleware/staticFileMiddleware.scala diff --git a/sjsls/src/middleware/static.path.middleware.scala b/sjsls/src/middleware/staticpathMiddleware.scala similarity index 100% rename from sjsls/src/middleware/static.path.middleware.scala rename to sjsls/src/middleware/staticpathMiddleware.scala diff --git a/sjsls/src/middleware/trace.logger.scala b/sjsls/src/middleware/traceLogger.scala similarity index 100% rename from sjsls/src/middleware/trace.logger.scala rename to sjsls/src/middleware/traceLogger.scala diff --git a/sjsls/src/open.browser.scala b/sjsls/src/openBrowser.scala similarity index 87% rename from sjsls/src/open.browser.scala rename to sjsls/src/openBrowser.scala index dfe0854..a1f376b 100644 --- a/sjsls/src/open.browser.scala +++ b/sjsls/src/openBrowser.scala @@ -11,7 +11,7 @@ import cats.effect.IO def openBrowser(openBrowserAt: Option[String], port: Port)(logger: Scribe[IO]): IO[Unit] = openBrowserAt match - case None => logger.trace("No openBrowserAt flag set, so no browser will be opened") + case None => logger.trace("No openBrowserAt flag set, so no browser will be opened") case Some(value) => val openAt = URI(s"http://localhost:$port$value") logger.info(s"Attempting to open browser to $openAt") >> diff --git a/sjsls/src/refresh.route.scala b/sjsls/src/refreshRoute.scala similarity index 100% rename from sjsls/src/refresh.route.scala rename to sjsls/src/refreshRoute.scala diff --git a/sjsls/src/sse.reload.scala b/sjsls/src/sseReload.scala similarity index 100% rename from sjsls/src/sse.reload.scala rename to sjsls/src/sseReload.scala diff --git a/sjsls/src/static.routes.scala b/sjsls/src/staticRoutes.scala similarity index 100% rename from sjsls/src/static.routes.scala rename to sjsls/src/staticRoutes.scala diff --git a/sjsls/src/static.watcher.scala b/sjsls/src/staticWatcher.scala similarity index 100% rename from sjsls/src/static.watcher.scala rename to sjsls/src/staticWatcher.scala diff --git a/sjsls/test/src/liveServer.test.scala b/sjsls/test/src/liveServer.test.scala index 73498a9..c969004 100644 --- a/sjsls/test/src/liveServer.test.scala +++ b/sjsls/test/src/liveServer.test.scala @@ -31,6 +31,7 @@ class FirefoxSuite extends PlaywrightTest: override def beforeAll(): Unit = basePort = 5000 + backendPort = 8999 pw = Playwright.create() browser = pw.firefox().launch(options); page = browser.newPage(); @@ -43,6 +44,7 @@ class SafariSuite extends PlaywrightTest: override def beforeAll(): Unit = basePort = 4000 + backendPort = 8998 pw = Playwright.create() browser = pw.webkit().launch(options); page = browser.newPage(); @@ -55,6 +57,7 @@ class ChromeSuite extends PlaywrightTest: override def beforeAll(): Unit = basePort = 3000 + backendPort = 8997 pw = Playwright.create() browser = pw.chromium().launch(options); page = browser.newPage(); @@ -66,6 +69,7 @@ end ChromeSuite trait PlaywrightTest extends CatsEffectSuite: var basePort: Int = uninitialized + var backendPort: Int = uninitialized var pw: Playwright = uninitialized var browser: Browser = uninitialized var page: Page = uninitialized @@ -108,9 +112,7 @@ trait PlaywrightTest extends CatsEffectSuite: val client = EmberClientBuilder.default[IO].build - val backendPort = 8999 - - val simpleBackend = EmberServerBuilder + def simpleBackend(port: Int) = EmberServerBuilder .default[IO] .withHttpApp( HttpRoutes @@ -120,7 +122,8 @@ trait PlaywrightTest extends CatsEffectSuite: } .orNotFound ) - .withPort(Port.fromInt(backendPort).get) + .withPort(Port.fromInt(port).get) + .withShutdownTimeout(1.millis) .build ResourceFunFixture { @@ -175,19 +178,17 @@ trait PlaywrightTest extends CatsEffectSuite: .both(client) .flatMap { (dir, client) => - val backendPort = 8999 - val lsc = LiveServerConfig( baseDir = Some(dir.toString), stylesDir = Some(styleDir(dir).toString), port = Port.fromInt(basePort).get, openBrowserAt = "", preventBrowserOpen = true, - proxyPortTarget = Port.fromInt(backendPort), + proxyPortTarget = Port.fromInt(backendPort), // Now uses class-level backendPort proxyPathMatchPrefix = Some("/api") ) - simpleBackend.flatMap { + simpleBackend(backendPort).flatMap { // Now uses class-level backendPort _ => LiveServer.main(lsc).map(_ => (lsc.port, client)) } @@ -225,7 +226,7 @@ trait PlaywrightTest extends CatsEffectSuite: logLevel = "info" ) - simpleBackend.flatMap { + simpleBackend(backendPort).flatMap { _ => LiveServer.main(lsc).map(_ => (lsc.port, client)) } @@ -306,8 +307,9 @@ trait PlaywrightTest extends CatsEffectSuite: client.expect[String](s"http://localhost:$basePort").map(out => out.contains("less.watch()")) ) >> assertIO( - client - .status(org.http4s.Request[IO](Method.GET, Uri.unsafeFromString(s"http://localhost:$basePort/index.less"))), + client.status( + org.http4s.Request[IO](Method.GET, Uri.unsafeFromString(s"http://localhost:$basePort/index.less")) + ), Ok ) } @@ -320,11 +322,12 @@ trait PlaywrightTest extends CatsEffectSuite: end PlaywrightTest def helloWorldCode(greet: String) = s""" -//> using scala 3.3.5 +//> using scala ${sjsls.BuildInfo.scalaVersion} //> using platform js +//> using jsVersion ${sjsls.BuildInfo.scalaJsVersion} -//> using dep org.scala-js::scalajs-dom::2.8.0 -//> using dep com.raquo::laminar::17.2.1 +//> using dep org.scala-js::scalajs-dom::${sjsls.BuildInfo.scalaJsDom} +//> using dep com.raquo::laminar::${sjsls.BuildInfo.laminar} //> using jsModuleKind es //> using jsModuleSplitStyleStr smallmodulesfor diff --git a/sjsls/test/src/test_extensions.scala b/sjsls/test/src/test_extensions.scala index fac0e9a..6d79c15 100644 --- a/sjsls/test/src/test_extensions.scala +++ b/sjsls/test/src/test_extensions.scala @@ -3,3 +3,4 @@ package io.github.quafadas.sjsls extension (path: os.Path) def toFs2: fs2.io.file.Path = fs2.io.file.Path.fromNioPath(path.toNIO) +end extension