Skip to content

Commit 129670b

Browse files
Copying over akka-http module
1 parent b0dcf44 commit 129670b

37 files changed

+6739
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dev.guardrail.generators.scala.akkaHttp.AkkaHttpClientGeneratorLoader
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dev.guardrail.generators.scala.akkaHttp.AkkaHttpGeneratorLoader
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dev.guardrail.generators.scala.akkaHttp.AkkaHttpServerGeneratorLoader

modules/scala-pekko-http/src/main/scala/dev/guardrail/generators/scala/akkaHttp/AkkaHttpClientGenerator.scala

Lines changed: 642 additions & 0 deletions
Large diffs are not rendered by default.

modules/scala-pekko-http/src/main/scala/dev/guardrail/generators/scala/akkaHttp/AkkaHttpGenerator.scala

Lines changed: 469 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package dev.guardrail.generators.scala.akkaHttp
2+
3+
import cats.data.NonEmptyList
4+
import cats.syntax.all._
5+
import dev.guardrail.{ RuntimeFailure, Target }
6+
import dev.guardrail.core.Tracker
7+
import dev.guardrail.generators.scala.{ CirceModelGenerator, JacksonModelGenerator, ModelGeneratorType }
8+
import dev.guardrail.terms.{ ApplicationJson, ContentType, TextPlain }
9+
import scala.meta._
10+
11+
object AkkaHttpHelper {
12+
def generateDecoder(tpe: Type, consumes: Tracker[NonEmptyList[ContentType]], modelGeneratorType: ModelGeneratorType): Target[(Term, Type)] = {
13+
val baseType = tpe match {
14+
case t"Option[$x]" => x
15+
case x => x
16+
}
17+
18+
for {
19+
unmarshallers <- consumes.indexedDistribute.toList.flatTraverse {
20+
case Tracker(_, _: ApplicationJson) => Target.pure(List(q"structuredJsonEntityUnmarshaller"))
21+
case Tracker(_, _: TextPlain) => Target.pure(List(q"stringyJsonEntityUnmarshaller"))
22+
case Tracker(history, contentType) => Target.log.warning(s"Unable to generate decoder for ${contentType} (${history})").map(_ => List.empty[Term.Name])
23+
}
24+
unmarshaller <- unmarshallers match {
25+
case Nil => Target.raiseUserError(s"No decoders available (${consumes.showHistory})")
26+
case x :: Nil => Target.pure(x)
27+
case xs => Target.pure(q"Unmarshaller.firstOf(..${xs})")
28+
}
29+
decode <- Target.fromOption(
30+
modelGeneratorType match {
31+
case _: CirceModelGenerator => Some(q"""io.circe.Decoder[${baseType}].decodeJson(json).fold(FastFuture.failed, FastFuture.successful)""")
32+
case _: JacksonModelGenerator =>
33+
Some(q"""FastFuture(implicitly[GuardrailDecoder[$baseType]].decode(json))""")
34+
case _ => None
35+
},
36+
RuntimeFailure(s"Unknown modelGeneratorType: ${modelGeneratorType}")
37+
)
38+
} yield {
39+
val decoder = q"""{ ${unmarshaller}.flatMap(_ => _ => json => $decode) }"""
40+
(decoder, baseType)
41+
}
42+
}
43+
44+
def fromStringConverter(tpe: Type, modelGeneratorType: ModelGeneratorType): Either[String, Term] = modelGeneratorType match {
45+
case _: CirceModelGenerator => Right(q"_root_.io.circe.Json.fromString(str).as[$tpe].toOption")
46+
case _: JacksonModelGenerator => Right(q"scala.util.Try(mapper.convertValue(str, new com.fasterxml.jackson.core.`type`.TypeReference[$tpe] {})).toOption")
47+
case _ => Left(s"Unknown modelGeneratorType: ${modelGeneratorType}")
48+
}
49+
50+
def protocolImplicits(modelGeneratorType: ModelGeneratorType): Target[Term.ParamClause] = modelGeneratorType match {
51+
case _: CirceModelGenerator => Target.pure(Term.ParamClause(Nil))
52+
case _: JacksonModelGenerator =>
53+
Target.pure(
54+
Term.ParamClause(
55+
List(
56+
param"mapper: com.fasterxml.jackson.databind.ObjectMapper",
57+
param"validator: javax.validation.Validator"
58+
),
59+
Some(Mod.Implicit())
60+
)
61+
)
62+
case _ => Target.raiseError(RuntimeFailure(s"Unknown modelGeneratorType: ${modelGeneratorType}"))
63+
}
64+
65+
def unmarshalFieldTypeParam(modelGeneratorType: ModelGeneratorType): Target[Type.Param] = modelGeneratorType match {
66+
case _: CirceModelGenerator => Target.pure(tparam"A: io.circe.Decoder")
67+
case _: JacksonModelGenerator => Target.pure(tparam"A: GuardrailDecoder: GuardrailValidator: scala.reflect.ClassTag")
68+
case _ => Target.raiseError(RuntimeFailure(s"Unknown modelGeneratorType: ${modelGeneratorType}"))
69+
}
70+
71+
def unmarshalFieldUnmarshallerType(modelGeneratorType: ModelGeneratorType): Target[Type] = modelGeneratorType match {
72+
case _: CirceModelGenerator => Target.pure(t"io.circe.Json")
73+
case _: JacksonModelGenerator => Target.pure(t"com.fasterxml.jackson.databind.JsonNode")
74+
case _ => Target.raiseError(RuntimeFailure(s"Unknown modelGeneratorType: ${modelGeneratorType}"))
75+
}
76+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package dev.guardrail.generators.scala.akkaHttp
2+
3+
import scala.meta._
4+
5+
import dev.guardrail.core.PathExtractor
6+
import dev.guardrail.generators.scala.{ ModelGeneratorType, ScalaLanguage }
7+
import dev.guardrail.generators.LanguageParameter
8+
9+
object AkkaHttpPathExtractor
10+
extends PathExtractor[ScalaLanguage, Term, Term.Name, ModelGeneratorType](
11+
pathSegmentConverter = { case (LanguageParameter(_, param, _, argName, argType), base, modelGeneratorType) =>
12+
base.fold {
13+
argType match {
14+
case t"String" => Right(q"Segment")
15+
case t"Double" => Right(q"DoubleNumber")
16+
case t"BigDecimal" =>
17+
Right(q"Segment.map(BigDecimal.apply _)")
18+
case t"Int" => Right(q"IntNumber")
19+
case t"Long" => Right(q"LongNumber")
20+
case t"BigInt" => Right(q"Segment.map(BigInt.apply _)")
21+
case tpe =>
22+
AkkaHttpHelper
23+
.fromStringConverter(tpe, modelGeneratorType)
24+
.map(tpe => q"Segment.flatMap(str => ${tpe})")
25+
}
26+
} { segment =>
27+
argType match {
28+
case t"String" => Right(segment)
29+
case t"BigDecimal" =>
30+
Right(q"${segment}.map(BigDecimal.apply _)")
31+
case t"BigInt" => Right(q"${segment}.map(BigInt.apply _)")
32+
case tpe =>
33+
AkkaHttpHelper
34+
.fromStringConverter(tpe, modelGeneratorType)
35+
.map(tpe => q"${segment}.flatMap(str => ${tpe})")
36+
}
37+
}
38+
},
39+
buildParamConstraint = { case (k, v) =>
40+
q" parameter(${Lit.String(k)}).require(_ == ${Lit.String(v)}) "
41+
},
42+
joinParams = { (l, r) =>
43+
q"${l} & ${r}"
44+
},
45+
stringPath = Lit.String(_),
46+
liftBinding = identity,
47+
litRegex = (before, _, after) =>
48+
q"""new scala.util.matching.Regex("^" + ${Lit
49+
.String(before)} + "(.*)" + ${Lit.String(after)} + ${Lit.String("$")})"""
50+
)

0 commit comments

Comments
 (0)