Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#203: Wrap POST body as in wiro (closes #203) #212

Merged
merged 14 commits into from
Apr 22, 2020

Conversation

tpetrucciani
Copy link
Contributor

@tpetrucciani tpetrucciani commented Mar 30, 2020

Closes #2520577

⚠️ The line above was added during the automatic migration of all github project issues to Kaiten. The old GH issue link is kept here for reference (it is now deprecated, continue follow the original issue on Kaiten).

Closes #203

Notes:

  • The wrapper classes are generated in the tapir endpoints file.
  • To ensure that they have instances for JsonCodec, I've added an import of import sttp.tapir.json.circe._ to that file (so it can generate JsonCodec instances given Circe Encoder and Decoder) and added the Circe semiauto derivation of the Encoder and Decoder, adding implicit parameters of Encoder and Decoder for field names.
  • Not very nice: in the implicits we're now mixing tapir JsonCodec/PlainCodec with circe Encoder/Decoder, it would be maybe nicer to always require JsonCodec and be able to derive the JsonCodec for the case class from those of the fields, but I couldn't find a way to do it.
  • It's also not nice that we need Encoder, but tapir always expects both to be able to describe clients I think.

For example, for the controller

@path("test")
trait TestController[F[_], AuthToken] {
  @command
  def pusho(x: Obj1, y: Obj2): F[Either[Error1, String]]
}

case class Obj1(name: String)
case class Obj2(name: String)

we generate the tapir endpoints

trait TestTapirEndpoints[AuthToken] {
  val pusho: Endpoint[PushoRequestPayload, Error1, String, Nothing]
}

object TestTapirEndpoints {

  def create[AuthToken](statusCodes: String => StatusCode)(
      implicit codec0: JsonCodec[Error1],
      codec1: JsonCodec[String],
      codec2: Decoder[Obj1],
      codec3: Encoder[Obj1],
      codec4: Decoder[Obj2],
      codec5: Encoder[Obj2]
  ) = new TestTapirEndpoints[AuthToken] {
    implicit val pushoRequestPayloadDecoder: Decoder[PushoRequestPayload] =
      deriveDecoder
    implicit val pushoRequestPayloadEncoder: Encoder[PushoRequestPayload] =
      deriveEncoder
    override val pusho: Endpoint[PushoRequestPayload, Error1, String, Nothing] =
      endpoint.post
        .in("pusho")
        .in(jsonBody[PushoRequestPayload])
        .errorOut(jsonBody[Error1])
        .out(jsonBody[String])
  }
}

case class PushoRequestPayload(x: Obj1, y: Obj2)

and the http4s endpoints

object TestHttpEndpoints {
  def routes[F[_]: Sync, AuthToken](
      controller: TestController[F, AuthToken],
      statusCodes: String => StatusCode = _ => StatusCode.UnprocessableEntity
  )(
      implicit codec0: JsonCodec[Error1],
      codec1: JsonCodec[String],
      codec2: Decoder[Obj1],
      codec3: Encoder[Obj1],
      codec4: Decoder[Obj2],
      codec5: Encoder[Obj2],
      cs: ContextShift[F]
  ): HttpRoutes[F] = {
    val endpoints = TestTapirEndpoints.create[AuthToken](statusCodes)
    val pusho = endpoints.pusho.toRoutes(x => controller.pusho(x.x, x.y))
    Router("/test" -> NonEmptyList(pusho, List()).reduceK)
  }
}

Test Plan

Tested on a small example project

