UNPKG

@graphql-mesh/runtime

Version:
174 lines (173 loc) • 8.22 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useSubschema = void 0; const graphql_1 = require("graphql"); const graphql_jit_1 = require("graphql-jit"); const core_1 = require("@envelop/core"); const utils_1 = require("@graphql-mesh/utils"); const delegate_1 = require("@graphql-tools/delegate"); const utils_2 = require("@graphql-tools/utils"); var IntrospectionQueryType; (function (IntrospectionQueryType) { IntrospectionQueryType["FEDERATION"] = "FEDERATION"; IntrospectionQueryType["REGULAR"] = "REGULAR"; IntrospectionQueryType["STREAM"] = "STREAM"; })(IntrospectionQueryType || (IntrospectionQueryType = {})); const getIntrospectionOperationType = (0, utils_2.memoize1)(function getIntrospectionOperationType(operationAST) { let introspectionQueryType = null; if (operationAST.operation === 'query' && operationAST.selectionSet.selections.length === 1) { (0, graphql_1.visit)(operationAST, { Field: (node) => { if (node.name.value === '__schema' || node.name.value === '__type') { introspectionQueryType = IntrospectionQueryType.REGULAR; return graphql_1.BREAK; } if (node.name.value === '_service') { introspectionQueryType = IntrospectionQueryType.FEDERATION; return graphql_1.BREAK; } if (node.directives?.some(d => d.name.value === 'stream')) { introspectionQueryType = IntrospectionQueryType.STREAM; return graphql_1.BREAK; } }, }); } return introspectionQueryType; }); function getExecuteFn(subschema) { const compiledQueryCache = new WeakMap(); const transformedDocumentNodeCache = new WeakMap(); return function subschemaExecute(args) { const originalRequest = { document: args.document, variables: args.variableValues, operationName: args.operationName ?? undefined, rootValue: args.rootValue, context: args.contextValue, }; const operationAST = (0, utils_2.getOperationASTFromRequest)(originalRequest); // TODO: We need more elegant solution const introspectionQueryType = getIntrospectionOperationType(operationAST); if (introspectionQueryType === IntrospectionQueryType.FEDERATION) { const executionResult = { data: { _service: { sdl: (0, utils_2.printSchemaWithDirectives)(args.schema), }, }, }; return executionResult; } else if (introspectionQueryType === IntrospectionQueryType.REGULAR) { return (0, graphql_1.execute)(args); } const isStream = introspectionQueryType === IntrospectionQueryType.STREAM; const delegationContext = { subschema, subschemaConfig: subschema, targetSchema: args.schema, operation: operationAST.operation, fieldName: '', // Might not work context: args.contextValue, rootValue: args.rootValue, transforms: subschema.transforms, transformedSchema: subschema.transformedSchema, skipTypeMerging: true, returnType: (0, utils_2.getDefinedRootType)(args.schema, operationAST.operation), }; let executor = subschema.executor; if (executor == null) { if (isStream || operationAST.operation === 'subscription') { executor = (0, delegate_1.createDefaultExecutor)(subschema.schema); } else { executor = function subschemaExecutor(request) { let compiledQuery = compiledQueryCache.get(request.document); if (!compiledQuery) { const compilationResult = (0, graphql_jit_1.compileQuery)(subschema.schema, request.document, request.operationName, { // TODO: Disable for now customJSONSerializer: false, disableLeafSerialization: true, }); if (!(0, graphql_jit_1.isCompiledQuery)(compilationResult)) { return compilationResult; } compiledQuery = compilationResult; compiledQueryCache.set(request.document, compiledQuery); } if (operationAST.operation === 'subscription') { const result$ = compiledQuery.subscribe(request.rootValue, request.context, request.variables); if ((0, utils_2.isPromise)(result$)) { return result$.then(result => { result.stringify = compiledQuery.stringify; return result; }); } result$.stringify = compiledQuery.stringify; return result$; } const result$ = compiledQuery.query(request.rootValue, request.context, request.variables); if ((0, utils_2.isPromise)(result$)) { return result$.then(result => { result.stringify = compiledQuery.stringify; return result; }); } result$.stringify = compiledQuery.stringify; return result$; }; } } /* if (subschema.batch) { executor = createBatchingExecutor(executor); } */ const transformationContext = {}; const transformedRequest = (0, utils_1.applyRequestTransforms)(originalRequest, delegationContext, transformationContext, subschema.transforms); const cachedTransfomedDocumentNode = transformedDocumentNodeCache.get(originalRequest.document); if (cachedTransfomedDocumentNode) { transformedRequest.document = cachedTransfomedDocumentNode; } else { transformedDocumentNodeCache.set(originalRequest.document, transformedRequest.document); } function handleResult(originalResult) { if ((0, utils_2.isAsyncIterable)(originalResult)) { return (0, core_1.mapAsyncIterator)(originalResult, singleResult => (0, utils_1.applyResultTransforms)(singleResult, delegationContext, transformationContext, subschema.transforms)); } const transformedResult = (0, utils_1.applyResultTransforms)(originalResult, delegationContext, transformationContext, subschema.transforms); return transformedResult; } const originalResult$ = executor(transformedRequest); if ((0, utils_2.isPromise)(originalResult$)) { return originalResult$.then(handleResult); } return handleResult(originalResult$); }; } // Creates an envelop plugin to execute a subschema inside Envelop function useSubschema(subschema) { const executeFn = getExecuteFn(subschema); const plugin = { onPluginInit({ setSchema }) { // To prevent unwanted warnings from stitching if (!('_transformedSchema' in subschema)) { subschema.transformedSchema = (0, delegate_1.applySchemaTransforms)(subschema.schema, subschema); } subschema.transformedSchema.extensions = subschema.transformedSchema.extensions || subschema.schema.extensions || {}; Object.assign(subschema.transformedSchema.extensions, subschema.schema.extensions); setSchema(subschema.transformedSchema); }, onExecute({ setExecuteFn }) { setExecuteFn(executeFn); }, onSubscribe({ setSubscribeFn }) { setSubscribeFn(executeFn); }, }; return plugin; } exports.useSubschema = useSubschema;