diff --git a/build.sbt b/build.sbt index f0fe88f..ee4de1d 100644 --- a/build.sbt +++ b/build.sbt @@ -4,6 +4,9 @@ publishToIW +lazy val fixSilencerDoc = + libraryDependencies += "com.github.ghik" %% "silencer-lib" % "1.4.2" % Provided cross CrossVersion.for3Use2_13 + lazy val core = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Full) .settings(name := "iw-support-core") @@ -51,17 +54,21 @@ lazy val `mongo-support` = project .in(file("mongo")) - .configs(IntegrationTest) .settings(name := "iw-support-mongo") .settings( - Defaults.itSettings, - IWDeps.useZIO(Test, IntegrationTest), + fixSilencerDoc, + IWDeps.useZIO(), IWDeps.useZIOJson, IWDeps.zioConfig, libraryDependencies += ("org.mongodb.scala" %% "mongo-scala-driver" % "4.2.3") .cross(CrossVersion.for3Use2_13) ) +lazy val `mongo-support-it` = project + .in(file("mongo/it")) + .settings(publish / skip := true) + .dependsOn(`mongo-support`) + lazy val `akka-persistence-support` = project .in(file("akka-persistence")) .settings(name := "iw-support-akka-persistence") @@ -98,6 +105,29 @@ ) .dependsOn(core) +lazy val http = (project in file("server/http")) + .settings(name := "iw-support-server-http") + .settings( + fixSilencerDoc, + IWDeps.useZIO(), + IWDeps.zioConfig, + IWDeps.zioConfigTypesafe, + IWDeps.zioConfigMagnolia, + IWDeps.zioLoggingSlf4j, + // TODO: use IWDeps.zioInteropCats with next iw-support version (0.3.19+) + libraryDependencies += "dev.zio" %% "zio-interop-cats" % "23.0.0.8", + IWDeps.tapirCore, + IWDeps.tapirZIO, + IWDeps.tapirZIOJson, + IWDeps.tapirLib("files"), + IWDeps.tapirZIOHttp4sServer, + IWDeps.http4sBlazeServer, + IWDeps.http4sPac4J, + IWDeps.pac4jOIDC, + IWDeps.logbackClassic + ) + .dependsOn(core.jvm, codecs.jvm, `tapir-support`.jvm) + lazy val root = (project in file(".")) .enablePlugins(IWScalaProjectPlugin) .settings( @@ -114,5 +144,6 @@ `mongo-support`, `akka-persistence-support`, ui.js, - ui.jvm + ui.jvm, + http ) diff --git a/build.sbt b/build.sbt index f0fe88f..ee4de1d 100644 --- a/build.sbt +++ b/build.sbt @@ -4,6 +4,9 @@ publishToIW +lazy val fixSilencerDoc = + libraryDependencies += "com.github.ghik" %% "silencer-lib" % "1.4.2" % Provided cross CrossVersion.for3Use2_13 + lazy val core = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Full) .settings(name := "iw-support-core") @@ -51,17 +54,21 @@ lazy val `mongo-support` = project .in(file("mongo")) - .configs(IntegrationTest) .settings(name := "iw-support-mongo") .settings( - Defaults.itSettings, - IWDeps.useZIO(Test, IntegrationTest), + fixSilencerDoc, + IWDeps.useZIO(), IWDeps.useZIOJson, IWDeps.zioConfig, libraryDependencies += ("org.mongodb.scala" %% "mongo-scala-driver" % "4.2.3") .cross(CrossVersion.for3Use2_13) ) +lazy val `mongo-support-it` = project + .in(file("mongo/it")) + .settings(publish / skip := true) + .dependsOn(`mongo-support`) + lazy val `akka-persistence-support` = project .in(file("akka-persistence")) .settings(name := "iw-support-akka-persistence") @@ -98,6 +105,29 @@ ) .dependsOn(core) +lazy val http = (project in file("server/http")) + .settings(name := "iw-support-server-http") + .settings( + fixSilencerDoc, + IWDeps.useZIO(), + IWDeps.zioConfig, + IWDeps.zioConfigTypesafe, + IWDeps.zioConfigMagnolia, + IWDeps.zioLoggingSlf4j, + // TODO: use IWDeps.zioInteropCats with next iw-support version (0.3.19+) + libraryDependencies += "dev.zio" %% "zio-interop-cats" % "23.0.0.8", + IWDeps.tapirCore, + IWDeps.tapirZIO, + IWDeps.tapirZIOJson, + IWDeps.tapirLib("files"), + IWDeps.tapirZIOHttp4sServer, + IWDeps.http4sBlazeServer, + IWDeps.http4sPac4J, + IWDeps.pac4jOIDC, + IWDeps.logbackClassic + ) + .dependsOn(core.jvm, codecs.jvm, `tapir-support`.jvm) + lazy val root = (project in file(".")) .enablePlugins(IWScalaProjectPlugin) .settings( @@ -114,5 +144,6 @@ `mongo-support`, `akka-persistence-support`, ui.js, - ui.jvm + ui.jvm, + http ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..467dd17 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala @@ -0,0 +1,48 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonFileRepositoryIntegrationSpec extends ZIOSpecDefault: + case class ExampleMetadata(osobniCislo: String) + sealed trait ExampleCriteria + case class ByOsobniCislo(osobniCislo: String) extends ExampleCriteria + + given JsonCodec[ExampleMetadata] = DeriveJsonCodec.gen + + override def spec = suite("Mongo file repository integration spec")( + test("repo can put and read back file")( + for + repo <- ZIO + .service[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] + fname = "Příliš žluťoučký kůň úpěl ďábelské ódy.txt" + _ <- repo.put( + fname, + "Example content".getBytes(), + ExampleMetadata("10123") + ) + result <- repo.matching(ByOsobniCislo("10123")) + yield assertTrue(result.head.name == fname) + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer + : TaskLayer[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.mongodb.scala.gridfs.GridFSBucket + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer( + for + client <- ZIO.service[MongoClient] + bucket <- ZIO.attempt( + GridFSBucket(client.getDatabase("test"), "testfiles") + ) + yield new MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]( + bucket, { + _ match + case ByOsobniCislo(osc) => equal("metadata.osobniCislo", osc) + } + ) + ) diff --git a/build.sbt b/build.sbt index f0fe88f..ee4de1d 100644 --- a/build.sbt +++ b/build.sbt @@ -4,6 +4,9 @@ publishToIW +lazy val fixSilencerDoc = + libraryDependencies += "com.github.ghik" %% "silencer-lib" % "1.4.2" % Provided cross CrossVersion.for3Use2_13 + lazy val core = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Full) .settings(name := "iw-support-core") @@ -51,17 +54,21 @@ lazy val `mongo-support` = project .in(file("mongo")) - .configs(IntegrationTest) .settings(name := "iw-support-mongo") .settings( - Defaults.itSettings, - IWDeps.useZIO(Test, IntegrationTest), + fixSilencerDoc, + IWDeps.useZIO(), IWDeps.useZIOJson, IWDeps.zioConfig, libraryDependencies += ("org.mongodb.scala" %% "mongo-scala-driver" % "4.2.3") .cross(CrossVersion.for3Use2_13) ) +lazy val `mongo-support-it` = project + .in(file("mongo/it")) + .settings(publish / skip := true) + .dependsOn(`mongo-support`) + lazy val `akka-persistence-support` = project .in(file("akka-persistence")) .settings(name := "iw-support-akka-persistence") @@ -98,6 +105,29 @@ ) .dependsOn(core) +lazy val http = (project in file("server/http")) + .settings(name := "iw-support-server-http") + .settings( + fixSilencerDoc, + IWDeps.useZIO(), + IWDeps.zioConfig, + IWDeps.zioConfigTypesafe, + IWDeps.zioConfigMagnolia, + IWDeps.zioLoggingSlf4j, + // TODO: use IWDeps.zioInteropCats with next iw-support version (0.3.19+) + libraryDependencies += "dev.zio" %% "zio-interop-cats" % "23.0.0.8", + IWDeps.tapirCore, + IWDeps.tapirZIO, + IWDeps.tapirZIOJson, + IWDeps.tapirLib("files"), + IWDeps.tapirZIOHttp4sServer, + IWDeps.http4sBlazeServer, + IWDeps.http4sPac4J, + IWDeps.pac4jOIDC, + IWDeps.logbackClassic + ) + .dependsOn(core.jvm, codecs.jvm, `tapir-support`.jvm) + lazy val root = (project in file(".")) .enablePlugins(IWScalaProjectPlugin) .settings( @@ -114,5 +144,6 @@ `mongo-support`, `akka-persistence-support`, ui.js, - ui.jvm + ui.jvm, + http ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..467dd17 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala @@ -0,0 +1,48 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonFileRepositoryIntegrationSpec extends ZIOSpecDefault: + case class ExampleMetadata(osobniCislo: String) + sealed trait ExampleCriteria + case class ByOsobniCislo(osobniCislo: String) extends ExampleCriteria + + given JsonCodec[ExampleMetadata] = DeriveJsonCodec.gen + + override def spec = suite("Mongo file repository integration spec")( + test("repo can put and read back file")( + for + repo <- ZIO + .service[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] + fname = "Příliš žluťoučký kůň úpěl ďábelské ódy.txt" + _ <- repo.put( + fname, + "Example content".getBytes(), + ExampleMetadata("10123") + ) + result <- repo.matching(ByOsobniCislo("10123")) + yield assertTrue(result.head.name == fname) + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer + : TaskLayer[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.mongodb.scala.gridfs.GridFSBucket + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer( + for + client <- ZIO.service[MongoClient] + bucket <- ZIO.attempt( + GridFSBucket(client.getDatabase("test"), "testfiles") + ) + yield new MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]( + bucket, { + _ match + case ByOsobniCislo(osc) => equal("metadata.osobniCislo", osc) + } + ) + ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..56ad2c3 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala @@ -0,0 +1,46 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonRepositoryIntegrationSpec extends ZIOSpecDefault: + case class Example(id: String, value: String) + sealed trait ExampleCriteria + case object All extends ExampleCriteria + case class ById(id: String) extends ExampleCriteria + + given JsonCodec[Example] = DeriveJsonCodec.gen + + override def spec = suite("Mongo repository integration spec")( + test("repo can put and read back")( + for + repo <- ZIO + .service[MongoJsonRepository[Example, String, ExampleCriteria]] + _ <- repo.put(Example("1", "test")) + result <- repo.matching(ById("1")) + yield assertTrue(result.head.value == "test") + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer: TaskLayer[MongoJsonRepository[Example, String, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.bson.json.JsonObject + import org.mongodb.scala.bson.Document + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer { + (for + client <- ZIO.service[MongoClient] + coll <- ZIO.attempt( + client.getDatabase("test").getCollection[JsonObject]("example") + ) + yield new MongoJsonRepository[Example, String, ExampleCriteria]( + coll, { + _ match + case ById(id) => equal("id", id) + case All => Document() + }, + e => ("id", e.id) + )) + } diff --git a/build.sbt b/build.sbt index f0fe88f..ee4de1d 100644 --- a/build.sbt +++ b/build.sbt @@ -4,6 +4,9 @@ publishToIW +lazy val fixSilencerDoc = + libraryDependencies += "com.github.ghik" %% "silencer-lib" % "1.4.2" % Provided cross CrossVersion.for3Use2_13 + lazy val core = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Full) .settings(name := "iw-support-core") @@ -51,17 +54,21 @@ lazy val `mongo-support` = project .in(file("mongo")) - .configs(IntegrationTest) .settings(name := "iw-support-mongo") .settings( - Defaults.itSettings, - IWDeps.useZIO(Test, IntegrationTest), + fixSilencerDoc, + IWDeps.useZIO(), IWDeps.useZIOJson, IWDeps.zioConfig, libraryDependencies += ("org.mongodb.scala" %% "mongo-scala-driver" % "4.2.3") .cross(CrossVersion.for3Use2_13) ) +lazy val `mongo-support-it` = project + .in(file("mongo/it")) + .settings(publish / skip := true) + .dependsOn(`mongo-support`) + lazy val `akka-persistence-support` = project .in(file("akka-persistence")) .settings(name := "iw-support-akka-persistence") @@ -98,6 +105,29 @@ ) .dependsOn(core) +lazy val http = (project in file("server/http")) + .settings(name := "iw-support-server-http") + .settings( + fixSilencerDoc, + IWDeps.useZIO(), + IWDeps.zioConfig, + IWDeps.zioConfigTypesafe, + IWDeps.zioConfigMagnolia, + IWDeps.zioLoggingSlf4j, + // TODO: use IWDeps.zioInteropCats with next iw-support version (0.3.19+) + libraryDependencies += "dev.zio" %% "zio-interop-cats" % "23.0.0.8", + IWDeps.tapirCore, + IWDeps.tapirZIO, + IWDeps.tapirZIOJson, + IWDeps.tapirLib("files"), + IWDeps.tapirZIOHttp4sServer, + IWDeps.http4sBlazeServer, + IWDeps.http4sPac4J, + IWDeps.pac4jOIDC, + IWDeps.logbackClassic + ) + .dependsOn(core.jvm, codecs.jvm, `tapir-support`.jvm) + lazy val root = (project in file(".")) .enablePlugins(IWScalaProjectPlugin) .settings( @@ -114,5 +144,6 @@ `mongo-support`, `akka-persistence-support`, ui.js, - ui.jvm + ui.jvm, + http ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..467dd17 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala @@ -0,0 +1,48 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonFileRepositoryIntegrationSpec extends ZIOSpecDefault: + case class ExampleMetadata(osobniCislo: String) + sealed trait ExampleCriteria + case class ByOsobniCislo(osobniCislo: String) extends ExampleCriteria + + given JsonCodec[ExampleMetadata] = DeriveJsonCodec.gen + + override def spec = suite("Mongo file repository integration spec")( + test("repo can put and read back file")( + for + repo <- ZIO + .service[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] + fname = "Příliš žluťoučký kůň úpěl ďábelské ódy.txt" + _ <- repo.put( + fname, + "Example content".getBytes(), + ExampleMetadata("10123") + ) + result <- repo.matching(ByOsobniCislo("10123")) + yield assertTrue(result.head.name == fname) + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer + : TaskLayer[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.mongodb.scala.gridfs.GridFSBucket + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer( + for + client <- ZIO.service[MongoClient] + bucket <- ZIO.attempt( + GridFSBucket(client.getDatabase("test"), "testfiles") + ) + yield new MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]( + bucket, { + _ match + case ByOsobniCislo(osc) => equal("metadata.osobniCislo", osc) + } + ) + ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..56ad2c3 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala @@ -0,0 +1,46 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonRepositoryIntegrationSpec extends ZIOSpecDefault: + case class Example(id: String, value: String) + sealed trait ExampleCriteria + case object All extends ExampleCriteria + case class ById(id: String) extends ExampleCriteria + + given JsonCodec[Example] = DeriveJsonCodec.gen + + override def spec = suite("Mongo repository integration spec")( + test("repo can put and read back")( + for + repo <- ZIO + .service[MongoJsonRepository[Example, String, ExampleCriteria]] + _ <- repo.put(Example("1", "test")) + result <- repo.matching(ById("1")) + yield assertTrue(result.head.value == "test") + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer: TaskLayer[MongoJsonRepository[Example, String, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.bson.json.JsonObject + import org.mongodb.scala.bson.Document + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer { + (for + client <- ZIO.service[MongoClient] + coll <- ZIO.attempt( + client.getDatabase("test").getCollection[JsonObject]("example") + ) + yield new MongoJsonRepository[Example, String, ExampleCriteria]( + coll, { + _ match + case ById(id) => equal("id", id) + case All => Document() + }, + e => ("id", e.id) + )) + } diff --git a/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala b/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala deleted file mode 100644 index 467dd17..0000000 --- a/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala +++ /dev/null @@ -1,48 +0,0 @@ -package works.iterative.mongo - -import zio.* -import zio.test.* -import zio.json.* -import Assertion.* - -object MongoJsonFileRepositoryIntegrationSpec extends ZIOSpecDefault: - case class ExampleMetadata(osobniCislo: String) - sealed trait ExampleCriteria - case class ByOsobniCislo(osobniCislo: String) extends ExampleCriteria - - given JsonCodec[ExampleMetadata] = DeriveJsonCodec.gen - - override def spec = suite("Mongo file repository integration spec")( - test("repo can put and read back file")( - for - repo <- ZIO - .service[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] - fname = "Příliš žluťoučký kůň úpěl ďábelské ódy.txt" - _ <- repo.put( - fname, - "Example content".getBytes(), - ExampleMetadata("10123") - ) - result <- repo.matching(ByOsobniCislo("10123")) - yield assertTrue(result.head.name == fname) - ) - ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") - - val layer - : TaskLayer[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] = - import org.mongodb.scala.* - import org.mongodb.scala.model.Filters.* - import org.mongodb.scala.gridfs.GridFSBucket - MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer( - for - client <- ZIO.service[MongoClient] - bucket <- ZIO.attempt( - GridFSBucket(client.getDatabase("test"), "testfiles") - ) - yield new MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]( - bucket, { - _ match - case ByOsobniCislo(osc) => equal("metadata.osobniCislo", osc) - } - ) - ) diff --git a/build.sbt b/build.sbt index f0fe88f..ee4de1d 100644 --- a/build.sbt +++ b/build.sbt @@ -4,6 +4,9 @@ publishToIW +lazy val fixSilencerDoc = + libraryDependencies += "com.github.ghik" %% "silencer-lib" % "1.4.2" % Provided cross CrossVersion.for3Use2_13 + lazy val core = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Full) .settings(name := "iw-support-core") @@ -51,17 +54,21 @@ lazy val `mongo-support` = project .in(file("mongo")) - .configs(IntegrationTest) .settings(name := "iw-support-mongo") .settings( - Defaults.itSettings, - IWDeps.useZIO(Test, IntegrationTest), + fixSilencerDoc, + IWDeps.useZIO(), IWDeps.useZIOJson, IWDeps.zioConfig, libraryDependencies += ("org.mongodb.scala" %% "mongo-scala-driver" % "4.2.3") .cross(CrossVersion.for3Use2_13) ) +lazy val `mongo-support-it` = project + .in(file("mongo/it")) + .settings(publish / skip := true) + .dependsOn(`mongo-support`) + lazy val `akka-persistence-support` = project .in(file("akka-persistence")) .settings(name := "iw-support-akka-persistence") @@ -98,6 +105,29 @@ ) .dependsOn(core) +lazy val http = (project in file("server/http")) + .settings(name := "iw-support-server-http") + .settings( + fixSilencerDoc, + IWDeps.useZIO(), + IWDeps.zioConfig, + IWDeps.zioConfigTypesafe, + IWDeps.zioConfigMagnolia, + IWDeps.zioLoggingSlf4j, + // TODO: use IWDeps.zioInteropCats with next iw-support version (0.3.19+) + libraryDependencies += "dev.zio" %% "zio-interop-cats" % "23.0.0.8", + IWDeps.tapirCore, + IWDeps.tapirZIO, + IWDeps.tapirZIOJson, + IWDeps.tapirLib("files"), + IWDeps.tapirZIOHttp4sServer, + IWDeps.http4sBlazeServer, + IWDeps.http4sPac4J, + IWDeps.pac4jOIDC, + IWDeps.logbackClassic + ) + .dependsOn(core.jvm, codecs.jvm, `tapir-support`.jvm) + lazy val root = (project in file(".")) .enablePlugins(IWScalaProjectPlugin) .settings( @@ -114,5 +144,6 @@ `mongo-support`, `akka-persistence-support`, ui.js, - ui.jvm + ui.jvm, + http ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..467dd17 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala @@ -0,0 +1,48 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonFileRepositoryIntegrationSpec extends ZIOSpecDefault: + case class ExampleMetadata(osobniCislo: String) + sealed trait ExampleCriteria + case class ByOsobniCislo(osobniCislo: String) extends ExampleCriteria + + given JsonCodec[ExampleMetadata] = DeriveJsonCodec.gen + + override def spec = suite("Mongo file repository integration spec")( + test("repo can put and read back file")( + for + repo <- ZIO + .service[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] + fname = "Příliš žluťoučký kůň úpěl ďábelské ódy.txt" + _ <- repo.put( + fname, + "Example content".getBytes(), + ExampleMetadata("10123") + ) + result <- repo.matching(ByOsobniCislo("10123")) + yield assertTrue(result.head.name == fname) + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer + : TaskLayer[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.mongodb.scala.gridfs.GridFSBucket + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer( + for + client <- ZIO.service[MongoClient] + bucket <- ZIO.attempt( + GridFSBucket(client.getDatabase("test"), "testfiles") + ) + yield new MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]( + bucket, { + _ match + case ByOsobniCislo(osc) => equal("metadata.osobniCislo", osc) + } + ) + ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..56ad2c3 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala @@ -0,0 +1,46 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonRepositoryIntegrationSpec extends ZIOSpecDefault: + case class Example(id: String, value: String) + sealed trait ExampleCriteria + case object All extends ExampleCriteria + case class ById(id: String) extends ExampleCriteria + + given JsonCodec[Example] = DeriveJsonCodec.gen + + override def spec = suite("Mongo repository integration spec")( + test("repo can put and read back")( + for + repo <- ZIO + .service[MongoJsonRepository[Example, String, ExampleCriteria]] + _ <- repo.put(Example("1", "test")) + result <- repo.matching(ById("1")) + yield assertTrue(result.head.value == "test") + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer: TaskLayer[MongoJsonRepository[Example, String, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.bson.json.JsonObject + import org.mongodb.scala.bson.Document + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer { + (for + client <- ZIO.service[MongoClient] + coll <- ZIO.attempt( + client.getDatabase("test").getCollection[JsonObject]("example") + ) + yield new MongoJsonRepository[Example, String, ExampleCriteria]( + coll, { + _ match + case ById(id) => equal("id", id) + case All => Document() + }, + e => ("id", e.id) + )) + } diff --git a/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala b/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala deleted file mode 100644 index 467dd17..0000000 --- a/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala +++ /dev/null @@ -1,48 +0,0 @@ -package works.iterative.mongo - -import zio.* -import zio.test.* -import zio.json.* -import Assertion.* - -object MongoJsonFileRepositoryIntegrationSpec extends ZIOSpecDefault: - case class ExampleMetadata(osobniCislo: String) - sealed trait ExampleCriteria - case class ByOsobniCislo(osobniCislo: String) extends ExampleCriteria - - given JsonCodec[ExampleMetadata] = DeriveJsonCodec.gen - - override def spec = suite("Mongo file repository integration spec")( - test("repo can put and read back file")( - for - repo <- ZIO - .service[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] - fname = "Příliš žluťoučký kůň úpěl ďábelské ódy.txt" - _ <- repo.put( - fname, - "Example content".getBytes(), - ExampleMetadata("10123") - ) - result <- repo.matching(ByOsobniCislo("10123")) - yield assertTrue(result.head.name == fname) - ) - ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") - - val layer - : TaskLayer[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] = - import org.mongodb.scala.* - import org.mongodb.scala.model.Filters.* - import org.mongodb.scala.gridfs.GridFSBucket - MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer( - for - client <- ZIO.service[MongoClient] - bucket <- ZIO.attempt( - GridFSBucket(client.getDatabase("test"), "testfiles") - ) - yield new MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]( - bucket, { - _ match - case ByOsobniCislo(osc) => equal("metadata.osobniCislo", osc) - } - ) - ) diff --git a/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala b/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala deleted file mode 100644 index 56ad2c3..0000000 --- a/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala +++ /dev/null @@ -1,46 +0,0 @@ -package works.iterative.mongo - -import zio.* -import zio.test.* -import zio.json.* -import Assertion.* - -object MongoJsonRepositoryIntegrationSpec extends ZIOSpecDefault: - case class Example(id: String, value: String) - sealed trait ExampleCriteria - case object All extends ExampleCriteria - case class ById(id: String) extends ExampleCriteria - - given JsonCodec[Example] = DeriveJsonCodec.gen - - override def spec = suite("Mongo repository integration spec")( - test("repo can put and read back")( - for - repo <- ZIO - .service[MongoJsonRepository[Example, String, ExampleCriteria]] - _ <- repo.put(Example("1", "test")) - result <- repo.matching(ById("1")) - yield assertTrue(result.head.value == "test") - ) - ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") - - val layer: TaskLayer[MongoJsonRepository[Example, String, ExampleCriteria]] = - import org.mongodb.scala.* - import org.mongodb.scala.model.Filters.* - import org.bson.json.JsonObject - import org.mongodb.scala.bson.Document - MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer { - (for - client <- ZIO.service[MongoClient] - coll <- ZIO.attempt( - client.getDatabase("test").getCollection[JsonObject]("example") - ) - yield new MongoJsonRepository[Example, String, ExampleCriteria]( - coll, { - _ match - case ById(id) => equal("id", id) - case All => Document() - }, - e => ("id", e.id) - )) - } diff --git a/build.sbt b/build.sbt index f0fe88f..ee4de1d 100644 --- a/build.sbt +++ b/build.sbt @@ -4,6 +4,9 @@ publishToIW +lazy val fixSilencerDoc = + libraryDependencies += "com.github.ghik" %% "silencer-lib" % "1.4.2" % Provided cross CrossVersion.for3Use2_13 + lazy val core = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Full) .settings(name := "iw-support-core") @@ -51,17 +54,21 @@ lazy val `mongo-support` = project .in(file("mongo")) - .configs(IntegrationTest) .settings(name := "iw-support-mongo") .settings( - Defaults.itSettings, - IWDeps.useZIO(Test, IntegrationTest), + fixSilencerDoc, + IWDeps.useZIO(), IWDeps.useZIOJson, IWDeps.zioConfig, libraryDependencies += ("org.mongodb.scala" %% "mongo-scala-driver" % "4.2.3") .cross(CrossVersion.for3Use2_13) ) +lazy val `mongo-support-it` = project + .in(file("mongo/it")) + .settings(publish / skip := true) + .dependsOn(`mongo-support`) + lazy val `akka-persistence-support` = project .in(file("akka-persistence")) .settings(name := "iw-support-akka-persistence") @@ -98,6 +105,29 @@ ) .dependsOn(core) +lazy val http = (project in file("server/http")) + .settings(name := "iw-support-server-http") + .settings( + fixSilencerDoc, + IWDeps.useZIO(), + IWDeps.zioConfig, + IWDeps.zioConfigTypesafe, + IWDeps.zioConfigMagnolia, + IWDeps.zioLoggingSlf4j, + // TODO: use IWDeps.zioInteropCats with next iw-support version (0.3.19+) + libraryDependencies += "dev.zio" %% "zio-interop-cats" % "23.0.0.8", + IWDeps.tapirCore, + IWDeps.tapirZIO, + IWDeps.tapirZIOJson, + IWDeps.tapirLib("files"), + IWDeps.tapirZIOHttp4sServer, + IWDeps.http4sBlazeServer, + IWDeps.http4sPac4J, + IWDeps.pac4jOIDC, + IWDeps.logbackClassic + ) + .dependsOn(core.jvm, codecs.jvm, `tapir-support`.jvm) + lazy val root = (project in file(".")) .enablePlugins(IWScalaProjectPlugin) .settings( @@ -114,5 +144,6 @@ `mongo-support`, `akka-persistence-support`, ui.js, - ui.jvm + ui.jvm, + http ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..467dd17 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala @@ -0,0 +1,48 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonFileRepositoryIntegrationSpec extends ZIOSpecDefault: + case class ExampleMetadata(osobniCislo: String) + sealed trait ExampleCriteria + case class ByOsobniCislo(osobniCislo: String) extends ExampleCriteria + + given JsonCodec[ExampleMetadata] = DeriveJsonCodec.gen + + override def spec = suite("Mongo file repository integration spec")( + test("repo can put and read back file")( + for + repo <- ZIO + .service[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] + fname = "Příliš žluťoučký kůň úpěl ďábelské ódy.txt" + _ <- repo.put( + fname, + "Example content".getBytes(), + ExampleMetadata("10123") + ) + result <- repo.matching(ByOsobniCislo("10123")) + yield assertTrue(result.head.name == fname) + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer + : TaskLayer[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.mongodb.scala.gridfs.GridFSBucket + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer( + for + client <- ZIO.service[MongoClient] + bucket <- ZIO.attempt( + GridFSBucket(client.getDatabase("test"), "testfiles") + ) + yield new MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]( + bucket, { + _ match + case ByOsobniCislo(osc) => equal("metadata.osobniCislo", osc) + } + ) + ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..56ad2c3 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala @@ -0,0 +1,46 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonRepositoryIntegrationSpec extends ZIOSpecDefault: + case class Example(id: String, value: String) + sealed trait ExampleCriteria + case object All extends ExampleCriteria + case class ById(id: String) extends ExampleCriteria + + given JsonCodec[Example] = DeriveJsonCodec.gen + + override def spec = suite("Mongo repository integration spec")( + test("repo can put and read back")( + for + repo <- ZIO + .service[MongoJsonRepository[Example, String, ExampleCriteria]] + _ <- repo.put(Example("1", "test")) + result <- repo.matching(ById("1")) + yield assertTrue(result.head.value == "test") + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer: TaskLayer[MongoJsonRepository[Example, String, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.bson.json.JsonObject + import org.mongodb.scala.bson.Document + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer { + (for + client <- ZIO.service[MongoClient] + coll <- ZIO.attempt( + client.getDatabase("test").getCollection[JsonObject]("example") + ) + yield new MongoJsonRepository[Example, String, ExampleCriteria]( + coll, { + _ match + case ById(id) => equal("id", id) + case All => Document() + }, + e => ("id", e.id) + )) + } diff --git a/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala b/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala deleted file mode 100644 index 467dd17..0000000 --- a/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala +++ /dev/null @@ -1,48 +0,0 @@ -package works.iterative.mongo - -import zio.* -import zio.test.* -import zio.json.* -import Assertion.* - -object MongoJsonFileRepositoryIntegrationSpec extends ZIOSpecDefault: - case class ExampleMetadata(osobniCislo: String) - sealed trait ExampleCriteria - case class ByOsobniCislo(osobniCislo: String) extends ExampleCriteria - - given JsonCodec[ExampleMetadata] = DeriveJsonCodec.gen - - override def spec = suite("Mongo file repository integration spec")( - test("repo can put and read back file")( - for - repo <- ZIO - .service[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] - fname = "Příliš žluťoučký kůň úpěl ďábelské ódy.txt" - _ <- repo.put( - fname, - "Example content".getBytes(), - ExampleMetadata("10123") - ) - result <- repo.matching(ByOsobniCislo("10123")) - yield assertTrue(result.head.name == fname) - ) - ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") - - val layer - : TaskLayer[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] = - import org.mongodb.scala.* - import org.mongodb.scala.model.Filters.* - import org.mongodb.scala.gridfs.GridFSBucket - MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer( - for - client <- ZIO.service[MongoClient] - bucket <- ZIO.attempt( - GridFSBucket(client.getDatabase("test"), "testfiles") - ) - yield new MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]( - bucket, { - _ match - case ByOsobniCislo(osc) => equal("metadata.osobniCislo", osc) - } - ) - ) diff --git a/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala b/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala deleted file mode 100644 index 56ad2c3..0000000 --- a/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala +++ /dev/null @@ -1,46 +0,0 @@ -package works.iterative.mongo - -import zio.* -import zio.test.* -import zio.json.* -import Assertion.* - -object MongoJsonRepositoryIntegrationSpec extends ZIOSpecDefault: - case class Example(id: String, value: String) - sealed trait ExampleCriteria - case object All extends ExampleCriteria - case class ById(id: String) extends ExampleCriteria - - given JsonCodec[Example] = DeriveJsonCodec.gen - - override def spec = suite("Mongo repository integration spec")( - test("repo can put and read back")( - for - repo <- ZIO - .service[MongoJsonRepository[Example, String, ExampleCriteria]] - _ <- repo.put(Example("1", "test")) - result <- repo.matching(ById("1")) - yield assertTrue(result.head.value == "test") - ) - ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") - - val layer: TaskLayer[MongoJsonRepository[Example, String, ExampleCriteria]] = - import org.mongodb.scala.* - import org.mongodb.scala.model.Filters.* - import org.bson.json.JsonObject - import org.mongodb.scala.bson.Document - MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer { - (for - client <- ZIO.service[MongoClient] - coll <- ZIO.attempt( - client.getDatabase("test").getCollection[JsonObject]("example") - ) - yield new MongoJsonRepository[Example, String, ExampleCriteria]( - coll, { - _ match - case ById(id) => equal("id", id) - case All => Document() - }, - e => ("id", e.id) - )) - } diff --git a/server/http/src/main/scala/works/iterative/server/http/HttpApplication.scala b/server/http/src/main/scala/works/iterative/server/http/HttpApplication.scala new file mode 100644 index 0000000..2233842 --- /dev/null +++ b/server/http/src/main/scala/works/iterative/server/http/HttpApplication.scala @@ -0,0 +1,7 @@ +package works.iterative.server.http + +import works.iterative.tapir.CustomTapir.* + +final case class HttpApplication[Env]( + endpoints: List[ZServerEndpoint[Env, Any]] +) diff --git a/build.sbt b/build.sbt index f0fe88f..ee4de1d 100644 --- a/build.sbt +++ b/build.sbt @@ -4,6 +4,9 @@ publishToIW +lazy val fixSilencerDoc = + libraryDependencies += "com.github.ghik" %% "silencer-lib" % "1.4.2" % Provided cross CrossVersion.for3Use2_13 + lazy val core = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Full) .settings(name := "iw-support-core") @@ -51,17 +54,21 @@ lazy val `mongo-support` = project .in(file("mongo")) - .configs(IntegrationTest) .settings(name := "iw-support-mongo") .settings( - Defaults.itSettings, - IWDeps.useZIO(Test, IntegrationTest), + fixSilencerDoc, + IWDeps.useZIO(), IWDeps.useZIOJson, IWDeps.zioConfig, libraryDependencies += ("org.mongodb.scala" %% "mongo-scala-driver" % "4.2.3") .cross(CrossVersion.for3Use2_13) ) +lazy val `mongo-support-it` = project + .in(file("mongo/it")) + .settings(publish / skip := true) + .dependsOn(`mongo-support`) + lazy val `akka-persistence-support` = project .in(file("akka-persistence")) .settings(name := "iw-support-akka-persistence") @@ -98,6 +105,29 @@ ) .dependsOn(core) +lazy val http = (project in file("server/http")) + .settings(name := "iw-support-server-http") + .settings( + fixSilencerDoc, + IWDeps.useZIO(), + IWDeps.zioConfig, + IWDeps.zioConfigTypesafe, + IWDeps.zioConfigMagnolia, + IWDeps.zioLoggingSlf4j, + // TODO: use IWDeps.zioInteropCats with next iw-support version (0.3.19+) + libraryDependencies += "dev.zio" %% "zio-interop-cats" % "23.0.0.8", + IWDeps.tapirCore, + IWDeps.tapirZIO, + IWDeps.tapirZIOJson, + IWDeps.tapirLib("files"), + IWDeps.tapirZIOHttp4sServer, + IWDeps.http4sBlazeServer, + IWDeps.http4sPac4J, + IWDeps.pac4jOIDC, + IWDeps.logbackClassic + ) + .dependsOn(core.jvm, codecs.jvm, `tapir-support`.jvm) + lazy val root = (project in file(".")) .enablePlugins(IWScalaProjectPlugin) .settings( @@ -114,5 +144,6 @@ `mongo-support`, `akka-persistence-support`, ui.js, - ui.jvm + ui.jvm, + http ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..467dd17 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala @@ -0,0 +1,48 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonFileRepositoryIntegrationSpec extends ZIOSpecDefault: + case class ExampleMetadata(osobniCislo: String) + sealed trait ExampleCriteria + case class ByOsobniCislo(osobniCislo: String) extends ExampleCriteria + + given JsonCodec[ExampleMetadata] = DeriveJsonCodec.gen + + override def spec = suite("Mongo file repository integration spec")( + test("repo can put and read back file")( + for + repo <- ZIO + .service[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] + fname = "Příliš žluťoučký kůň úpěl ďábelské ódy.txt" + _ <- repo.put( + fname, + "Example content".getBytes(), + ExampleMetadata("10123") + ) + result <- repo.matching(ByOsobniCislo("10123")) + yield assertTrue(result.head.name == fname) + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer + : TaskLayer[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.mongodb.scala.gridfs.GridFSBucket + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer( + for + client <- ZIO.service[MongoClient] + bucket <- ZIO.attempt( + GridFSBucket(client.getDatabase("test"), "testfiles") + ) + yield new MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]( + bucket, { + _ match + case ByOsobniCislo(osc) => equal("metadata.osobniCislo", osc) + } + ) + ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..56ad2c3 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala @@ -0,0 +1,46 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonRepositoryIntegrationSpec extends ZIOSpecDefault: + case class Example(id: String, value: String) + sealed trait ExampleCriteria + case object All extends ExampleCriteria + case class ById(id: String) extends ExampleCriteria + + given JsonCodec[Example] = DeriveJsonCodec.gen + + override def spec = suite("Mongo repository integration spec")( + test("repo can put and read back")( + for + repo <- ZIO + .service[MongoJsonRepository[Example, String, ExampleCriteria]] + _ <- repo.put(Example("1", "test")) + result <- repo.matching(ById("1")) + yield assertTrue(result.head.value == "test") + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer: TaskLayer[MongoJsonRepository[Example, String, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.bson.json.JsonObject + import org.mongodb.scala.bson.Document + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer { + (for + client <- ZIO.service[MongoClient] + coll <- ZIO.attempt( + client.getDatabase("test").getCollection[JsonObject]("example") + ) + yield new MongoJsonRepository[Example, String, ExampleCriteria]( + coll, { + _ match + case ById(id) => equal("id", id) + case All => Document() + }, + e => ("id", e.id) + )) + } diff --git a/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala b/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala deleted file mode 100644 index 467dd17..0000000 --- a/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala +++ /dev/null @@ -1,48 +0,0 @@ -package works.iterative.mongo - -import zio.* -import zio.test.* -import zio.json.* -import Assertion.* - -object MongoJsonFileRepositoryIntegrationSpec extends ZIOSpecDefault: - case class ExampleMetadata(osobniCislo: String) - sealed trait ExampleCriteria - case class ByOsobniCislo(osobniCislo: String) extends ExampleCriteria - - given JsonCodec[ExampleMetadata] = DeriveJsonCodec.gen - - override def spec = suite("Mongo file repository integration spec")( - test("repo can put and read back file")( - for - repo <- ZIO - .service[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] - fname = "Příliš žluťoučký kůň úpěl ďábelské ódy.txt" - _ <- repo.put( - fname, - "Example content".getBytes(), - ExampleMetadata("10123") - ) - result <- repo.matching(ByOsobniCislo("10123")) - yield assertTrue(result.head.name == fname) - ) - ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") - - val layer - : TaskLayer[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] = - import org.mongodb.scala.* - import org.mongodb.scala.model.Filters.* - import org.mongodb.scala.gridfs.GridFSBucket - MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer( - for - client <- ZIO.service[MongoClient] - bucket <- ZIO.attempt( - GridFSBucket(client.getDatabase("test"), "testfiles") - ) - yield new MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]( - bucket, { - _ match - case ByOsobniCislo(osc) => equal("metadata.osobniCislo", osc) - } - ) - ) diff --git a/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala b/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala deleted file mode 100644 index 56ad2c3..0000000 --- a/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala +++ /dev/null @@ -1,46 +0,0 @@ -package works.iterative.mongo - -import zio.* -import zio.test.* -import zio.json.* -import Assertion.* - -object MongoJsonRepositoryIntegrationSpec extends ZIOSpecDefault: - case class Example(id: String, value: String) - sealed trait ExampleCriteria - case object All extends ExampleCriteria - case class ById(id: String) extends ExampleCriteria - - given JsonCodec[Example] = DeriveJsonCodec.gen - - override def spec = suite("Mongo repository integration spec")( - test("repo can put and read back")( - for - repo <- ZIO - .service[MongoJsonRepository[Example, String, ExampleCriteria]] - _ <- repo.put(Example("1", "test")) - result <- repo.matching(ById("1")) - yield assertTrue(result.head.value == "test") - ) - ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") - - val layer: TaskLayer[MongoJsonRepository[Example, String, ExampleCriteria]] = - import org.mongodb.scala.* - import org.mongodb.scala.model.Filters.* - import org.bson.json.JsonObject - import org.mongodb.scala.bson.Document - MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer { - (for - client <- ZIO.service[MongoClient] - coll <- ZIO.attempt( - client.getDatabase("test").getCollection[JsonObject]("example") - ) - yield new MongoJsonRepository[Example, String, ExampleCriteria]( - coll, { - _ match - case ById(id) => equal("id", id) - case All => Document() - }, - e => ("id", e.id) - )) - } diff --git a/server/http/src/main/scala/works/iterative/server/http/HttpApplication.scala b/server/http/src/main/scala/works/iterative/server/http/HttpApplication.scala new file mode 100644 index 0000000..2233842 --- /dev/null +++ b/server/http/src/main/scala/works/iterative/server/http/HttpApplication.scala @@ -0,0 +1,7 @@ +package works.iterative.server.http + +import works.iterative.tapir.CustomTapir.* + +final case class HttpApplication[Env]( + endpoints: List[ZServerEndpoint[Env, Any]] +) diff --git a/server/http/src/main/scala/works/iterative/server/http/HttpServer.scala b/server/http/src/main/scala/works/iterative/server/http/HttpServer.scala new file mode 100644 index 0000000..6ca5ef6 --- /dev/null +++ b/server/http/src/main/scala/works/iterative/server/http/HttpServer.scala @@ -0,0 +1,10 @@ +package works.iterative.server.http + +import zio.* + +trait HttpServer: + def serve[Env](app: HttpApplication[Env]): URIO[Env, Nothing] + +object HttpServer: + def serve[Env](app: HttpApplication[Env]): URIO[Env & HttpServer, Nothing] = + ZIO.serviceWithZIO[HttpServer](_.serve(app)) diff --git a/build.sbt b/build.sbt index f0fe88f..ee4de1d 100644 --- a/build.sbt +++ b/build.sbt @@ -4,6 +4,9 @@ publishToIW +lazy val fixSilencerDoc = + libraryDependencies += "com.github.ghik" %% "silencer-lib" % "1.4.2" % Provided cross CrossVersion.for3Use2_13 + lazy val core = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Full) .settings(name := "iw-support-core") @@ -51,17 +54,21 @@ lazy val `mongo-support` = project .in(file("mongo")) - .configs(IntegrationTest) .settings(name := "iw-support-mongo") .settings( - Defaults.itSettings, - IWDeps.useZIO(Test, IntegrationTest), + fixSilencerDoc, + IWDeps.useZIO(), IWDeps.useZIOJson, IWDeps.zioConfig, libraryDependencies += ("org.mongodb.scala" %% "mongo-scala-driver" % "4.2.3") .cross(CrossVersion.for3Use2_13) ) +lazy val `mongo-support-it` = project + .in(file("mongo/it")) + .settings(publish / skip := true) + .dependsOn(`mongo-support`) + lazy val `akka-persistence-support` = project .in(file("akka-persistence")) .settings(name := "iw-support-akka-persistence") @@ -98,6 +105,29 @@ ) .dependsOn(core) +lazy val http = (project in file("server/http")) + .settings(name := "iw-support-server-http") + .settings( + fixSilencerDoc, + IWDeps.useZIO(), + IWDeps.zioConfig, + IWDeps.zioConfigTypesafe, + IWDeps.zioConfigMagnolia, + IWDeps.zioLoggingSlf4j, + // TODO: use IWDeps.zioInteropCats with next iw-support version (0.3.19+) + libraryDependencies += "dev.zio" %% "zio-interop-cats" % "23.0.0.8", + IWDeps.tapirCore, + IWDeps.tapirZIO, + IWDeps.tapirZIOJson, + IWDeps.tapirLib("files"), + IWDeps.tapirZIOHttp4sServer, + IWDeps.http4sBlazeServer, + IWDeps.http4sPac4J, + IWDeps.pac4jOIDC, + IWDeps.logbackClassic + ) + .dependsOn(core.jvm, codecs.jvm, `tapir-support`.jvm) + lazy val root = (project in file(".")) .enablePlugins(IWScalaProjectPlugin) .settings( @@ -114,5 +144,6 @@ `mongo-support`, `akka-persistence-support`, ui.js, - ui.jvm + ui.jvm, + http ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..467dd17 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala @@ -0,0 +1,48 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonFileRepositoryIntegrationSpec extends ZIOSpecDefault: + case class ExampleMetadata(osobniCislo: String) + sealed trait ExampleCriteria + case class ByOsobniCislo(osobniCislo: String) extends ExampleCriteria + + given JsonCodec[ExampleMetadata] = DeriveJsonCodec.gen + + override def spec = suite("Mongo file repository integration spec")( + test("repo can put and read back file")( + for + repo <- ZIO + .service[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] + fname = "Příliš žluťoučký kůň úpěl ďábelské ódy.txt" + _ <- repo.put( + fname, + "Example content".getBytes(), + ExampleMetadata("10123") + ) + result <- repo.matching(ByOsobniCislo("10123")) + yield assertTrue(result.head.name == fname) + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer + : TaskLayer[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.mongodb.scala.gridfs.GridFSBucket + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer( + for + client <- ZIO.service[MongoClient] + bucket <- ZIO.attempt( + GridFSBucket(client.getDatabase("test"), "testfiles") + ) + yield new MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]( + bucket, { + _ match + case ByOsobniCislo(osc) => equal("metadata.osobniCislo", osc) + } + ) + ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..56ad2c3 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala @@ -0,0 +1,46 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonRepositoryIntegrationSpec extends ZIOSpecDefault: + case class Example(id: String, value: String) + sealed trait ExampleCriteria + case object All extends ExampleCriteria + case class ById(id: String) extends ExampleCriteria + + given JsonCodec[Example] = DeriveJsonCodec.gen + + override def spec = suite("Mongo repository integration spec")( + test("repo can put and read back")( + for + repo <- ZIO + .service[MongoJsonRepository[Example, String, ExampleCriteria]] + _ <- repo.put(Example("1", "test")) + result <- repo.matching(ById("1")) + yield assertTrue(result.head.value == "test") + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer: TaskLayer[MongoJsonRepository[Example, String, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.bson.json.JsonObject + import org.mongodb.scala.bson.Document + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer { + (for + client <- ZIO.service[MongoClient] + coll <- ZIO.attempt( + client.getDatabase("test").getCollection[JsonObject]("example") + ) + yield new MongoJsonRepository[Example, String, ExampleCriteria]( + coll, { + _ match + case ById(id) => equal("id", id) + case All => Document() + }, + e => ("id", e.id) + )) + } diff --git a/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala b/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala deleted file mode 100644 index 467dd17..0000000 --- a/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala +++ /dev/null @@ -1,48 +0,0 @@ -package works.iterative.mongo - -import zio.* -import zio.test.* -import zio.json.* -import Assertion.* - -object MongoJsonFileRepositoryIntegrationSpec extends ZIOSpecDefault: - case class ExampleMetadata(osobniCislo: String) - sealed trait ExampleCriteria - case class ByOsobniCislo(osobniCislo: String) extends ExampleCriteria - - given JsonCodec[ExampleMetadata] = DeriveJsonCodec.gen - - override def spec = suite("Mongo file repository integration spec")( - test("repo can put and read back file")( - for - repo <- ZIO - .service[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] - fname = "Příliš žluťoučký kůň úpěl ďábelské ódy.txt" - _ <- repo.put( - fname, - "Example content".getBytes(), - ExampleMetadata("10123") - ) - result <- repo.matching(ByOsobniCislo("10123")) - yield assertTrue(result.head.name == fname) - ) - ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") - - val layer - : TaskLayer[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] = - import org.mongodb.scala.* - import org.mongodb.scala.model.Filters.* - import org.mongodb.scala.gridfs.GridFSBucket - MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer( - for - client <- ZIO.service[MongoClient] - bucket <- ZIO.attempt( - GridFSBucket(client.getDatabase("test"), "testfiles") - ) - yield new MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]( - bucket, { - _ match - case ByOsobniCislo(osc) => equal("metadata.osobniCislo", osc) - } - ) - ) diff --git a/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala b/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala deleted file mode 100644 index 56ad2c3..0000000 --- a/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala +++ /dev/null @@ -1,46 +0,0 @@ -package works.iterative.mongo - -import zio.* -import zio.test.* -import zio.json.* -import Assertion.* - -object MongoJsonRepositoryIntegrationSpec extends ZIOSpecDefault: - case class Example(id: String, value: String) - sealed trait ExampleCriteria - case object All extends ExampleCriteria - case class ById(id: String) extends ExampleCriteria - - given JsonCodec[Example] = DeriveJsonCodec.gen - - override def spec = suite("Mongo repository integration spec")( - test("repo can put and read back")( - for - repo <- ZIO - .service[MongoJsonRepository[Example, String, ExampleCriteria]] - _ <- repo.put(Example("1", "test")) - result <- repo.matching(ById("1")) - yield assertTrue(result.head.value == "test") - ) - ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") - - val layer: TaskLayer[MongoJsonRepository[Example, String, ExampleCriteria]] = - import org.mongodb.scala.* - import org.mongodb.scala.model.Filters.* - import org.bson.json.JsonObject - import org.mongodb.scala.bson.Document - MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer { - (for - client <- ZIO.service[MongoClient] - coll <- ZIO.attempt( - client.getDatabase("test").getCollection[JsonObject]("example") - ) - yield new MongoJsonRepository[Example, String, ExampleCriteria]( - coll, { - _ match - case ById(id) => equal("id", id) - case All => Document() - }, - e => ("id", e.id) - )) - } diff --git a/server/http/src/main/scala/works/iterative/server/http/HttpApplication.scala b/server/http/src/main/scala/works/iterative/server/http/HttpApplication.scala new file mode 100644 index 0000000..2233842 --- /dev/null +++ b/server/http/src/main/scala/works/iterative/server/http/HttpApplication.scala @@ -0,0 +1,7 @@ +package works.iterative.server.http + +import works.iterative.tapir.CustomTapir.* + +final case class HttpApplication[Env]( + endpoints: List[ZServerEndpoint[Env, Any]] +) diff --git a/server/http/src/main/scala/works/iterative/server/http/HttpServer.scala b/server/http/src/main/scala/works/iterative/server/http/HttpServer.scala new file mode 100644 index 0000000..6ca5ef6 --- /dev/null +++ b/server/http/src/main/scala/works/iterative/server/http/HttpServer.scala @@ -0,0 +1,10 @@ +package works.iterative.server.http + +import zio.* + +trait HttpServer: + def serve[Env](app: HttpApplication[Env]): URIO[Env, Nothing] + +object HttpServer: + def serve[Env](app: HttpApplication[Env]): URIO[Env & HttpServer, Nothing] = + ZIO.serviceWithZIO[HttpServer](_.serve(app)) diff --git a/server/http/src/main/scala/works/iterative/server/http/impl/blaze/BlazeHttpServer.scala b/server/http/src/main/scala/works/iterative/server/http/impl/blaze/BlazeHttpServer.scala new file mode 100644 index 0000000..53d3033 --- /dev/null +++ b/server/http/src/main/scala/works/iterative/server/http/impl/blaze/BlazeHttpServer.scala @@ -0,0 +1,21 @@ +package works.iterative.server.http +package impl.blaze + +import zio.* +import zio.interop.catz.* +import org.http4s.blaze.server.BlazeServerBuilder + +class BlazeHttpServer(config: BlazeServerConfig) extends HttpServer: + override def serve[Env](app: HttpApplication[Env]): URIO[Env, Nothing] = + BlazeServerBuilder[RIO[Env, *]] + .bindHttp(config.port, config.host) + .serve + .compile + .drain + .orDie *> ZIO.never + +object BlazeHttpServer: + val layer: RLayer[BlazeServerConfig, HttpServer] = ZLayer { + for config <- ZIO.service[BlazeServerConfig] + yield BlazeHttpServer(config) + } diff --git a/build.sbt b/build.sbt index f0fe88f..ee4de1d 100644 --- a/build.sbt +++ b/build.sbt @@ -4,6 +4,9 @@ publishToIW +lazy val fixSilencerDoc = + libraryDependencies += "com.github.ghik" %% "silencer-lib" % "1.4.2" % Provided cross CrossVersion.for3Use2_13 + lazy val core = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Full) .settings(name := "iw-support-core") @@ -51,17 +54,21 @@ lazy val `mongo-support` = project .in(file("mongo")) - .configs(IntegrationTest) .settings(name := "iw-support-mongo") .settings( - Defaults.itSettings, - IWDeps.useZIO(Test, IntegrationTest), + fixSilencerDoc, + IWDeps.useZIO(), IWDeps.useZIOJson, IWDeps.zioConfig, libraryDependencies += ("org.mongodb.scala" %% "mongo-scala-driver" % "4.2.3") .cross(CrossVersion.for3Use2_13) ) +lazy val `mongo-support-it` = project + .in(file("mongo/it")) + .settings(publish / skip := true) + .dependsOn(`mongo-support`) + lazy val `akka-persistence-support` = project .in(file("akka-persistence")) .settings(name := "iw-support-akka-persistence") @@ -98,6 +105,29 @@ ) .dependsOn(core) +lazy val http = (project in file("server/http")) + .settings(name := "iw-support-server-http") + .settings( + fixSilencerDoc, + IWDeps.useZIO(), + IWDeps.zioConfig, + IWDeps.zioConfigTypesafe, + IWDeps.zioConfigMagnolia, + IWDeps.zioLoggingSlf4j, + // TODO: use IWDeps.zioInteropCats with next iw-support version (0.3.19+) + libraryDependencies += "dev.zio" %% "zio-interop-cats" % "23.0.0.8", + IWDeps.tapirCore, + IWDeps.tapirZIO, + IWDeps.tapirZIOJson, + IWDeps.tapirLib("files"), + IWDeps.tapirZIOHttp4sServer, + IWDeps.http4sBlazeServer, + IWDeps.http4sPac4J, + IWDeps.pac4jOIDC, + IWDeps.logbackClassic + ) + .dependsOn(core.jvm, codecs.jvm, `tapir-support`.jvm) + lazy val root = (project in file(".")) .enablePlugins(IWScalaProjectPlugin) .settings( @@ -114,5 +144,6 @@ `mongo-support`, `akka-persistence-support`, ui.js, - ui.jvm + ui.jvm, + http ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..467dd17 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala @@ -0,0 +1,48 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonFileRepositoryIntegrationSpec extends ZIOSpecDefault: + case class ExampleMetadata(osobniCislo: String) + sealed trait ExampleCriteria + case class ByOsobniCislo(osobniCislo: String) extends ExampleCriteria + + given JsonCodec[ExampleMetadata] = DeriveJsonCodec.gen + + override def spec = suite("Mongo file repository integration spec")( + test("repo can put and read back file")( + for + repo <- ZIO + .service[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] + fname = "Příliš žluťoučký kůň úpěl ďábelské ódy.txt" + _ <- repo.put( + fname, + "Example content".getBytes(), + ExampleMetadata("10123") + ) + result <- repo.matching(ByOsobniCislo("10123")) + yield assertTrue(result.head.name == fname) + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer + : TaskLayer[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.mongodb.scala.gridfs.GridFSBucket + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer( + for + client <- ZIO.service[MongoClient] + bucket <- ZIO.attempt( + GridFSBucket(client.getDatabase("test"), "testfiles") + ) + yield new MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]( + bucket, { + _ match + case ByOsobniCislo(osc) => equal("metadata.osobniCislo", osc) + } + ) + ) diff --git a/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala new file mode 100644 index 0000000..56ad2c3 --- /dev/null +++ b/mongo/it/src/main/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala @@ -0,0 +1,46 @@ +package works.iterative.mongo + +import zio.* +import zio.test.* +import zio.json.* +import Assertion.* + +object MongoJsonRepositoryIntegrationSpec extends ZIOSpecDefault: + case class Example(id: String, value: String) + sealed trait ExampleCriteria + case object All extends ExampleCriteria + case class ById(id: String) extends ExampleCriteria + + given JsonCodec[Example] = DeriveJsonCodec.gen + + override def spec = suite("Mongo repository integration spec")( + test("repo can put and read back")( + for + repo <- ZIO + .service[MongoJsonRepository[Example, String, ExampleCriteria]] + _ <- repo.put(Example("1", "test")) + result <- repo.matching(ById("1")) + yield assertTrue(result.head.value == "test") + ) + ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") + + val layer: TaskLayer[MongoJsonRepository[Example, String, ExampleCriteria]] = + import org.mongodb.scala.* + import org.mongodb.scala.model.Filters.* + import org.bson.json.JsonObject + import org.mongodb.scala.bson.Document + MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer { + (for + client <- ZIO.service[MongoClient] + coll <- ZIO.attempt( + client.getDatabase("test").getCollection[JsonObject]("example") + ) + yield new MongoJsonRepository[Example, String, ExampleCriteria]( + coll, { + _ match + case ById(id) => equal("id", id) + case All => Document() + }, + e => ("id", e.id) + )) + } diff --git a/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala b/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala deleted file mode 100644 index 467dd17..0000000 --- a/mongo/src/it/scala/works/iterative/mongo/MongoJsonFileRepositoryIntegrationSpec.scala +++ /dev/null @@ -1,48 +0,0 @@ -package works.iterative.mongo - -import zio.* -import zio.test.* -import zio.json.* -import Assertion.* - -object MongoJsonFileRepositoryIntegrationSpec extends ZIOSpecDefault: - case class ExampleMetadata(osobniCislo: String) - sealed trait ExampleCriteria - case class ByOsobniCislo(osobniCislo: String) extends ExampleCriteria - - given JsonCodec[ExampleMetadata] = DeriveJsonCodec.gen - - override def spec = suite("Mongo file repository integration spec")( - test("repo can put and read back file")( - for - repo <- ZIO - .service[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] - fname = "Příliš žluťoučký kůň úpěl ďábelské ódy.txt" - _ <- repo.put( - fname, - "Example content".getBytes(), - ExampleMetadata("10123") - ) - result <- repo.matching(ByOsobniCislo("10123")) - yield assertTrue(result.head.name == fname) - ) - ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") - - val layer - : TaskLayer[MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]] = - import org.mongodb.scala.* - import org.mongodb.scala.model.Filters.* - import org.mongodb.scala.gridfs.GridFSBucket - MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer( - for - client <- ZIO.service[MongoClient] - bucket <- ZIO.attempt( - GridFSBucket(client.getDatabase("test"), "testfiles") - ) - yield new MongoJsonFileRepository[ExampleMetadata, ExampleCriteria]( - bucket, { - _ match - case ByOsobniCislo(osc) => equal("metadata.osobniCislo", osc) - } - ) - ) diff --git a/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala b/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala deleted file mode 100644 index 56ad2c3..0000000 --- a/mongo/src/it/scala/works/iterative/mongo/MongoJsonRepositoryIntegrationSpec.scala +++ /dev/null @@ -1,46 +0,0 @@ -package works.iterative.mongo - -import zio.* -import zio.test.* -import zio.json.* -import Assertion.* - -object MongoJsonRepositoryIntegrationSpec extends ZIOSpecDefault: - case class Example(id: String, value: String) - sealed trait ExampleCriteria - case object All extends ExampleCriteria - case class ById(id: String) extends ExampleCriteria - - given JsonCodec[Example] = DeriveJsonCodec.gen - - override def spec = suite("Mongo repository integration spec")( - test("repo can put and read back")( - for - repo <- ZIO - .service[MongoJsonRepository[Example, String, ExampleCriteria]] - _ <- repo.put(Example("1", "test")) - result <- repo.matching(ById("1")) - yield assertTrue(result.head.value == "test") - ) - ).provide(layer) @@ TestAspect.ifEnvSet("MONGO_URI") - - val layer: TaskLayer[MongoJsonRepository[Example, String, ExampleCriteria]] = - import org.mongodb.scala.* - import org.mongodb.scala.model.Filters.* - import org.bson.json.JsonObject - import org.mongodb.scala.bson.Document - MongoConfig.fromEnv >>> MongoClient.layer >>> ZLayer { - (for - client <- ZIO.service[MongoClient] - coll <- ZIO.attempt( - client.getDatabase("test").getCollection[JsonObject]("example") - ) - yield new MongoJsonRepository[Example, String, ExampleCriteria]( - coll, { - _ match - case ById(id) => equal("id", id) - case All => Document() - }, - e => ("id", e.id) - )) - } diff --git a/server/http/src/main/scala/works/iterative/server/http/HttpApplication.scala b/server/http/src/main/scala/works/iterative/server/http/HttpApplication.scala new file mode 100644 index 0000000..2233842 --- /dev/null +++ b/server/http/src/main/scala/works/iterative/server/http/HttpApplication.scala @@ -0,0 +1,7 @@ +package works.iterative.server.http + +import works.iterative.tapir.CustomTapir.* + +final case class HttpApplication[Env]( + endpoints: List[ZServerEndpoint[Env, Any]] +) diff --git a/server/http/src/main/scala/works/iterative/server/http/HttpServer.scala b/server/http/src/main/scala/works/iterative/server/http/HttpServer.scala new file mode 100644 index 0000000..6ca5ef6 --- /dev/null +++ b/server/http/src/main/scala/works/iterative/server/http/HttpServer.scala @@ -0,0 +1,10 @@ +package works.iterative.server.http + +import zio.* + +trait HttpServer: + def serve[Env](app: HttpApplication[Env]): URIO[Env, Nothing] + +object HttpServer: + def serve[Env](app: HttpApplication[Env]): URIO[Env & HttpServer, Nothing] = + ZIO.serviceWithZIO[HttpServer](_.serve(app)) diff --git a/server/http/src/main/scala/works/iterative/server/http/impl/blaze/BlazeHttpServer.scala b/server/http/src/main/scala/works/iterative/server/http/impl/blaze/BlazeHttpServer.scala new file mode 100644 index 0000000..53d3033 --- /dev/null +++ b/server/http/src/main/scala/works/iterative/server/http/impl/blaze/BlazeHttpServer.scala @@ -0,0 +1,21 @@ +package works.iterative.server.http +package impl.blaze + +import zio.* +import zio.interop.catz.* +import org.http4s.blaze.server.BlazeServerBuilder + +class BlazeHttpServer(config: BlazeServerConfig) extends HttpServer: + override def serve[Env](app: HttpApplication[Env]): URIO[Env, Nothing] = + BlazeServerBuilder[RIO[Env, *]] + .bindHttp(config.port, config.host) + .serve + .compile + .drain + .orDie *> ZIO.never + +object BlazeHttpServer: + val layer: RLayer[BlazeServerConfig, HttpServer] = ZLayer { + for config <- ZIO.service[BlazeServerConfig] + yield BlazeHttpServer(config) + } diff --git a/server/http/src/main/scala/works/iterative/server/http/impl/blaze/BlazeServerConfig.scala b/server/http/src/main/scala/works/iterative/server/http/impl/blaze/BlazeServerConfig.scala new file mode 100644 index 0000000..3d6a837 --- /dev/null +++ b/server/http/src/main/scala/works/iterative/server/http/impl/blaze/BlazeServerConfig.scala @@ -0,0 +1,20 @@ +package works.iterative.server.http.impl.blaze + +import zio.* +import zio.config.* + +case class BlazeServerConfig(host: String, port: Int) + +object BlazeServerConfig: + val configDesc: ConfigDescriptor[BlazeServerConfig] = + import ConfigDescriptor.* + nested("BLAZE")( + string("HOST").default("localhost") zip int("PORT").default(8080) + ).to[BlazeServerConfig] + + val fromEnv: ZLayer[Any, ReadError[String], BlazeServerConfig] = + ZConfig.fromSystemEnv( + configDesc, + keyDelimiter = Some('_'), + valueDelimiter = Some(',') + )