@@ -9,33 +9,42 @@ import cats.data.NonEmptyList
object Meta {
val codecsImplicits = (routes: List[TapiroRoute]) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is getting quite messy...

Part of the problem is that we're delaying the conversion to scalameta type for each type of codec because we want to call .distinct while we still have a list of metarpheus types, because it wouldn't work on scalameta types because == is by reference

Maybe we could use structural equality from scala.meta.contrib (https://scalameta.org/docs/trees/guide.html#compare-trees-for-equality) to clean this up a bit?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using isEqual is a good idea

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried to rewrite that function and I think it reads a bit better now

Copy link
Member

@gabro gabro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made a first pass: overall it looks like a good approach.

It would be nice to add unit tests before merging, once #211 is in

Comment on lines 53 to 55
case 0 => q"_ => $controllersName()"
case 1 => controllersName
case _ => q"($controllersName _).tupled"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}
case RouteMethod.POST =>
val fields = route.route.params
.filterNot(_.tpe == MetarpheusType.Name("AuthToken"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it correct that we hardcode AuthToken here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's sort-of-correct right now because we're hardcoding it everywhere anyway, so we expect the type parameter in the controller trait to be always named exactly AuthToken. As I understand it, we should fix that in #204 when we change metarpheus to return the real name of the type parameter

q"x => $controllersName(..${fields.map(f => q"x.$f")})"
}
val toRoute = q"$endpointsName.toRoute($controllerContent)"
q"val ${Pat.Var(name)} = $toRoute"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor, but I think this can be

Suggested change
q"val ${Pat.Var(name)} = $toRoute"
q"val $name = $toRoute"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't get this to work 🙁 it expects a Pat there and $name is a Term.Name, which doesn't seem to work (using a String instead compiles but generates a literal string pattern)

Comment on lines 48 to 68
val endpoints = (routes: List[TapiroRoute]) =>
routes.map { route =>
val name = Term.Name(route.route.name.last)
val endpointsName = q"endpoints.$name"
val controllersName = q"controller.$name"
val controllerContent =
if (route.params.length <= 1) Some(controllersName)
else Some(Term.Select(Term.Eta(controllersName), Term.Name("tupled")))
controllerContent.map { content =>
val toRoutes = Term.Apply(Term.Select(endpointsName, Term.Name("toRoutes")), List(content))
q"val ${Pat.Var(name)} = $toRoutes"
}
route.method match {
case RouteMethod.GET =>
route.route.params.length match {
case 0 => q"_ => $controllersName()"
case 1 => controllersName
case _ => q"($controllersName _).tupled"
}
case RouteMethod.POST =>
val fields = route.route.params
.filterNot(_.tpe == MetarpheusType.Name("AuthToken"))
.map(p => Term.Name(p.name.getOrElse(Meta.typeNameString(p.tpe))))
q"x => $controllersName(..${fields.map(f => q"x.$f")})"
}
val toRoutes = q"$endpointsName.toRoutes($controllerContent)"
q"val ${Pat.Var(name)} = $toRoutes"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems identical to the same code in AkkaHttpMeta. Can we deduplicate it? (Not necessarily in this PR)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've factored out most of the duplication while fixing bugs

There's still some duplicated code here and there that processes route parameters (filtering out the auth param, computing default param names from their types if missing, etc.) which I think we should factor out, but it's best done in another PR I think

In particular, I think we could include in TapiroRoute a "cleaned" version of the route parameters, already processed so we don't have to do the same processing in different functions

@@ -9,33 +9,42 @@ import cats.data.NonEmptyList
object Meta {
val codecsImplicits = (routes: List[TapiroRoute]) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using isEqual is a good idea

@giuscri
Copy link
Contributor

giuscri commented Apr 2, 2020

This generates wrong endpoints for code at https://github.com/buildo/banksealer/pull/2413 as of commit https://github.com/buildo/banksealer/pull/2413/commits/48d6003dd082a43899489cde7d925a59f7107849

I launched tapiro via

git reset --hard 6c38fb9eef40be61491ce11aac3ee1531ff33a52
sbt "project tapiroCore" "runMain io.buildo.tapiro.Main"

where Main is

package io.buildo.tapiro

import sbt.internal.util.ManagedLogger

object Main extends App {
  (new Util(new ManagedLogger("tapiro", None, None, null))).createFiles(
    List("/Users/g/banksealer/cloud/backend/services/userManager"),
    List("/Users/g/banksealer/cloud/backend/services/userManager"),
    "/Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints",
    List("userManager"),
    Server.Http4s
  )
}

then compiled the target service (called userManager) via

cd /Users/g/banksealer/cloud/backend
git reset --hard 591a81dc2211fb72adf5974bd72b5afb90d13ff6
sbt "project userManager" clean compile

and got the following

[info] Loading settings for project backend-build from plugins.sbt ...
[info] Loading project definition from /Users/g/banksealer/cloud/backend/project
[info] Loading settings for project backend from build.sbt ...
[info] Set current project to backend (in build file:/Users/g/banksealer/cloud/backend/)
[info] Executing in batch mode. For better performance use sbt's shell
[info] Set current project to userManager (in build file:/Users/g/banksealer/cloud/backend/)
[success] Total time: 0 s, completed Apr 2, 2020 12:09:08 PM
[warn] There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings.
[info] Compiling 29 Scala sources to /Users/g/banksealer/cloud/backend/services/userManager/target/scala-2.12/classes ...
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:97:11: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(AuthToken, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[AuthToken,userManager.GenericError,Set[userManager.User],Nothing]
[error]       .out(jsonBody[Set[User]])
[error]           ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:104:11: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(AuthToken, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[AuthToken,userManager.GenericError,Set[userManager.Group],Nothing]
[error]       .out(jsonBody[Set[Group]])
[error]           ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:112:13: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(userManager.AddUserRequestPayload, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[userManager.AddUserRequestPayload,userManager.GenericError,userManager.UserId,Nothing]
[error]         .out(jsonBody[UserId])
[error]             ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:120:13: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(userManager.ChangeGroupRequestPayload, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[userManager.ChangeGroupRequestPayload,userManager.GenericError,userManager.UserId,Nothing]
[error]         .out(jsonBody[UserId])
[error]             ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:128:13: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(userManager.ResetPasswordRequestPayload, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[userManager.ResetPasswordRequestPayload,userManager.GenericError,userManager.UserId,Nothing]
[error]         .out(jsonBody[UserId])
[error]             ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:136:13: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(userManager.DeleteUserRequestPayload, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[userManager.DeleteUserRequestPayload,userManager.GenericError,userManager.UserId,Nothing]
[error]         .out(jsonBody[UserId])
[error]             ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:144:13: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(AuthToken, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[AuthToken,userManager.GenericError,List[userManager.AuditLogMetaData],Nothing]
[error]         .out(jsonBody[List[AuditLogMetaData]])
[error]             ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:153:13: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(String, AuthToken, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[(String, AuthToken),userManager.GenericError,userManager.MyFile,Nothing]
[error]         .out(jsonBody[MyFile])
[error]             ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerHttpEndpoints.scala:47:69: not enough arguments for method addUser: (request: userManager.NewUserRequest, token: AuthToken)F[Either[userManager.GenericError,userManager.UserId]].
[error] Unspecified value parameter token.
[error]     val addUser = endpoints.addUser.toRoutes(x => controller.addUser(x.request))
[error]                                                                     ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerHttpEndpoints.scala:49:34: not enough arguments for method changeGroup: (userId: userManager.UserId, groupId: userManager.GroupId, token: AuthToken)F[Either[userManager.GenericError,userManager.UserId]].
[error] Unspecified value parameter token.
[error]       x => controller.changeGroup(x.userId, x.groupId)
[error]                                  ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerHttpEndpoints.scala:52:36: not enough arguments for method resetPassword: (userId: userManager.UserId, password: String, token: AuthToken)F[Either[userManager.GenericError,userManager.UserId]].
[error] Unspecified value parameter token.
[error]       x => controller.resetPassword(x.userId, x.password)
[error]                                    ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerHttpEndpoints.scala:55:63: not enough arguments for method deleteUser: (userId: userManager.UserId, token: AuthToken)F[Either[userManager.GenericError,userManager.UserId]].
[error] Unspecified value parameter token.
[error]       endpoints.deleteUser.toRoutes(x => controller.deleteUser(x.userId))
[error]                                                               ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerHttpEndpoints.scala:9:20: Unused import
[warn] import userManager._
[warn]                    ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerHttpEndpoints.scala:11:23: Unused import
[warn] import cats.implicits._
[warn]                       ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:9:20: Unused import
[warn] import userManager._
[warn]                    ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:57:25: parameter value statusCodes in method create is never used
[warn]   def create[AuthToken](statusCodes: String => StatusCode)(
[warn]                         ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:66:7: parameter value codec8 in method create is never used
[warn]       codec8: Decoder[NewUserRequest],
[warn]       ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:67:7: parameter value codec9 in method create is never used
[warn]       codec9: Encoder[NewUserRequest],
[warn]       ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:68:7: parameter value codec10 in method create is never used
[warn]       codec10: Decoder[UserId],
[warn]       ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:69:7: parameter value codec11 in method create is never used
[warn]       codec11: Encoder[UserId],
[warn]       ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:70:7: parameter value codec12 in method create is never used
[warn]       codec12: Decoder[GroupId],
[warn]       ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:71:7: parameter value codec13 in method create is never used
[warn]       codec13: Encoder[GroupId],
[warn]       ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:72:7: parameter value codec14 in method create is never used
[warn]       codec14: Decoder[String],
[warn]       ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/AdminControllerTapirEndpoints.scala:73:7: parameter value codec15 in method create is never used
[warn]       codec15: Encoder[String]
[warn]       ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerTapirEndpoints.scala:112:18: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [EF]sttp.tapir.Endpoint[this.Out,EF,Unit,Nothing]
[error]     (which expands to)  [EF]sttp.tapir.Endpoint[(userManager.LogoutRequestPayload, AuthToken),EF,Unit,Nothing]
[error]  required: sttp.tapir.Endpoint[userManager.LogoutRequestPayload,userManager.MyAuthenticationError,Unit,Nothing]
[error]         .errorOut(jsonBody[MyAuthenticationError])
[error]                  ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerTapirEndpoints.scala:123:11: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.MyAuthenticationError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(userManager.ChangePasswordRequestPayload, AuthToken),userManager.MyAuthenticationError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[userManager.ChangePasswordRequestPayload,userManager.MyAuthenticationError,userManager.MyUserSubject,Nothing]
[error]       .out(jsonBody[MyUserSubject])
[error]           ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerTapirEndpoints.scala:131:13: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.MyAuthenticationError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(AuthToken, AuthToken),userManager.MyAuthenticationError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[AuthToken,userManager.MyAuthenticationError,Boolean,Nothing]
[error]         .out(jsonBody[Boolean])
[error]             ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerHttpEndpoints.scala:44:66: not enough arguments for method logout: (token: AuthToken)F[Either[userManager.MyAuthenticationError,Unit]].
[error] Unspecified value parameter token.
[error]     val logout = endpoints.logout.toRoutes(x => controller.logout())
[error]                                                                  ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerHttpEndpoints.scala:46:37: not enough arguments for method changePassword: (oldPassword: String, newPassword: String, token: AuthToken)F[Either[userManager.MyAuthenticationError,userManager.MyUserSubject]].
[error] Unspecified value parameter token.
[error]       x => controller.changePassword(x.oldPassword, x.newPassword)
[error]                                     ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerHttpEndpoints.scala:9:20: Unused import
[warn] import userManager._
[warn]                    ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerHttpEndpoints.scala:11:23: Unused import
[warn] import cats.implicits._
[warn]                       ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerHttpEndpoints.scala:44:44: parameter value x in value $anonfun is never used
[warn]     val logout = endpoints.logout.toRoutes(x => controller.logout())
[warn]                                            ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerTapirEndpoints.scala:9:20: Unused import
[warn] import userManager._
[warn]                    ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerTapirEndpoints.scala:57:25: parameter value statusCodes in method create is never used
[warn]   def create[AuthToken](statusCodes: String => StatusCode)(
[warn]                         ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerTapirEndpoints.scala:63:7: parameter value codec5 in method create is never used
[warn]       codec5: Decoder[MyLogin],
[warn]       ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerTapirEndpoints.scala:64:7: parameter value codec6 in method create is never used
[warn]       codec6: Encoder[MyLogin],
[warn]       ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerTapirEndpoints.scala:65:7: parameter value codec7 in method create is never used
[warn]       codec7: Decoder[MyRefreshToken],
[warn]       ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerTapirEndpoints.scala:66:7: parameter value codec8 in method create is never used
[warn]       codec8: Encoder[MyRefreshToken],
[warn]       ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerTapirEndpoints.scala:67:7: parameter value codec9 in method create is never used
[warn]       codec9: Decoder[String],
[warn]       ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/TokenAuthenticationControllerTapirEndpoints.scala:68:7: parameter value codec10 in method create is never used
[warn]       codec10: Encoder[String]
[warn]       ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerTapirEndpoints.scala:66:13: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(userManager.UserId, AuthToken, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[(userManager.UserId, AuthToken),userManager.GenericError,userManager.User,Nothing]
[error]         .out(jsonBody[User])
[error]             ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerTapirEndpoints.scala:75:13: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(String, AuthToken, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[(String, AuthToken),userManager.GenericError,userManager.User,Nothing]
[error]         .out(jsonBody[User])
[error]             ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerTapirEndpoints.scala:88:11: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(String, String, AuthToken, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[(String, String, AuthToken),userManager.GenericError,userManager.Authorization,Nothing]
[error]       .out(jsonBody[Authorization])
[error]           ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerTapirEndpoints.scala:101:11: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(userManager.UserId, String, AuthToken, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[(userManager.UserId, String, AuthToken),userManager.GenericError,userManager.Authorization,Nothing]
[error]       .out(jsonBody[Authorization])
[error]           ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerTapirEndpoints.scala:108:11: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(AuthToken, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[AuthToken,userManager.GenericError,userManager.User,Nothing]
[error]       .out(jsonBody[User])
[error]           ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerTapirEndpoints.scala:120:11: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(userManager.OperationName, AuthToken, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[(userManager.OperationName, AuthToken),userManager.GenericError,userManager.UserAndAuthorization,Nothing]
[error]       .out(jsonBody[UserAndAuthorization])
[error]           ^
[error] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerTapirEndpoints.scala:127:11: polymorphic expression cannot be instantiated to expected type;
[error]  found   : [OP]sttp.tapir.Endpoint[this.Out,userManager.GenericError,OP,Nothing]
[error]     (which expands to)  [OP]sttp.tapir.Endpoint[(AuthToken, AuthToken),userManager.GenericError,OP,Nothing]
[error]  required: sttp.tapir.Endpoint[AuthToken,userManager.GenericError,Boolean,Nothing]
[error]       .out(jsonBody[Boolean])
[error]           ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerHttpEndpoints.scala:9:20: Unused import
[warn] import userManager._
[warn]                    ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerHttpEndpoints.scala:13:18: Unused import
[warn] import io.circe.{Decoder, Encoder}
[warn]                  ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerHttpEndpoints.scala:13:27: Unused import
[warn] import io.circe.{Decoder, Encoder}
[warn]                           ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerTapirEndpoints.scala:9:20: Unused import
[warn] import userManager._
[warn]                    ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerTapirEndpoints.scala:10:18: Unused import
[warn] import io.circe.{Decoder, Encoder}
[warn]                  ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerTapirEndpoints.scala:10:27: Unused import
[warn] import io.circe.{Decoder, Encoder}
[warn]                           ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerTapirEndpoints.scala:11:35: Unused import
[warn] import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
[warn]                                   ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerTapirEndpoints.scala:11:50: Unused import
[warn] import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
[warn]                                                  ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerTapirEndpoints.scala:13:30: Unused import
[warn] import sttp.tapir.json.circe._
[warn]                              ^
[warn] /Users/g/banksealer/cloud/backend/services/userManager/src/main/scala/endpoints/UsersControllerTapirEndpoints.scala:47:25: parameter value statusCodes in method create is never used
[warn]   def create[AuthToken](statusCodes: String => StatusCode)(
[warn]                         ^
[warn] 33 warnings found
[error] 24 errors found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 13 s, completed Apr 2, 2020 12:09:21 PM

@tpetrucciani
Copy link
Contributor Author

Many thanks for the test @giuscri! I had indeed messed things up with with auth tokens 🙈

The version I just pushed (a8ecd98) should fix that. I still get an error on your code, but it seems unrelated (File vs MyFile in a controller trait vs implementation), could you check that too?

Adding some unit tests will surely be useful 😄

@calippo calippo removed their request for review April 7, 2020 10:59
@calippo
Copy link
Member

calippo commented Apr 7, 2020

I removed myself as an assignee enough people is working on this :D

@tpetrucciani tpetrucciani mentioned this pull request Apr 10, 2020
gabro
gabro previously approved these changes Apr 16, 2020
Copy link
Member

@gabro gabro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two minor comments, but otherwise LGTM!

@@ -5,7 +5,7 @@ import java.nio.file.Files
class TapiroSuite extends munit.FunSuite {

check(
"http4s",
"tapir and http4s endpoints",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: let's try to keep test names short and without spaces, so that they're easily selectable for testOnly.

E.g.

tapiroCore/testOnly -- io.buildo.tapiro.TapiroSuite.tapir-http4s-endpoints

@@ -44,17 +45,10 @@ object Http4sMeta {
q"Router($route -> NonEmptyList($first, List(..$rest)).reduceK)"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not related to this PR, but this can be:

Suggested change
q"Router($route -> NonEmptyList($first, List(..$rest)).reduceK)"
q"Router($route -> NonEmptyList.of(first, rest: _*).reduceK)"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Wrap POST body as in wiro
5 participants