All Downloads are FREE. Search and download functionalities are using the official Maven repository.

caliban.quick.package.scala Maven / Gradle / Ivy

The newest version!
package caliban

import caliban.Configurator.ExecutionConfiguration
import zio._
import zio.http._
import zio.stacktracer.TracingImplicits.disableAutoTrace

package object quick {

  implicit class GraphqlServerOps[R](val gql: GraphQL[R]) extends AnyVal {

    /**
     * Serves the GraphQL API on the specified port using the default zio-http configuration.
     * This is meant as a convenience method for getting started quickly.
     *
     * @param port The port to serve the API on
     * @param apiPath The route to serve the API on, e.g., `/api/graphql`
     * @param graphiqlPath Optionally define a route to serve the GraphiQL UI on, e.g., `/graphiql`
     * @param uploadPath Optionally define a route to serve file uploads on, e.g., `/api/upload`
     * @param webSocketPath The path where websocket requests will be set. If None, websocket-based subscriptions will be disabled.
     */
    def runServer(
      port: Int,
      apiPath: String,
      graphiqlPath: Option[String] = None,
      uploadPath: Option[String] = None,
      webSocketPath: Option[String] = None
    )(implicit
      trace: Trace,
      tag: Tag[R]
    ): RIO[R, Nothing] =
      gql.interpreter.flatMap(
        QuickAdapter(_).runServer(
          port,
          apiPath = apiPath,
          graphiqlPath = graphiqlPath,
          uploadPath = uploadPath,
          webSocketPath = webSocketPath
        )
      )

    /**
     * Creates zio-http `Routes` from the GraphQL API
     *
     * @param apiPath The route to serve the API on, e.g., `/api/graphql`
     * @param graphiqlPath Optionally define a route to serve the GraphiQL UI on, e.g., `/graphiql`
     * @param uploadPath Optionally define a route to serve file uploads on, e.g., `/api/upload`
     * @param webSocketPath The path where websocket requests will be set. If None, websocket-based subscriptions will be disabled.
     */
    def routes(
      apiPath: String,
      graphiqlPath: Option[String] = None,
      uploadPath: Option[String] = None,
      webSocketPath: Option[String] = None
    )(implicit trace: Trace): Task[Routes[R, Nothing]] =
      gql.interpreter.map(
        QuickAdapter(_).routes(
          apiPath = apiPath,
          graphiqlPath = graphiqlPath,
          uploadPath = uploadPath,
          webSocketPath = webSocketPath
        )
      )

    /**
     * Creates a zio-http handler for the GraphQL API
     *
     * @see [[handlersConfigured]] for a more powerful variant that allows configuring the GraphQL request execution
     */
    def handlers(implicit trace: Trace): IO[CalibanError.ValidationError, QuickHandlers[R]] =
      gql.interpreter.map(QuickAdapter(_).handlers)

    @deprecated("Use handlers instead", "2.5.0")
    def handler(implicit trace: Trace): IO[CalibanError.ValidationError, RequestHandler[R, Nothing]] =
      gql.interpreter.map(QuickAdapter(_).handler)

    /**
     * Creates a zio-http handler for the GraphQL API, allowing to configure the GraphQL request execution
     */
    def handlersConfigured(config: ExecutionConfiguration)(implicit
      trace: Trace
    ): IO[CalibanError.ValidationError, QuickHandlers[R]] =
      gql.interpreter.map(QuickAdapter(_).configure(config).handlers)

    @deprecated("Use handlersConfigured instead", "2.5.0")
    def handlerConfigured(config: ExecutionConfiguration)(implicit
      trace: Trace
    ): IO[CalibanError.ValidationError, RequestHandler[R, Response]] =
      gql.interpreter.map(QuickAdapter(_).configure(config).handler)

    /**
     * Unsafe API which allows running the server impurely
     */
    def unsafe: UnsafeApi[R] = new UnsafeApi[R](gql.interpreterUnsafe)
  }

  final class UnsafeApi[R](
    interpreter: GraphQLInterpreter[R, Any],
    executionConfig: ExecutionConfiguration = ExecutionConfiguration()
  ) {

    /**
     * Creates zio-http `Routes` from the GraphQL API
     *
     * @param apiPath The route to serve the API on, e.g., `/api/graphql`
     * @param graphiqlPath Optionally define a route to serve the GraphiQL UI on, e.g., `/graphiql`
     * @param uploadPath Optionally define a route to serve file uploads on, e.g., `/api/upload`
     * @param webSocketPath The path where websocket requests will be set. If None, websocket-based subscriptions will be disabled.
     */
    def routes(
      apiPath: String,
      graphiqlPath: Option[String] = None,
      uploadPath: Option[String] = None,
      webSocketPath: Option[String] = None
    ): Routes[R, Nothing] =
      QuickAdapter(interpreter).routes(
        apiPath = apiPath,
        graphiqlPath = graphiqlPath,
        uploadPath = uploadPath,
        webSocketPath = webSocketPath
      )

    /**
     * Convenience method for impurely running the server.
     *
     * Useful for scripts / demos / showing off Caliban to your colleagues etc.
     *
     * Note that in order to call this method, you need to provide all dependencies required by the GraphQL environment. You can do that by passing a `ZLayer` to [[provideLayer]].
     */
    def runServer(
      port: Int = 8080,
      apiPath: String = "/graphql",
      graphiqlPath: Option[String] = Some("/graphiql"),
      uploadPath: Option[String] = None
    )(implicit trace: Trace, tag: Tag[R], ev: Any =:= R): Unit = {
      val run: RIO[R, Nothing] =
        QuickAdapter(interpreter)
          .runServer(port, apiPath, graphiqlPath, uploadPath)
          .provideSomeLayer[R](ZLayer.scoped[Any](Configurator.ref.locallyScoped(executionConfig)))

      ZIOApp.fromZIO(run.asInstanceOf[RIO[Any, Nothing]]).main(Array.empty)
    }

    def provideLayer(layer: ZLayer[Any, Any, R]): UnsafeApi[Any] =
      new UnsafeApi(interpreter.provideLayer(layer))

    def provideSomeLayer[R0](layer: ZLayer[R0, Any, R])(implicit tag: Tag[R]): UnsafeApi[R0] =
      new UnsafeApi(interpreter.provideSomeLayer(layer))

    def configure(cfg: ExecutionConfiguration): UnsafeApi[R] =
      new UnsafeApi(interpreter, cfg)

    def configureWith(cfg: ExecutionConfiguration => ExecutionConfiguration): UnsafeApi[R] =
      new UnsafeApi(interpreter, cfg(executionConfig))
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy