UNPKG

@graphql-tools/delegate

Version:

A set of utils for faster development of GraphQL tools

154 lines (153 loc) • 6.89 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createDefaultExecutor = exports.delegateRequest = exports.delegateToSchema = void 0; const graphql_1 = require("graphql"); const batch_execute_1 = require("@graphql-tools/batch-execute"); const executor_1 = require("@graphql-tools/executor"); const utils_1 = require("@graphql-tools/utils"); const applySchemaTransforms_js_1 = require("./applySchemaTransforms.js"); const createRequest_js_1 = require("./createRequest.js"); const Subschema_js_1 = require("./Subschema.js"); const subschemaConfig_js_1 = require("./subschemaConfig.js"); const Transformer_js_1 = require("./Transformer.js"); function delegateToSchema(options) { const { info, schema, rootValue = schema.rootValue ?? info.rootValue, operationName = info.operation.name?.value, operation = (0, createRequest_js_1.getDelegatingOperation)(info.parentType, info.schema), fieldName = info.fieldName, selectionSet, fieldNodes = info.fieldNodes, context, } = options; const request = (0, createRequest_js_1.createRequest)({ sourceSchema: info.schema, sourceParentType: info.parentType, sourceFieldName: info.fieldName, fragments: info.fragments, variableDefinitions: info.operation.variableDefinitions, variableValues: info.variableValues, targetRootValue: rootValue, targetOperationName: operationName, targetOperation: operation, targetFieldName: fieldName, selectionSet, fieldNodes, context, info, }); return delegateRequest({ ...options, request, }); } exports.delegateToSchema = delegateToSchema; function getDelegationReturnType(targetSchema, operation, fieldName) { const rootType = (0, utils_1.getDefinedRootType)(targetSchema, operation); const rootFieldType = rootType.getFields()[fieldName]; if (!rootFieldType) { throw new Error(`Unable to find field '${fieldName}' in type '${rootType}'.`); } return rootFieldType.type; } function delegateRequest(options) { const delegationContext = getDelegationContext(options); const transformer = new Transformer_js_1.Transformer(delegationContext); const processedRequest = transformer.transformRequest(options.request); if (options.validateRequest) { validateRequest(delegationContext, processedRequest.document); } const executor = getExecutor(delegationContext); const result$ = executor(processedRequest); function handleExecutorResult(executorResult) { if ((0, utils_1.isAsyncIterable)(executorResult)) { const iterator = executorResult[Symbol.asyncIterator](); // "subscribe" to the subscription result and map the result through the transforms return (0, utils_1.mapAsyncIterator)(iterator, result => transformer.transformResult(result)); } return transformer.transformResult(executorResult); } if ((0, utils_1.isPromise)(result$)) { return result$.then(handleExecutorResult); } return handleExecutorResult(result$); } exports.delegateRequest = delegateRequest; function getDelegationContext({ request, schema, fieldName, returnType, args, info, transforms = [], transformedSchema, skipTypeMerging = false, }) { const operationDefinition = (0, utils_1.getOperationASTFromRequest)(request); let targetFieldName; if (fieldName == null) { targetFieldName = operationDefinition.selectionSet.selections[0].name.value; } else { targetFieldName = fieldName; } const stitchingInfo = info?.schema.extensions?.['stitchingInfo']; const subschemaOrSubschemaConfig = stitchingInfo?.subschemaMap.get(schema) ?? schema; const operation = operationDefinition.operation; if ((0, subschemaConfig_js_1.isSubschemaConfig)(subschemaOrSubschemaConfig)) { const targetSchema = subschemaOrSubschemaConfig.schema; return { subschema: schema, subschemaConfig: subschemaOrSubschemaConfig, targetSchema, operation, fieldName: targetFieldName, args, context: request.context, info, returnType: returnType ?? info?.returnType ?? getDelegationReturnType(targetSchema, operation, targetFieldName), transforms: subschemaOrSubschemaConfig.transforms != null ? subschemaOrSubschemaConfig.transforms.concat(transforms) : transforms, transformedSchema: transformedSchema ?? (subschemaOrSubschemaConfig instanceof Subschema_js_1.Subschema ? subschemaOrSubschemaConfig.transformedSchema : (0, applySchemaTransforms_js_1.applySchemaTransforms)(targetSchema, subschemaOrSubschemaConfig)), skipTypeMerging, }; } return { subschema: schema, subschemaConfig: undefined, targetSchema: subschemaOrSubschemaConfig, operation, fieldName: targetFieldName, args, context: request.context, info, returnType: returnType ?? info?.returnType ?? getDelegationReturnType(subschemaOrSubschemaConfig, operation, targetFieldName), transforms, transformedSchema: transformedSchema ?? subschemaOrSubschemaConfig, skipTypeMerging, }; } function validateRequest(delegationContext, document) { const errors = (0, graphql_1.validate)(delegationContext.targetSchema, document); if (errors.length > 0) { if (errors.length > 1) { const combinedError = new AggregateError(errors, errors.map(error => error.message).join(', \n')); throw combinedError; } const error = errors[0]; throw error.originalError || error; } } const GLOBAL_CONTEXT = {}; function getExecutor(delegationContext) { const { subschemaConfig, targetSchema, context } = delegationContext; let executor = subschemaConfig?.executor || (0, exports.createDefaultExecutor)(targetSchema); if (subschemaConfig?.batch) { const batchingOptions = subschemaConfig?.batchingOptions; executor = (0, batch_execute_1.getBatchingExecutor)(context ?? GLOBAL_CONTEXT, executor, batchingOptions?.dataLoaderOptions, batchingOptions?.extensionsReducer); } return executor; } exports.createDefaultExecutor = (0, utils_1.memoize1)(function createDefaultExecutor(schema) { return function defaultExecutor(request) { return (0, executor_1.normalizedExecutor)({ schema, document: request.document, rootValue: request.rootValue, contextValue: request.context, variableValues: request.variables, operationName: request.operationName, }); }; });