0
votes

I'm using Sangria for a Play application and currently struggling to implement the schema definition. The Problem is, that the service does not return the needed object directly, it returns an EitherT containing the object.

Here are some code examples

case class

case class User(name: String, age: Int)

UserService

def user(): EitherT[Future, AbstractError, User] = {...}

If the service would return a User instead of a EitherT[Future, AbstractError, User] I would derive the schema like this:

Schema

  val UserType = deriveObjectType[UserService, User]( 
      ObjectTypeName("User"),
      ObjectTypeDescription("A simple user."))

Do I have to implement an additional layer to extract the User from the EitherT object or is there another way to handle this situation?

2

2 Answers

1
votes

You can still derive the User object type since it is just a simple case class. For other GraphQL fields that load the users and return EitherT you would need to transform the value to something that sangria can work with (which means that these fields need to be defined manually, but you still can use derive* macros for other fields). The most simple approach would be to fold it to a simple Future[User]. Future is able to hold the error or the success result. If you would have a list of errors inside of the Either, then you can just wrap it in some custom exception, and then unwrap and properly render it in the ExceptionHandler.

0
votes

You can also use an implicit conversion from cats EitherT to a sangria FutureValue somewhere in your schema :

implicit def eithertAction[Ctx, Val, E <: Throwable](value: EitherT[Future, E, Val]): ReduceAction[Ctx, Val] = FutureValue(value.valueOrF(Future.failed))