UNPKG

@miragejs/graphql

Version:

A library for handling GraphQL requests with Mirage JS

81 lines (73 loc) 3.18 kB
import { GraphQLFieldResolver, GraphQLSchema, graphql } from "graphql"; import { Response } from "miragejs"; import createFieldResolver from "./resolvers/field.js"; import { createModels } from "./orm/models.js"; import { ensureExecutableGraphQLSchema } from "./utils.js"; import type { AnyRegistry } from "miragejs/-types"; import type { MirageSchema, ResolverMap, SourceGraphQLSchema, } from "./@types/index.js"; import type { RouteHandler } from "miragejs/server"; /** * Options for creating a GraphQL request handler for Mirage. * * 1. `context` - A context object that GraphQL will pass into each resolver. A * common use case for this is to supply current user information to * resolvers. By default, whatever context you pass in will be appended with * a reference to the Mirage schema and the request being handled. * 2. `resolvers` - A resolver map for cases where the default Mirage resolvers * aren't sufficient. Such cases include: resolving root-level scalar values, * sorting records and complex mutations. * 3. `root` - A root level value that GraphQL will use as the parent object for * fields at the highest level. */ type CreateHandlerOptions = { context?: { [key: string]: any }; resolvers?: ResolverMap; root?: any; }; /** * A higher-order function that returns a request handler for GraphQL queries. * It accepts both a GraphQL and Mirage schema along with a hash of options. * * The GraphQL schema param may be a string, an AST or an executable * GraphQL schema. This library ensures the schema is executable in any case. * * This also ensures models are added to the Mirage schema for each appropriate * type from the GraphQL schema. Since the GraphQL schema already defines types * and relationships, it may be redundant to define Mirage models when using * GraphQL. You may still define Mirage models, though, if you’d like. * * Lastly, it creates a field resolver that GraphQL will use to resolve every * field from a query. If an optional resolver isn't supplied for a given field, * this field resolver will be used. It does its best to resolve queries and * mutations automatically based on the information from the GraphQL schema and * the records in Mirage’s database. */ export function createGraphQLHandler( graphQLSchema: SourceGraphQLSchema, mirageSchema: MirageSchema, options: CreateHandlerOptions = {} ): RouteHandler<AnyRegistry> { const { context = {}, resolvers, root } = options; const fieldResolver = createFieldResolver(resolvers); graphQLSchema = ensureExecutableGraphQLSchema(graphQLSchema); createModels(graphQLSchema, mirageSchema); return function graphQLHandler(_, request) { try { const { query, variables } = JSON.parse(request.requestBody); return graphql({ contextValue: { ...context, mirageSchema, request }, fieldResolver: fieldResolver as GraphQLFieldResolver<any, any>, rootValue: root, schema: graphQLSchema as GraphQLSchema, source: query, variableValues: variables, }); } catch (ex) { return new Response(500, {}, { errors: [ex] }); } }; }