UNPKG

graphql-modules

Version:

Create reusable, maintainable, testable and extendable GraphQL modules

56 lines (55 loc) • 2.55 kB
import { subscribe, } from 'graphql'; import { tapAsyncIterator, isAsyncIterable, isNotSchema, } from '../shared/utils'; export function subscriptionCreator({ contextBuilder, }) { const createSubscription = (options) => { // Custom or original subscribe function const subscribeFn = (options === null || options === void 0 ? void 0 : options.subscribe) || subscribe; return (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, subscribeFieldResolver) => { function perform({ context, ɵdestroy: destroy, }) { const subscriptionArgs = isNotSchema(argsOrSchema) ? { ...argsOrSchema, contextValue: context, } : { schema: argsOrSchema, document: document, rootValue, contextValue: context, variableValues, operationName, fieldResolver, subscribeFieldResolver, }; let isIterable = false; // It's important to wrap the subscribeFn within a promise // so we can easily control the end of subscription (with finally) return Promise.resolve() .then(() => subscribeFn(subscriptionArgs)) .then((sub) => { if (isAsyncIterable(sub)) { isIterable = true; return tapAsyncIterator(sub, destroy); } return sub; }) .finally(() => { if (!isIterable) { destroy(); } }); } if (options === null || options === void 0 ? void 0 : options.controller) { // Wrap `perform` in the controller's own ALS frame so that // `@ExecutionContext()` reads inside the resolver — including // after an `await`. const controller = options.controller; return controller.ɵrunWithContext(() => perform(controller)); } return contextBuilder(isNotSchema(argsOrSchema) ? argsOrSchema.contextValue : contextValue).runWithContext(perform); }; }; return createSubscription; }