Skip to content

Commit

Permalink
Merge branch 'series/2.x' into jsoniter-only-encoders-decoders
Browse files Browse the repository at this point in the history
# Conflicts:
#	adapters/akka-http/src/main/scala/caliban/AkkaHttpAdapter.scala
#	adapters/pekko-http/src/main/scala/caliban/PekkoHttpAdapter.scala
#	adapters/play/src/main/scala/caliban/PlayAdapter.scala
#	build.sbt
#	interop/tapir/src/main/scala/caliban/interop/tapir/HttpInterpreter.scala
  • Loading branch information
kyri-petrou committed Sep 14, 2024
2 parents 71d52ac + e3ec8dd commit 2fdb393
Show file tree
Hide file tree
Showing 68 changed files with 1,518 additions and 941 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
- checkout
- restore_cache:
key: sbtcache
- run: sbt 'set ThisBuild / scalaVersion := "2.12.19"; codegenScriptedScala3'
- run: sbt 'set ThisBuild / scalaVersion := "2.12.20"; codegenScriptedScala3'
- save_cache:
key: sbtcache
paths:
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Want to see your company here? [Submit a PR](https://github.com/ghostdogpr/calib
* [Devsisters](https://www.devsisters.com)
* [Fugo.ai](https://www.fugo.ai)
* [LeadIQ](https://leadiq.com)
* [Norwegian Agency for Shared Services in Education and Research](https://sikt.no/en/home)
* [Sanjagh.pro](https://sanjagh.pro)
* [Soundtrack Your Brand](https://www.soundtrackyourbrand.com)
* [StepZen](https://www.stepzen.com)
Expand Down
15 changes: 15 additions & 0 deletions adapters/akka-http/src/main/scala/caliban/AkkaHttpAdapter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import sttp.capabilities.WebSockets
import sttp.capabilities.akka.AkkaStreams
import sttp.capabilities.akka.AkkaStreams.Pipe
import sttp.model.StatusCode
import sttp.monad.{ FutureMonad, MonadError }
import sttp.tapir.PublicEndpoint
import sttp.tapir.model.ServerRequest
import sttp.tapir.server.ServerEndpoint
Expand All @@ -21,6 +22,8 @@ import zio.stream.ZStream
import scala.concurrent.{ ExecutionContext, Future }

class AkkaHttpAdapter private (private val options: AkkaHttpServerOptions)(implicit ec: ExecutionContext) {
private implicit val monadErrorFuture: MonadError[Future] = new FutureMonad

private val akkaInterpreter = AkkaHttpServerInterpreter(options)(ec)

def makeHttpService[R, E](
Expand Down Expand Up @@ -55,6 +58,18 @@ class AkkaHttpAdapter private (private val options: AkkaHttpServerOptions)(impli
)
)

/**
* Creates a route which serves the GraphiQL UI from CDN.
*
* @param apiPath The path at which the API can be introspected.
*
* @see [[https://github.com/graphql/graphiql/tree/main/examples/graphiql-cdn]]
*/
def makeGraphiqlService(apiPath: String): Route =
akkaInterpreter.toRoute(
HttpInterpreter.makeGraphiqlEndpoint[Future](apiPath)
)

private implicit def streamConstructor(implicit
runtime: Runtime[Any],
mat: Materializer
Expand Down
17 changes: 16 additions & 1 deletion adapters/http4s/src/main/scala/caliban/Http4sAdapter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ import sttp.capabilities.WebSockets
import sttp.capabilities.fs2.Fs2Streams
import sttp.capabilities.zio.ZioStreams
import sttp.tapir.Endpoint
import sttp.tapir.integ.cats.effect.CatsMonadError
import sttp.tapir.server.ServerEndpoint
import sttp.tapir.server.http4s.Http4sServerInterpreter
import sttp.tapir.server.http4s.ztapir.ZHttp4sServerInterpreter
import zio._
import zio.interop.catz.concurrentInstance
import zio.stream.interop.fs2z._
import zio.stream.ZStream
import zio.stream.interop.fs2z._

object Http4sAdapter {

Expand Down Expand Up @@ -46,6 +47,20 @@ object Http4sAdapter {
Http4sServerInterpreter().toRoutes(endpointF)
}

/**
* Creates a route which serves the GraphiQL UI from CDN.
*
* @param apiPath The path at which the API can be introspected.
*
* @see [[https://github.com/graphql/graphiql/tree/main/examples/graphiql-cdn]]
*/
def makeGraphiqlService[F[_]: Async](apiPath: String): HttpRoutes[F] = {
implicit val F: CatsMonadError[F] = new CatsMonadError[F]
Http4sServerInterpreter().toRoutes(
HttpInterpreter.makeGraphiqlEndpoint[F](apiPath)
)
}

def makeWebSocketService[R, R1 <: R, E](
builder: WebSocketBuilder2[RIO[R, *]],
interpreter: WebSocketInterpreter[R1, E]
Expand Down
13 changes: 13 additions & 0 deletions adapters/pekko-http/src/main/scala/caliban/PekkoHttpAdapter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import sttp.capabilities.WebSockets
import sttp.capabilities.pekko.PekkoStreams
import sttp.capabilities.pekko.PekkoStreams.Pipe
import sttp.model.StatusCode
import sttp.monad.{ FutureMonad, MonadError }
import sttp.tapir.PublicEndpoint
import sttp.tapir.model.ServerRequest
import sttp.tapir.server.ServerEndpoint
Expand All @@ -21,6 +22,8 @@ import zio.stream.ZStream
import scala.concurrent.{ ExecutionContext, Future }

class PekkoHttpAdapter private (val options: PekkoHttpServerOptions)(implicit ec: ExecutionContext) {
private implicit val monadErrorFuture: MonadError[Future] = new FutureMonad

private val pekkoInterpreter = PekkoHttpServerInterpreter(options)(ec)

def makeHttpService[R, E](
Expand Down Expand Up @@ -55,6 +58,16 @@ class PekkoHttpAdapter private (val options: PekkoHttpServerOptions)(implicit ec
)
)

/**
* Creates a route which serves the GraphiQL UI from CDN.
*
* @param apiPath The path at which the API can be introspected.
*
* @see [[https://github.com/graphql/graphiql/tree/main/examples/graphiql-cdn]]
*/
def makeGraphiqlService(apiPath: String): Route =
pekkoInterpreter.toRoute(HttpInterpreter.makeGraphiqlEndpoint[Future](apiPath))

private implicit def streamConstructor(implicit
runtime: Runtime[Any],
mat: Materializer
Expand Down
13 changes: 13 additions & 0 deletions adapters/play/src/main/scala/caliban/PlayAdapter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import sttp.capabilities.WebSockets
import sttp.capabilities.pekko.PekkoStreams
import sttp.capabilities.pekko.PekkoStreams.Pipe
import sttp.model.StatusCode
import sttp.monad.FutureMonad
import sttp.tapir.PublicEndpoint
import sttp.tapir.model.ServerRequest
import sttp.tapir.server.ServerEndpoint
Expand All @@ -34,6 +35,18 @@ class PlayAdapter private (private val options: Option[PlayServerOptions]) {
): Routes =
playInterpreter.toRoutes(interpreter.serverEndpointFuture[PekkoStreams](PekkoStreams)(runtime))

/**
* Creates a route which serves the GraphiQL UI from CDN.
*
* @param apiPath The path at which the API can be introspected.
*
* @see [[https://github.com/graphql/graphiql/tree/main/examples/graphiql-cdn]]
*/
def makeGraphiqlService(apiPath: String)(implicit materializer: Materializer): Routes = {
implicit val F: FutureMonad = new FutureMonad()(materializer.executionContext)
playInterpreter.toRoutes(HttpInterpreter.makeGraphiqlEndpoint[Future](apiPath))
}

def makeWebSocketService[R, E](
interpreter: WebSocketInterpreter[R, E]
)(implicit runtime: Runtime[R], materializer: Materializer): Routes = {
Expand Down
83 changes: 13 additions & 70 deletions adapters/quick/src/main/scala/caliban/GraphiQLHandler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,84 +11,27 @@ object GraphiQLHandler {
* Creates a handler which serves the GraphiQL UI from CDN.
*
* @param apiPath The path at which the API can be introspected.
* @param graphiqlPath The path at which the GraphiQL UI will be served.
*
* @see [[https://github.com/graphql/graphiql/tree/main/examples/graphiql-cdn]]
*/
def handler(apiPath: String): RequestHandler[Any, Nothing] = {
val headers = Headers(Header.ContentType(MediaType.text.html).untyped)
zio.http.handler { (req: Request) =>
Response(
Status.Ok,
headers,
Body.fromString(html(apiPath, req.path.encode))
)
}
}

@deprecated("Use overloaded method without providing the graphiqlPath param", since = "2.8.2")
def handler(apiPath: String, graphiqlPath: String): RequestHandler[Any, Nothing] =
Response(
Status.Ok,
Headers(Header.ContentType(MediaType.text.html).untyped),
Body.fromString(html(apiPath, graphiqlPath))
).toHandler

def html(apiPath: String, uiPath: String): String =
s"""
|<!--
| * Copyright (c) 2021 GraphQL Contributors
| * All rights reserved.
| *
| * This source code is licensed under the license found in the
| * LICENSE file in the root directory of this source tree.
|-->
|<!doctype html>
|<html lang="en">
|<head>
| <title>GraphiQL</title>
| <style>
| body {
| height: 100%;
| margin: 0;
| width: 100%;
| overflow: hidden;
| }
|
| #graphiql {
| height: 100vh;
| }
| </style>
| <script
| crossorigin
| src="https://unpkg.com/react@18/umd/react.development.js"
| ></script>
| <script
| crossorigin
| src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
| ></script>
| <script
| src="https://unpkg.com/graphiql/graphiql.min.js"
| type="application/javascript"
| ></script>
| <link rel="stylesheet" href="https://unpkg.com/graphiql/graphiql.min.css"/>
| <script
| src="https://unpkg.com/@graphiql/plugin-explorer/dist/index.umd.js"
| crossorigin
| ></script>
|
| <link
| rel="stylesheet"
| href="https://unpkg.com/@graphiql/plugin-explorer/dist/style.css"
| />
|</head>
|
|<body>
|<div id="graphiql">Loading...</div>
|<script>
| const root = ReactDOM.createRoot(document.getElementById('graphiql'));
| const fetcher = GraphiQL.createFetcher({
| url: window.location.href.replace("$uiPath", "$apiPath")
| });
| const explorerPlugin = GraphiQLPluginExplorer.explorerPlugin();
| root.render(
| React.createElement(GraphiQL, {
| fetcher,
| defaultEditorToolsVisibility: true,
| plugins: [explorerPlugin],
| }),
| );
|</script>
|</body>
|</html>
|""".stripMargin

def html(apiPath: String, uiPath: String): String = HttpUtils.graphiqlHtml(apiPath, uiPath)
}
11 changes: 1 addition & 10 deletions adapters/quick/src/main/scala/caliban/QuickAdapter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ final class QuickAdapter[R] private (requestHandler: QuickRequestHandler[R]) {
RoutePattern(Method.GET, apiPath) -> handlers.api
)
val graphiqlRoute = graphiqlPath.toList.map { uiPath =>
RoutePattern(Method.GET, uiPath) -> GraphiQLHandler.handler(apiPath, uiPath)
RoutePattern(Method.GET, uiPath) -> GraphiQLHandler.handler(apiPath)
}
val uploadRoute = uploadPath.toList.map { uPath =>
RoutePattern(Method.POST, uPath) -> handlers.upload
Expand All @@ -54,15 +54,6 @@ final class QuickAdapter[R] private (requestHandler: QuickRequestHandler[R]) {
Routes.fromIterable(apiRoutes ::: graphiqlRoute ::: uploadRoute ::: wsRoute)
}

@deprecated("Use `routes` instead", "2.6.1")
def toApp(
apiPath: String,
graphiqlPath: Option[String] = None,
uploadPath: Option[String] = None,
webSocketPath: Option[String] = None
): HttpApp[R] =
HttpApp(routes(apiPath, graphiqlPath, uploadPath, webSocketPath))

/**
* Runs the server using the default zio-http server configuration on the specified port.
* This is meant as a convenience method for getting started quickly
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,9 @@ final private class QuickRequestHandler[R](
.mapConcatChunk(Chunk.fromArray)
}

private def encodeTextEventStream(resp: GraphQLResponse[Any])(implicit trace: Trace): UStream[ServerSentEvent] =
private def encodeTextEventStream(
resp: GraphQLResponse[Any]
)(implicit trace: Trace): UStream[ServerSentEvent[String]] =
ServerSentEvents.transformResponse(
resp,
v => ServerSentEvent(writeToString(v), Some("next")),
Expand Down
16 changes: 0 additions & 16 deletions adapters/quick/src/main/scala/caliban/quick/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,6 @@ package object quick {
)
)

@deprecated("use `routes` instead", "2.6.1")
def toApp(
apiPath: String,
graphiqlPath: Option[String] = None,
uploadPath: Option[String] = None,
webSocketPath: Option[String] = None
)(implicit trace: Trace): IO[CalibanError.ValidationError, HttpApp[R]] =
gql.interpreter.map(
QuickAdapter(_).toApp(
apiPath = apiPath,
graphiqlPath = graphiqlPath,
uploadPath = uploadPath,
webSocketPath = webSocketPath
)
)

/**
* Creates a zio-http handler for the GraphQL API
*
Expand Down
Loading

0 comments on commit 2fdb393

Please sign in to comment.