Skip to content

Commit

Permalink
Kebs 2.0 package cleanup (#380)
Browse files Browse the repository at this point in the history
* Renaming packages for spray & play json.

* Fixing pekko-http Scala 2/3 division.

* Refactoring tests for doobie.

* Refactoring circe tests.

* Cleaning up http4s package.

* Adding previously removed doobie tests.

* Refactor of scalacheck package

* Mergin spray-json-macros and spray-json.

* Fixing akka-http to work with generic EnumLike

* Merging pekko-http tests.

* Removing bunch of useless classtags

* Merging http4s-stir implementation and tests.

* Removing legacy `sv` from build.sbt

* Cleaning up akka-http, pekko-http and http4s-stir.

* Circe cleanup.

* Naming fix Enum -> Enums in Circe

* Doobie cleanup.

* Http4s cleanup

* jsonschema cleanup

* Cleaning up play-json, adding enums.

* Fixing scalacheck

* Slick trait visibility fix.

* Cleanup spray-json.

* Cleanup tagged.
  • Loading branch information
luksow authored Aug 7, 2024
1 parent fc933b5 commit daad478
Show file tree
Hide file tree
Showing 138 changed files with 944 additions and 2,383 deletions.
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
package pl.iterators.kebs.akkahttp.matchers

import akka.http.scaladsl.server.{PathMatcher1, PathMatchers}
import enumeratum.{Enum, EnumEntry}
import pl.iterators.kebs.core.enums.{EnumLike, ValueEnumLike, ValueEnumLikeEntry}
import pl.iterators.kebs.core.instances.InstanceConverter
import pl.iterators.kebs.core.macros.ValueClassLike

trait KebsMatchers extends PathMatchers {

trait KebsAkkaHttpMatchers extends PathMatchers {
implicit class SegmentIsomorphism[U](segment: PathMatcher1[U]) {
def as[T](implicit rep: ValueClassLike[T, U]): PathMatcher1[T] = segment.map(rep.apply)
def as[T](implicit rep: ValueClassLike[T, U]): PathMatcher1[T] = segment.map(rep.apply)
def asValueEnum[T <: ValueEnumLikeEntry[U]](implicit e: ValueEnumLike[U, T]): PathMatcher1[T] = segment.map(e.withValue)
}

implicit class SegmentConversion[Source](segment: PathMatcher1[Source]) {
def to[Type](implicit ico: InstanceConverter[Type, Source]): PathMatcher1[Type] = segment.map(ico.decode)
}

object EnumSegment {
def as[T <: EnumEntry: Enum]: PathMatcher1[T] = {
val enumCompanion = implicitly[Enum[T]]
Segment.map(enumCompanion.withNameInsensitive)
}
implicit class SegmentEnumIsomorphism[U](segment: PathMatcher1[String]) {
def asEnum[T](implicit e: EnumLike[T]): PathMatcher1[T] = segment.map(e.withNameIgnoreCase)
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package pl.iterators.kebs.akkahttp

package object matchers extends KebsMatchers
package object matchers extends KebsAkkaHttpMatchers
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package pl.iterators.kebs.akkahttp.unmarshallers.enums
package pl.iterators.kebs.akkahttp.unmarshallers

import akka.http.scaladsl.unmarshalling.PredefinedFromStringUnmarshallers._
import akka.http.scaladsl.unmarshalling.{FromStringUnmarshaller, Unmarshaller}
import pl.iterators.kebs.core.instances.InstanceConverter
import pl.iterators.kebs.core.macros.ValueClassLike
import akka.http.scaladsl.util.FastFuture
import akka.http.scaladsl.unmarshalling.PredefinedFromStringUnmarshallers._
import pl.iterators.kebs.core.enums.{EnumLike, ValueEnumLike, ValueEnumLikeEntry}

trait EnumUnmarshallers {
final def enumUnmarshaller[E](`enum`: EnumLike[E]): FromStringUnmarshaller[E] = Unmarshaller { _ => name =>
trait KebsAkkaHttpEnumUnmarshallers {
private final def enumUnmarshaller[E](`enum`: EnumLike[E]): FromStringUnmarshaller[E] = Unmarshaller { _ => name =>
`enum`.withNameInsensitiveOption(name) match {
case Some(enumEntry) => FastFuture.successful(enumEntry)
case None =>
Expand All @@ -21,7 +23,7 @@ trait EnumUnmarshallers {
enumUnmarshaller(ev)
}

trait ValueEnumUnmarshallers {
trait KebsAkkaHttpValueEnumUnmarshallers {
final def valueEnumUnmarshaller[V, E <: ValueEnumLikeEntry[V]](`enum`: ValueEnumLike[V, E]): Unmarshaller[V, E] = Unmarshaller {
_ => v =>
`enum`.withValueOption(v) match {
Expand Down Expand Up @@ -55,4 +57,23 @@ trait ValueEnumUnmarshallers {
byteFromStringUnmarshaller andThen valueEnumUnmarshaller(ev)
}

trait KebsEnumUnmarshallers extends EnumUnmarshallers with ValueEnumUnmarshallers {}
trait KebsAkkaHttpUnmarshallers extends KebsAkkaHttpEnumUnmarshallers with KebsAkkaHttpValueEnumUnmarshallers {
implicit def kebsUnmarshaller[A, B](implicit rep: ValueClassLike[B, A]): Unmarshaller[A, B] =
Unmarshaller.strict[A, B](rep.apply)
@inline
implicit def kebsFromStringUnmarshaller[A, B](implicit
rep: ValueClassLike[B, A],
fsu: FromStringUnmarshaller[A]
): FromStringUnmarshaller[B] =
fsu andThen kebsUnmarshaller(rep)

implicit def kebsInstancesUnmarshaller[A, B](implicit ico: InstanceConverter[B, A]): Unmarshaller[A, B] =
Unmarshaller.strict[A, B](ico.decode)
@inline
implicit def kebsInstancesFromStringUnmarshaller[A, B](implicit
ico: InstanceConverter[B, A],
fsu: FromStringUnmarshaller[A]
): FromStringUnmarshaller[B] =
fsu andThen kebsInstancesUnmarshaller(ico)

}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package pl.iterators.kebs.akkahttp

package object unmarshallers extends KebsUnmarshallers
package object unmarshallers extends KebsAkkaHttpUnmarshallers
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers
import pl.iterators.kebs.akkahttp.domain.Domain.Greeting
import pl.iterators.kebs.akkahttp.domain.Domain._
import pl.iterators.kebs.core.macros.CaseClass1ToValueClass
import pl.iterators.kebs.enumeratum.{KebsEnumeratum, KebsValueEnumeratum}
import pl.iterators.kebs.instances.net.URIString
import pl.iterators.kebs.instances.time.{DayOfWeekInt, ZonedDateTimeString}
import pl.iterators.kebs.instances.time.mixins.InstantEpochMilliLong
Expand All @@ -23,6 +24,9 @@ class AkkaHttpMatchersTests
with ZonedDateTimeString
with DayOfWeekInt
with InstantEpochMilliLong
with KebsEnumeratum
with KebsValueEnumeratum
with CaseClass1ToValueClass
with URIString {

test("No ValueClassLike implicits derived") {
Expand Down Expand Up @@ -90,14 +94,32 @@ class AkkaHttpMatchersTests
}

test("Extract String as Enum") {
val testRoute = path("test" / EnumSegment.as[Greeting]) { greeting =>
val testRoute = path("test" / Segment.asEnum[Greeting]) { greeting =>
complete(greeting.toString)
}
Get("/test/hello") ~> testRoute ~> check {
responseAs[String] shouldEqual "Hello"
}
}

test("Extract String as value class") {
val testRoute = path("test" / Segment.as[S]) { item =>
complete(item.toString)
}
Get("/test/check") ~> testRoute ~> check {
responseAs[String] shouldEqual "S(check)"
}
}

test("Extract Int as ValueEnum") {
val testRoute = path("test" / IntNumber.asValueEnum[LibraryItem]) { item =>
complete(item.toString)
}
Get("/test/1") ~> testRoute ~> check {
responseAs[String] shouldEqual "Book"
}
}

test("Extract String to URI as tagged URI") {
val testRoute = path("test" / Segment.to[URI].as[TestTaggedUri]) { id =>
complete(id.toString)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import pl.iterators.kebs.akkahttp.domain.Domain._
import pl.iterators.kebs.instances.net.URIString
import pl.iterators.kebs.instances.time.{DayOfWeekInt, YearMonthString}
import pl.iterators.kebs.enumeratum.{KebsEnumeratum, KebsValueEnumeratum}
import pl.iterators.kebs.akkahttp.unmarshallers.enums.KebsEnumUnmarshallers
import pl.iterators.kebs.core.macros.CaseClass1ToValueClass

import java.time.{DayOfWeek, YearMonth}
Expand All @@ -23,8 +22,7 @@ class AkkaHttpUnmarshallersTests
with ScalatestRouteTest
with ScalaFutures
with Directives
with KebsUnmarshallers
with KebsEnumUnmarshallers
with KebsAkkaHttpUnmarshallers
with URIString
with YearMonthString
with DayOfWeekInt
Expand Down
40 changes: 8 additions & 32 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,6 @@ def disableScala(v: List[String]) =
)

def optional(dependency: ModuleID) = dependency % "provided"
def sv[A](scalaVersion: String, scala2_12Version: => A, scala2_13Version: => A) =
CrossVersion.partialVersion(scalaVersion) match {
case Some((2, 13)) => scala2_13Version
case Some((2, 12)) => scala2_12Version
case _ =>
throw new IllegalArgumentException(s"Unsupported Scala version $scalaVersion")
}

def paradiseFlag(scalaVersion: String): Seq[String] =
if (scalaVersion == scala_3)
Expand All @@ -118,11 +111,10 @@ val circeParser = "io.circe" %% "circe-parser" % circeV

val jsonschema = "com.github.andyglow" %% "scala-jsonschema" % "0.7.11"

val scalacheck = "org.scalacheck" %% "scalacheck" % "1.18.0" % "test"
val scalacheck = "org.scalacheck" %% "scalacheck" % "1.18.0"

val scalacheckMagnolify = "com.spotify" % "magnolify-scalacheck" % "0.7.3"
val scalacheckDerived = "io.github.martinhh" %% "scalacheck-derived" % "0.4.2"
val scalacheckEnumeratum = "com.beachape" %% "enumeratum-scalacheck" % "1.7.4"

val enumeratumVersion = "1.7.4"
val enumeratumPlayJsonVersion = "1.8.1"
Expand Down Expand Up @@ -206,16 +198,14 @@ lazy val enumeratumSettings = commonMacroSettings ++ Seq(
scalacOptions ++= paradiseFlag(scalaVersion.value)
)

lazy val sprayJsonMacroSettings = commonMacroSettings ++ Seq(
libraryDependencies += sprayJson.cross(CrossVersion.for3Use2_13)
)

lazy val sprayJsonSettings = commonSettings ++ Seq(
libraryDependencies += sprayJson.cross(CrossVersion.for3Use2_13),
libraryDependencies += optionalEnumeratum
)

lazy val playJsonSettings = commonSettings ++ Seq(
libraryDependencies += playJson
libraryDependencies += playJson,
libraryDependencies += (enumeratum % "test")
)

lazy val circeSettings = commonSettings ++ Seq(
Expand Down Expand Up @@ -264,7 +254,7 @@ lazy val jsonschemaSettings = commonSettings ++ Seq(

lazy val scalacheckSettings = commonSettings ++ Seq(
libraryDependencies += scalacheck,
libraryDependencies += scalacheckEnumeratum
libraryDependencies += (enumeratum % "test"),
) ++ Seq(
libraryDependencies ++= (if (scalaVersion.value.startsWith("3")) Seq(scalacheckDerived)
else Nil)
Expand Down Expand Up @@ -330,22 +320,9 @@ lazy val doobieSupport = project
crossScalaVersions := supportedScalaVersions
)

lazy val sprayJsonMacros = project
.in(file("spray-json-macros"))
.dependsOn(core.jvm)
.settings(sprayJsonMacroSettings *)
.settings(publishSettings *)
.settings(disableScala(List("3")))
.settings(
name := "spray-json-macros",
description := "Automatic generation of Spray json formats for case-classes - macros",
moduleName := "kebs-spray-json-macros",
crossScalaVersions := supportedScalaVersions
)

lazy val sprayJsonSupport = project
.in(file("spray-json"))
.dependsOn(sprayJsonMacros, enumeratumSupport, instances % "test -> test")
.dependsOn(enumeratumSupport, instances % "test -> test")
.settings(sprayJsonSettings *)
.settings(publishSettings *)
.settings(disableScala(List("3")))
Expand All @@ -358,7 +335,7 @@ lazy val sprayJsonSupport = project

lazy val playJsonSupport = project
.in(file("play-json"))
.dependsOn(core.jvm, instances % "test -> test")
.dependsOn(core.jvm, enumeratumSupport, enumSupport, instances % "test -> test")
.settings(playJsonSettings *)
.settings(publishSettings *)
.settings(
Expand Down Expand Up @@ -451,7 +428,7 @@ lazy val jsonschemaSupport = project

lazy val scalacheckSupport = project
.in(file("scalacheck"))
.dependsOn(core.jvm, opaque.jvm % "test -> test")
.dependsOn(core.jvm, enumSupport, opaque.jvm % "test -> test")
.settings(scalacheckSettings *)
.settings(publishSettings *)
.settings(
Expand Down Expand Up @@ -564,7 +541,6 @@ lazy val kebs = project
core.js,
slickSupport,
doobieSupport,
sprayJsonMacros,
sprayJsonSupport,
playJsonSupport,
circeSupport,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,13 @@ trait KebsCirce extends AutoDerivation {

implicit def instanceConverterDecoder[T, A](implicit rep: InstanceConverter[T, A], decoder: Decoder[A]): Decoder[T] =
decoder.emap(obj => Try(rep.decode(obj)).toEither.left.map(_.getMessage))
}

object KebsCirce {

trait Snakified extends KebsCirce {
trait KebsCirceSnakified extends KebsCirce {
implicit def genericSnakifiedDecoder[T <: Product]: Decoder[T] = macro KebsCirceMacros.SnakifyVariant.materializeDecoder[T]
implicit def genericSnakifiedEncoder[T <: Product]: Encoder[T] = macro KebsCirceMacros.SnakifyVariant.materializeEncoder[T]
}

trait Capitalized extends KebsCirce {
trait KebsCirceCapitalized extends KebsCirce {
implicit def genericCapitalizedDecoder[T <: Product]: Decoder[T] = macro KebsCirceMacros.CapitalizedCamelCase.materializeDecoder[T]
implicit def genericCapitalizedEncoder[T <: Product]: Encoder[T] = macro KebsCirceMacros.CapitalizedCamelCase.materializeEncoder[T]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,12 @@ trait KebsCirce extends KebsAutoDerivation {

inline implicit def instanceConverterDecoder[T, A](using rep: InstanceConverter[T, A], decoder: Decoder[A]): Decoder[T] =
decoder.emap(obj => Try(rep.decode(obj)).toEither.left.map(_.getMessage))
}

object KebsCirce {

trait Snakified extends KebsCirce {
trait KebsCirceSnakified extends KebsCirce {
override implicit val configuration: Configuration = Configuration.default.withSnakeCaseMemberNames
}

trait Capitalized extends KebsCirce {
trait KebsCirceCapitalized extends KebsCirce {
override implicit val configuration: Configuration = Configuration.default.withPascalCaseMemberNames
}
}
Loading

0 comments on commit daad478

Please sign in to comment.