UNPKG

graphql-modules

Version:

Create reusable, maintainable, testable and extendable GraphQL modules

78 lines (77 loc) 3.25 kB
import { wrapSchema } from '@graphql-tools/wrap'; import { execute } from 'graphql'; import { uniqueId } from '../shared/utils'; const CONTEXT_ID = Symbol.for('context-id'); export function apolloExecutorCreator({ createExecution, }) { return function createApolloExecutor(options) { const executor = createExecution(options); return async function executorAdapter(requestContext) { return executor({ schema: requestContext.schema, document: requestContext.document, operationName: requestContext.operationName, variableValues: requestContext.request.variables, contextValue: requestContext.context, }); }; }; } export function apolloSchemaCreator({ createSubscription, contextBuilder, schema, }) { const createApolloSchema = () => { const sessions = {}; const subscription = createSubscription(); function getSession(ctx, { context, ɵdestroy: destroy }) { if (!ctx[CONTEXT_ID]) { ctx[CONTEXT_ID] = uniqueId((id) => !sessions[id]); sessions[ctx[CONTEXT_ID]] = { count: 0, session: { context, destroy() { if (--sessions[ctx[CONTEXT_ID]].count === 0) { destroy(); delete sessions[ctx[CONTEXT_ID]]; delete ctx[CONTEXT_ID]; } }, }, }; } sessions[ctx[CONTEXT_ID]].count++; return sessions[ctx[CONTEXT_ID]].session; } return wrapSchema({ schema, batch: true, executor(input) { if (input.operationType === 'subscription') { return subscription({ schema, document: input.document, variableValues: input.variables, contextValue: input.context, rootValue: input.rootValue, operationName: input.operationName, }); } // Create an execution context and run within it return contextBuilder(input.context).runWithContext((env) => { const { context, destroy } = getSession(input.context, env); // It's important to wrap the executeFn within a promise // so we can easily control the end of execution (with finally) return Promise.resolve() .then(() => execute({ schema, document: input.document, contextValue: context, variableValues: input.variables, rootValue: input.rootValue, operationName: input.operationName, })) .finally(destroy); }); }, }); }; return createApolloSchema; }