diff --git a/tapiro/core/src/main/scala/io/buildo/tapiro/Meta.scala b/tapiro/core/src/main/scala/io/buildo/tapiro/Meta.scala index d5ce5340..30e1c629 100644 --- a/tapiro/core/src/main/scala/io/buildo/tapiro/Meta.scala +++ b/tapiro/core/src/main/scala/io/buildo/tapiro/Meta.scala @@ -1,6 +1,6 @@ package io.buildo.tapiro -import io.buildo.metarpheus.core.intermediate.{TaggedUnion, Type => MetarpheusType} +import io.buildo.metarpheus.core.intermediate.{TaggedUnion, RouteParam, Type => MetarpheusType} import scala.meta._ import scala.meta.contrib._ @@ -20,20 +20,20 @@ object Meta { val inputImplicits = route.method match { case RouteMethod.GET => - nonAuthParamTypes.map(toScalametaType).map(toPlainCodec) + nonAuthParamTypes.map(metarpheusTypeToScalametaType).map(toPlainCodec) case RouteMethod.POST => - nonAuthParamTypes.map(toScalametaType).flatMap(t => List(toDecoder(t), toEncoder(t))) + nonAuthParamTypes.map(metarpheusTypeToScalametaType).flatMap(t => List(toDecoder(t), toEncoder(t))) } val outputImplicits = - List(route.route.returns).filter(notUnit).map(toScalametaType).map(toJsonCodec) + List(route.route.returns).filter(notUnit).map(metarpheusTypeToScalametaType).map(toJsonCodec) val errorImplicits = route.error match { case RouteError.TaggedUnionError(tu) => tu.values.map(taggedUnionMemberType(tu)).map(toJsonCodec) case RouteError.OtherError(t) => - List(t).filter(notUnit).map(toScalametaType).map(toJsonCodec) + List(t).filter(notUnit).map(metarpheusTypeToScalametaType).map(toJsonCodec) } - val authImplicits = authParamTypes.map(toScalametaType).map(toPlainCodec) + val authImplicits = authParamTypes.map(metarpheusTypeToScalametaType).map(toPlainCodec) inputImplicits ++ outputImplicits ++ errorImplicits ++ authImplicits } deduplicate(routes.flatMap(routeRequiredImplicits)).zipWithIndex.map(toImplicitParam.tupled) @@ -60,12 +60,17 @@ object Meta { case MetarpheusType.Name(name) => name } - val toScalametaType: MetarpheusType => Type = { + val metarpheusTypeToScalametaType: MetarpheusType => Type = { case MetarpheusType.Apply(name, args) => - Type.Apply(Type.Name(name), args.map(toScalametaType).toList) + Type.Apply(Type.Name(name), args.map(metarpheusTypeToScalametaType).toList) case MetarpheusType.Name(name) => Type.Name(name) } + val routeParamToScalametaType = (routeParam: RouteParam) => { + val t = metarpheusTypeToScalametaType(routeParam.tpe) + if (routeParam.required) t else t"Option[$t]" + } + val taggedUnionMemberType = (taggedUnion: TaggedUnion) => (member: TaggedUnion.Member) => { if (member.params.isEmpty) diff --git a/tapiro/core/src/main/scala/io/buildo/tapiro/TapirMeta.scala b/tapiro/core/src/main/scala/io/buildo/tapiro/TapirMeta.scala index 684e3190..30b8bdc2 100644 --- a/tapiro/core/src/main/scala/io/buildo/tapiro/TapirMeta.scala +++ b/tapiro/core/src/main/scala/io/buildo/tapiro/TapirMeta.scala @@ -56,10 +56,10 @@ object TapirMeta { q"val ${Pat.Var(Term.Name(route.route.name.tail.mkString))}: ${endpointType(route)} = ${endpointImpl(route)}" private[this] val endpointType = (route: TapiroRoute) => { - val returnType = toScalametaType(route.route.returns) + val returnType = metarpheusTypeToScalametaType(route.route.returns) val argsType = route.method match { case RouteMethod.GET => - val argsList = route.route.params.map(p => toScalametaType(p.tpe)) + val argsList = route.route.params.map(routeParamToScalametaType) argsList match { case Nil => Type.Name("Unit") case head :: Nil => head @@ -68,7 +68,7 @@ object TapirMeta { case RouteMethod.POST => val authTokenType = route.route.params .filter(_.tpe == MetarpheusType.Name(authTokenName)) - .map(t => toScalametaType(t.tpe)) + .map(t => metarpheusTypeToScalametaType(t.tpe)) .headOption val inputType = postInputType(route.route) authTokenType match { @@ -76,7 +76,7 @@ object TapirMeta { case None => inputType } } - val error = toScalametaType(route.error match { + val error = metarpheusTypeToScalametaType(route.error match { case RouteError.TaggedUnionError(t) => MetarpheusType.Name(t.name) case RouteError.OtherError(t) => t }) @@ -153,7 +153,7 @@ object TapirMeta { case RouteError.OtherError(MetarpheusType.Name("String")) => Term.Name("stringBody") case RouteError.OtherError(t) => - Term.ApplyType(Term.Name("jsonBody"), List(toScalametaType(t))) + Term.ApplyType(Term.Name("jsonBody"), List(metarpheusTypeToScalametaType(t))) }, ), ) @@ -183,7 +183,7 @@ object TapirMeta { List( Term.ApplyType( Term.Name("jsonBody"), - List(toScalametaType(returnType)), + List(metarpheusTypeToScalametaType(returnType)), ), ), ) @@ -195,7 +195,7 @@ object TapirMeta { Term.Select(endpoint, Term.Name("in")), List( Term.Apply( - Term.ApplyType(Term.Name("query"), List(toScalametaType(param.tpe))), + Term.ApplyType(Term.Name("query"), List(routeParamToScalametaType(param))), List(Lit.String(param.name.getOrElse(typeNameString(param.tpe)))), ), ), @@ -217,7 +217,7 @@ object TapirMeta { val params = route.route.params .filterNot(_.tpe == MetarpheusType.Name(authTokenName)) .map { p => - param"${Term.Name(p.name.getOrElse(typeNameString(p.tpe)))}: ${toScalametaType(p.tpe)}" + param"${Term.Name(p.name.getOrElse(typeNameString(p.tpe)))}: ${metarpheusTypeToScalametaType(p.tpe)}" } List(q"case class ${postInputType(route.route)}(..$params)") case RouteMethod.GET =>