From bf0f60cf5d47fccde333f18837cfad990e1c5a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Piaggio?= Date: Tue, 10 Dec 2024 17:55:36 -0300 Subject: [PATCH 1/6] add flake --- .envrc | 3 +++ .gitignore | 1 + flake.nix | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 .envrc create mode 100644 flake.nix diff --git a/.envrc b/.envrc new file mode 100644 index 000000000..3add3fcca --- /dev/null +++ b/.envrc @@ -0,0 +1,3 @@ +use flake +layout node +eval "$shellHook" diff --git a/.gitignore b/.gitignore index eabf4fd55..2336af8ef 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ metals.sbt node_modules/ package-lock.json target +.direnv/ diff --git a/flake.nix b/flake.nix new file mode 100644 index 000000000..5855f5f2f --- /dev/null +++ b/flake.nix @@ -0,0 +1,43 @@ +{ + inputs = { + typelevel-nix.url = "github:typelevel/typelevel-nix"; + nixpkgs.follows = "typelevel-nix/nixpkgs"; + flake-utils.follows = "typelevel-nix/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils, typelevel-nix }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs-x86_64 = import nixpkgs { system = "x86_64-darwin"; }; + scala-cli-overlay = final: prev: { scala-cli = pkgs-x86_64.scala-cli; }; + pkgs = import nixpkgs { + inherit system; + overlays = [ typelevel-nix.overlays.default scala-cli-overlay]; + }; + in + { + devShell = pkgs.devshell.mkShell { + imports = [ typelevel-nix.typelevelShell ]; + packages = [ + pkgs.nodePackages.typescript-language-server + pkgs.nodePackages.vscode-langservers-extracted + pkgs.nodePackages.prettier + pkgs.nodePackages.typescript + pkgs.nodePackages.graphqurl + pkgs.hasura-cli + ]; + typelevelShell = { + nodejs.enable = true; + jdk.package = pkgs.jdk21; + }; + env = [ + { + name = "NODE_OPTIONS"; + value = "--max-old-space-size=8192"; + } + ]; + }; + } + + ); +} From 080b9370a938444caee7211e190097a47309b46f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Piaggio?= Date: Tue, 10 Dec 2024 19:35:57 -0300 Subject: [PATCH 2/6] first steps toward extensible parser for router --- flake.lock | 109 ++++++++++++++++++ .../scalajs/react/extra/router/Dsl.scala | 21 ++-- 2 files changed, 123 insertions(+), 7 deletions(-) create mode 100644 flake.lock diff --git a/flake.lock b/flake.lock new file mode 100644 index 000000000..055567cf7 --- /dev/null +++ b/flake.lock @@ -0,0 +1,109 @@ +{ + "nodes": { + "devshell": { + "inputs": { + "nixpkgs": [ + "typelevel-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1728330715, + "narHash": "sha256-xRJ2nPOXb//u1jaBnDP56M7v5ldavjbtR6lfGqSvcKg=", + "owner": "numtide", + "repo": "devshell", + "rev": "dd6b80932022cea34a019e2bb32f6fa9e494dfef", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1733376361, + "narHash": "sha256-aLJxoTDDSqB+/3orsulE6/qdlX6MzDLIITLZqdgMpqo=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "929116e316068c7318c54eb4d827f7d9756d5e9c", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": [ + "typelevel-nix", + "flake-utils" + ], + "nixpkgs": [ + "typelevel-nix", + "nixpkgs" + ], + "typelevel-nix": "typelevel-nix" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "typelevel-nix": { + "inputs": { + "devshell": "devshell", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1733783241, + "narHash": "sha256-nDM0W3EhiVJDFPCInPzJ9+QUyyjMTZhlTK8JGN7vfJQ=", + "owner": "typelevel", + "repo": "typelevel-nix", + "rev": "a4a46f0b1b94e150a1dda0a8f0f013696d9299fd", + "type": "github" + }, + "original": { + "owner": "typelevel", + "repo": "typelevel-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/library/extra/src/main/scala/japgolly/scalajs/react/extra/router/Dsl.scala b/library/extra/src/main/scala/japgolly/scalajs/react/extra/router/Dsl.scala index bc9aa8aed..7bd7ef062 100644 --- a/library/extra/src/main/scala/japgolly/scalajs/react/extra/router/Dsl.scala +++ b/library/extra/src/main/scala/japgolly/scalajs/react/extra/router/Dsl.scala @@ -87,7 +87,7 @@ object StaticDsl { val / = literal("/") } - abstract class RouteCommon[R[X] <: RouteCommon[R, X], A] { + trait RouteCommon[R[X] <: RouteCommon[R, X], A] { def parseThen(f: Option[A] => Option[A]): R[A] @@ -159,7 +159,7 @@ object StaticDsl { // val g = p.matcher("").groupCount // if (g != matchGroups) // sys.error(s"Error in regex: /${p.pattern}/. Expected $matchGroups match groups but detected $g.") - new Route(p, m => parse(i => m.group(i + 1)), a => Path(build(a))) + new RegexRoute(p, m => parse(i => m.group(i + 1)), a => Path(build(a))) } } @@ -191,20 +191,27 @@ object StaticDsl { r.xmap(_ getOrElse default)(a => if (default == a) None else Some(a)) } + trait Route[A] extends RouteCommon[Route, A] { + def parse(path: Path): Option[A] + def pathFor(a: A): Path + } + /** * A complete route. */ - final class Route[A](pattern: Pattern, - parseFn: Matcher => Option[A], - buildFn: A => Path) extends RouteCommon[Route, A] with RouterMacros.ForRoute[A] { + final class RegexRoute[A]( + pattern: Pattern, + parseFn: Matcher => Option[A], + buildFn: A => Path + ) extends Route[A] with RouterMacros.ForRoute[A] { override def toString = s"Route($pattern)" override def parseThen(f: Option[A] => Option[A]): Route[A] = - new Route(pattern, f compose parseFn, buildFn) + new RegexRoute(pattern, f compose parseFn, buildFn) override def pmap[B](b: A => Option[B])(a: B => A): Route[B] = - new Route(pattern, parseFn(_) flatMap b, buildFn compose a) + new RegexRoute(pattern, parseFn(_) flatMap b, buildFn compose a) def parse(path: Path): Option[A] = { val m = pattern.matcher(path.value) From 08650436af6d28f02f408d42008bc1fe9f0cac91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Piaggio?= Date: Wed, 11 Dec 2024 11:18:43 -0300 Subject: [PATCH 3/6] flexible route model --- .../main/scala/japgolly/scalajs/react/extra/router/Dsl.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/extra/src/main/scala/japgolly/scalajs/react/extra/router/Dsl.scala b/library/extra/src/main/scala/japgolly/scalajs/react/extra/router/Dsl.scala index 7bd7ef062..c285b2c46 100644 --- a/library/extra/src/main/scala/japgolly/scalajs/react/extra/router/Dsl.scala +++ b/library/extra/src/main/scala/japgolly/scalajs/react/extra/router/Dsl.scala @@ -191,6 +191,9 @@ object StaticDsl { r.xmap(_ getOrElse default)(a => if (default == a) None else Some(a)) } + /** + * Translates a `Path` into an instance of model `A` and vice versa. + */ trait Route[A] extends RouteCommon[Route, A] { def parse(path: Path): Option[A] def pathFor(a: A): Path From 2c028fc4bbdda655dc2cdb4923085b7cab285089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Piaggio?= Date: Wed, 11 Dec 2024 16:49:50 -0300 Subject: [PATCH 4/6] update versions, dial back jdk --- flake.nix | 2 +- .../react/callback/CallbackOption.scala | 4 ++-- .../scalajs/react/callback/CallbackTo.scala | 6 +++--- library/project/Dependencies.scala | 20 +++++++++---------- library/project/plugins.sbt | 4 ++-- library/scalafix.sbt | 2 +- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/flake.nix b/flake.nix index 5855f5f2f..e6885acf5 100644 --- a/flake.nix +++ b/flake.nix @@ -28,7 +28,7 @@ ]; typelevelShell = { nodejs.enable = true; - jdk.package = pkgs.jdk21; + jdk.package = pkgs.jdk11; }; env = [ { diff --git a/library/callback/src/main/scala-3/japgolly/scalajs/react/callback/CallbackOption.scala b/library/callback/src/main/scala-3/japgolly/scalajs/react/callback/CallbackOption.scala index 0948c371c..5120167c3 100644 --- a/library/callback/src/main/scala-3/japgolly/scalajs/react/callback/CallbackOption.scala +++ b/library/callback/src/main/scala-3/japgolly/scalajs/react/callback/CallbackOption.scala @@ -183,7 +183,7 @@ final class CallbackOption[+A](val underlyingRepr: CallbackOption.UnderlyingRepr def asCallback: CallbackTo[Option[A]] = CallbackTo lift cbfn - inline def map[B](f: A => B)(using inline ev: MapGuard[B]): CallbackOption[ev.Out] = + inline def map[B](f: A => B)(using ev: MapGuard[B]): CallbackOption[ev.Out] = unsafeMap(f) private[react] def unsafeMap[B](f: A => B): CallbackOption[B] = @@ -192,7 +192,7 @@ final class CallbackOption[+A](val underlyingRepr: CallbackOption.UnderlyingRepr /** * Alias for `map`. */ - inline def |>[B](f: A => B)(using inline ev: MapGuard[B]): CallbackOption[ev.Out] = + inline def |>[B](f: A => B)(using ev: MapGuard[B]): CallbackOption[ev.Out] = map(f) def flatMapOption[B](f: A => Option[B]): CallbackOption[B] = diff --git a/library/callback/src/main/scala-3/japgolly/scalajs/react/callback/CallbackTo.scala b/library/callback/src/main/scala-3/japgolly/scalajs/react/callback/CallbackTo.scala index 1a80ef18c..4863c657c 100644 --- a/library/callback/src/main/scala-3/japgolly/scalajs/react/callback/CallbackTo.scala +++ b/library/callback/src/main/scala-3/japgolly/scalajs/react/callback/CallbackTo.scala @@ -306,11 +306,11 @@ final class CallbackTo[+A] /*private[react]*/ (private[CallbackTo] val trampolin inline def runNow(): A = trampoline.run - inline def map[B](f: A => B)(using inline ev: MapGuard[B]): CallbackTo[ev.Out] = + inline def map[B](f: A => B)(using ev: MapGuard[B]): CallbackTo[ev.Out] = new CallbackTo(trampoline.map(f)) /** Alias for `map`. */ - inline def |>[B](inline f: A => B)(using inline ev: MapGuard[B]): CallbackTo[ev.Out] = + inline def |>[B](inline f: A => B)(using ev: MapGuard[B]): CallbackTo[ev.Out] = map(f) inline def flatMap[B](f: A => CallbackTo[B]): CallbackTo[B] = @@ -589,7 +589,7 @@ final class CallbackTo[+A] /*private[react]*/ (private[CallbackTo] val trampolin /** Convenience-method to run additional code after this callback. */ - inline def thenRun[B](inline runNext: B)(using inline ev: MapGuard[B]): CallbackTo[ev.Out] = + inline def thenRun[B](inline runNext: B)(using ev: MapGuard[B]): CallbackTo[ev.Out] = this >> CallbackTo(runNext) /** Convenience-method to run additional code before this callback. */ diff --git a/library/project/Dependencies.scala b/library/project/Dependencies.scala index d48d315d0..4f34f87f8 100644 --- a/library/project/Dependencies.scala +++ b/library/project/Dependencies.scala @@ -9,23 +9,23 @@ object Dependencies { object Ver { // Externally observable - val cats = "2.7.0" - val catsEffect = "3.3.11" - val microlibs = "4.2.1" + val cats = "2.12.0" + val catsEffect = "3.5.4" + val microlibs = "4.1.0" val monocle2 = "2.1.0" - val monocle3 = "3.1.0" - val scala2 = "2.13.8" - val scala3 = "3.1.2" - val scalaJsDom = "2.0.0" - val sourcecode = "0.2.8" + val monocle3 = "3.2.0" + val scala2 = "2.13.14" + val scala3 = "3.3.0" + val scalaJsDom = "2.8.0" + val sourcecode = "0.4.2" // Internal val betterMonadicFor = "0.3.1" val catsTestkitScalaTest = "2.1.5" val disciplineScalaTest = "2.1.5" val fastTextEncoding = "1.0.6" - val kindProjector = "0.13.2" - val macrotaskExecutor = "1.0.0" + val kindProjector = "0.13.3" + val macrotaskExecutor = "1.1.1" val nyaya = "1.0.0" val reactJs = "18.2.0" val scalaJsJavaTime = "1.0.0" diff --git a/library/project/plugins.sbt b/library/project/plugins.sbt index 0d5f5d427..29f96510d 100644 --- a/library/project/plugins.sbt +++ b/library/project/plugins.sbt @@ -2,7 +2,7 @@ libraryDependencies ++= Seq( "org.scala-js" %% "scalajs-env-jsdom-nodejs" % "1.1.0", "org.scala-js" %% "scalajs-env-selenium" % "1.1.1") -addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.10.1") -addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.10") +addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.12.1") +addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.12") addSbtPlugin("org.scala-js" % "sbt-jsdependencies" % "1.0.2") addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0") diff --git a/library/scalafix.sbt b/library/scalafix.sbt index fbe1c58c3..69d935353 100644 --- a/library/scalafix.sbt +++ b/library/scalafix.sbt @@ -8,4 +8,4 @@ ThisBuild / scalacOptions ++= { ThisBuild / semanticdbEnabled := true // NOTE: Upgrade downstream-tests/scalafix.sbt too! -ThisBuild / semanticdbVersion := "4.5.9" +ThisBuild / semanticdbVersion := "4.9.8" From cf15d1fb778eec989056fb2c6d00c6f35001ce1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Piaggio?= Date: Wed, 11 Dec 2024 17:17:17 -0300 Subject: [PATCH 5/6] even more flexible route --- .../scalajs/react/extra/router/Dsl.scala | 48 +++++++------------ library/project/Dependencies.scala | 2 +- 2 files changed, 19 insertions(+), 31 deletions(-) diff --git a/library/extra/src/main/scala/japgolly/scalajs/react/extra/router/Dsl.scala b/library/extra/src/main/scala/japgolly/scalajs/react/extra/router/Dsl.scala index c285b2c46..fcf185d3d 100644 --- a/library/extra/src/main/scala/japgolly/scalajs/react/extra/router/Dsl.scala +++ b/library/extra/src/main/scala/japgolly/scalajs/react/extra/router/Dsl.scala @@ -159,7 +159,7 @@ object StaticDsl { // val g = p.matcher("").groupCount // if (g != matchGroups) // sys.error(s"Error in regex: /${p.pattern}/. Expected $matchGroups match groups but detected $g.") - new RegexRoute(p, m => parse(i => m.group(i + 1)), a => Path(build(a))) + Route.forPattern(p, m => parse(i => m.group(i + 1)), a => Path(build(a))) } } @@ -192,40 +192,28 @@ object StaticDsl { } /** - * Translates a `Path` into an instance of model `A` and vice versa. + * A `Route` translates a `Path` into an instance of model `A` and vice versa. */ - trait Route[A] extends RouteCommon[Route, A] { - def parse(path: Path): Option[A] - def pathFor(a: A): Path - } - - /** - * A complete route. - */ - final class RegexRoute[A]( - pattern: Pattern, - parseFn: Matcher => Option[A], - buildFn: A => Path - ) extends Route[A] with RouterMacros.ForRoute[A] { - override def toString = - s"Route($pattern)" - + case class Route[A](parse: Path => Option[A], pathFor: A => Path) extends RouteCommon[Route, A] { override def parseThen(f: Option[A] => Option[A]): Route[A] = - new RegexRoute(pattern, f compose parseFn, buildFn) + Route(f compose parse, pathFor) override def pmap[B](b: A => Option[B])(a: B => A): Route[B] = - new RegexRoute(pattern, parseFn(_) flatMap b, buildFn compose a) - - def parse(path: Path): Option[A] = { - val m = pattern.matcher(path.value) - if (m.matches) - parseFn(m) - else - None - } + Route(parse(_) flatMap b, pathFor compose a) + } - def pathFor(a: A): Path = - buildFn(a) + object Route { + def forPattern[A](pattern: Pattern, parseFn: Matcher => Option[A], buildFn: A => Path): Route[A] = + new Route( + p => { + val m = pattern.matcher(p.value) + if (m.matches) + parseFn(m) + else + None + }, + buildFn + ) } // =================================================================================================================== diff --git a/library/project/Dependencies.scala b/library/project/Dependencies.scala index 4f34f87f8..821296cfc 100644 --- a/library/project/Dependencies.scala +++ b/library/project/Dependencies.scala @@ -14,7 +14,7 @@ object Dependencies { val microlibs = "4.1.0" val monocle2 = "2.1.0" val monocle3 = "3.2.0" - val scala2 = "2.13.14" + val scala2 = "2.13.15" val scala3 = "3.3.0" val scalaJsDom = "2.8.0" val sourcecode = "0.4.2" From 83ad0d1cad7e69a7adadc5b83d39b42980386928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Piaggio?= Date: Wed, 11 Dec 2024 21:05:41 -0300 Subject: [PATCH 6/6] bump semanticdb --- downstream-tests/scalafix.sbt | 2 +- library/scalafix.sbt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/downstream-tests/scalafix.sbt b/downstream-tests/scalafix.sbt index 094b38fc1..3515f51a1 100644 --- a/downstream-tests/scalafix.sbt +++ b/downstream-tests/scalafix.sbt @@ -10,7 +10,7 @@ ThisBuild / scalacOptions ++= { ThisBuild / semanticdbEnabled := true -ThisBuild / semanticdbVersion := "4.5.9" +ThisBuild / semanticdbVersion := "4.12.0" ThisBuild / scalafixScalaBinaryVersion := "2.13" diff --git a/library/scalafix.sbt b/library/scalafix.sbt index 69d935353..14bc20874 100644 --- a/library/scalafix.sbt +++ b/library/scalafix.sbt @@ -8,4 +8,4 @@ ThisBuild / scalacOptions ++= { ThisBuild / semanticdbEnabled := true // NOTE: Upgrade downstream-tests/scalafix.sbt too! -ThisBuild / semanticdbVersion := "4.9.8" +ThisBuild / semanticdbVersion := "4.12.0"