From 2d5d645174e3aaa22c8e1790906bebcbb17ba273 Mon Sep 17 00:00:00 2001 From: Calvin Lee Fernandes Date: Sun, 1 Sep 2024 20:17:22 -0400 Subject: [PATCH] Add /graphiql route to caliban-to-tapir example (#2386) --- .../example/calibantotapir/MainApp.scala | 35 ++++++++++++++----- .../scala/example/calibantotapir/README.md | 6 ++-- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/examples/src/main/scala/example/calibantotapir/MainApp.scala b/examples/src/main/scala/example/calibantotapir/MainApp.scala index 2175faa7a6..d91d5b804a 100644 --- a/examples/src/main/scala/example/calibantotapir/MainApp.scala +++ b/examples/src/main/scala/example/calibantotapir/MainApp.scala @@ -7,26 +7,43 @@ import caliban._ import caliban.interop.tapir._ import sttp.tapir.json.jsoniter._ import sttp.capabilities.zio.ZioStreams +import sttp.tapir.ztapir.RIOMonadError import sttp.tapir.server.ziohttp._ import sttp.tapir.server.ServerEndpoint import sttp.tapir.swagger.bundle.SwaggerInterpreter import example.calibantotapir.tapir.SampleRestEndpoint +import sttp.monad.MonadError object MainApp extends ZIOAppDefault { + implicit val monadErrorForTask: MonadError[Task] = new RIOMonadError[Any] + + /** + * Creates a list of endpoints: + * - GraphiQL UI (GET /graphiql) + * - GraphQL API (POST & GET /graphql) + * - Example endpoint (GET /example) + */ val graphQLToTapir: ZIO[Queries & Mutations, CalibanError, List[ServerEndpoint[ZioStreams, Task]]] = for { - queries <- ZIO.service[Queries] - mutations <- ZIO.service[Mutations] - graphql = graphQL(RootResolver(queries, mutations)) - interpreter <- graphql.interpreter - endpoints = - HttpInterpreter(interpreter) - .serverEndpoints[Any, ZioStreams](ZioStreams) - .map(_.prependSecurityIn("graphql")) + queries <- ZIO.service[Queries] + mutations <- ZIO.service[Mutations] + graphql = graphQL(RootResolver(queries, mutations)) + interpreter <- graphql.interpreter + graphqlApiPath = "graphql" + // NOTE: We mount the GraphQL endpoints (POST and GET) on /graphql + graphqlEndpoints = HttpInterpreter(interpreter) + .serverEndpoints[Any, ZioStreams](ZioStreams) + .map(_.prependSecurityIn(graphqlApiPath)) + // NOTE: We make GraphiQL point to the api path hosted on /graphql and we mount the GraphiQL UI on /graphiql + graphiqlEndpoint = HttpInterpreter + .makeGraphiqlEndpoint[Task](apiPath = graphqlApiPath) + .prependSecurityIn("graphiql") + endpoints = graphiqlEndpoint :: graphqlEndpoints } yield endpoints + // Produces a Swagger UI for the endpoints on GET /docs def documented(allEndpoints: List[ServerEndpoint[ZioStreams, Task]]) = { - val doc = SwaggerInterpreter().fromServerEndpoints(allEndpoints, "playground", "1.0") + val doc = SwaggerInterpreter().fromServerEndpoints(allEndpoints, "Caliban tapir playground", "1.0") doc ++ allEndpoints } diff --git a/examples/src/main/scala/example/calibantotapir/README.md b/examples/src/main/scala/example/calibantotapir/README.md index e4e4e12979..12bffabfed 100644 --- a/examples/src/main/scala/example/calibantotapir/README.md +++ b/examples/src/main/scala/example/calibantotapir/README.md @@ -1,11 +1,11 @@ # Caliban to Tapir -This example shows how to convert a Caliban GraphQL datatypes and turn them into Tapir endpoints. +This example shows how to convert the Caliban `GraphQL` datatype and turn them into Tapir `Endpoint`s. This is useful when you have both REST APIs and GraphQL endpoints and you want to use Tapir to expose a unified API. -The example also shows how to mount the GraphQL endpoint to `POST` and `GET` `/graphql` as well as provide `/example` for a sample endpoint returning JSON. +The example also shows how to mount the GraphQL endpoint to `POST /graphql` and `GET /graphql`, the GraphiQL UI (`GET` `/graphiql`), as well as provide `GET /example` for a sample endpoint returning JSON. All of the endpoints are documented in Swagger. Visiting `localhost:8080/` or `/docs` will show the Swagger UI. This example interprets the Tapir endpoints using ZIO HTTP. -Note: If you are only using GraphQL endpoints, then you are much better of using the quick adapter instead of this. This example is provided for when you want to use both GraphQL and REST endpoints and have them managed by Tapir to gain the benefits of documentation. \ No newline at end of file +**Note:** If you are only using GraphQL endpoints, then you are much better of using the `quick` adapter instead of this. This example is provided for when you want to use both GraphQL and REST endpoints and have them managed by Tapir to gain the benefits of documentation. \ No newline at end of file