graphql-server.ring

Ring middleware for GraphQL endpoint handling.

Provides Ring middleware that intercepts GraphQL requests and executes queries via Lacinia. Expects the request body to be pre-parsed JSON (a Clojure map). Use standard Ring JSON middleware like ring.middleware.json/wrap-json-body before this middleware.

Supports GraphQL subscriptions via Server-Sent Events (SSE) when enabled. See graphql-middleware for subscription configuration options.

build-lacinia-schema

(build-lacinia-schema resolver-map)(build-lacinia-schema resolver-map custom-scalars)

Builds a compiled Lacinia schema from a resolver map.

Takes a map of [object action] -> [schema resolver-var] tuples (as produced by graphql-server.core/collect-resolvers or graphql-server.core/def-resolver-map) and returns a compiled Lacinia schema ready for execution.

The resolver map may include both Query/Mutation resolvers and Subscription streamers. Resolvers are injected via inject-resolvers, streamers via inject-streamers.

The schema includes built-in scalar types for Date, UUID, and Json.

Optionally accepts a map of custom scalars where keys are scalar names (keywords) and values are maps with :parse and :serialize functions:

{:HexPosition {:parse vec :serialize identity}}

graphql-middleware

(graphql-middleware handler {:keys [path resolver-map context-fn enable-graphiql? scalars enable-subscriptions? subscription-path cors-origin], :or {path "/graphql", context-fn (fn [req] {:request req}), enable-graphiql? true, scalars {}, enable-subscriptions? false, subscription-path "/graphql/subscriptions", cors-origin "*"}})

Ring middleware that handles GraphQL requests at a specified endpoint.

Intercepts requests to the GraphQL endpoint: - POST requests: Executes GraphQL query from parsed body, returns JSON response - GET requests: Serves GraphiQL interactive query explorer (unless disabled)

The request :body must be a parsed map containing :query (string) and optionally :variables (map). Use standard Ring JSON middleware like ring.middleware.json/wrap-json-body before this middleware to parse incoming JSON requests.

Options: - :path - The URL path to intercept (default: /graphql) - :resolver-map - Map of resolvers from graphql-server.core/def-resolver-map - :context-fn - Optional function (fn [request] context-map) to build GraphQL context from the Ring request. Defaults to including the full request under :request key. - :enable-graphiql? - Whether to serve GraphiQL on GET requests (default: true) - :scalars - Optional map of custom scalar definitions. Keys are scalar names (keywords), values are maps with :parse and :serialize functions.

Subscription options (for real-time updates via SSE): - :enable-subscriptions? - Whether to enable subscription endpoint (default: false) - :subscription-path - Path for subscription endpoint (default: /graphql/subscriptions) - :cors-origin - CORS origin for SSE responses (default: "*")

Example:

(require '[ring.middleware.json :refer [wrap-json-body]]
         '[graphql-server.subscriptions :as subs])

(def subscription-manager (subs/create-subscription-manager))

(def app
  (-> handler
      (graphql-middleware {:resolver-map my-resolvers
                           :path "/api/graphql"
                           :context-fn (fn [req]
                                         {:user (:user req)
                                          :subscription-manager subscription-manager})
                           :scalars {:HexPosition {:parse vec :serialize identity}}
                           :enable-graphiql? true
                           :enable-subscriptions? true
                           :subscription-path "/api/graphql/subscriptions"})
      (wrap-json-body {:keywords? true})))