UNPKG

@graphql-mesh/runtime

Version:
247 lines (246 loc) • 13.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getInContextSDK = void 0; const graphql_1 = require("graphql"); const utils_1 = require("@graphql-mesh/utils"); const batch_delegate_1 = require("@graphql-tools/batch-delegate"); const delegate_1 = require("@graphql-tools/delegate"); const utils_2 = require("@graphql-tools/utils"); const wrap_1 = require("@graphql-tools/wrap"); const constants_js_1 = require("./constants.js"); function getInContextSDK(unifiedSchema, rawSources, logger, onDelegateHooks) { const inContextSDK = {}; const sourceMap = unifiedSchema.extensions.sourceMap; for (const rawSource of rawSources) { const rawSourceLogger = logger?.child(`${rawSource.name}`); const rawSourceContext = { rawSource, [constants_js_1.MESH_API_CONTEXT_SYMBOL]: true, }; // TODO: Somehow rawSource reference got lost in somewhere let rawSourceSubSchemaConfig = rawSource; const stitchingInfo = unifiedSchema.extensions.stitchingInfo; if (stitchingInfo) { for (const [subschemaConfig, subschema] of stitchingInfo.subschemaMap) { if (subschemaConfig.name === rawSource.name) { rawSourceSubSchemaConfig = subschema; break; } } } // If there is a single source, there is no unifiedSchema const transformedSchema = sourceMap?.get(rawSource) || rawSource.schema; const rootTypes = { query: transformedSchema.getQueryType(), mutation: transformedSchema.getMutationType(), subscription: transformedSchema.getSubscriptionType(), }; rawSourceLogger?.debug(`Generating In Context SDK`); for (const operationType in rootTypes) { const rootType = rootTypes[operationType]; if (rootType) { rawSourceContext[rootType.name] = {}; const rootTypeFieldMap = rootType.getFields(); for (const fieldName in rootTypeFieldMap) { const rootTypeField = rootTypeFieldMap[fieldName]; const inContextSdkLogger = rawSourceLogger?.child(`InContextSDK.${rootType.name}.${fieldName}`); const namedReturnType = (0, graphql_1.getNamedType)(rootTypeField.type); const shouldHaveSelectionSet = !(0, graphql_1.isLeafType)(namedReturnType); rawSourceContext[rootType.name][fieldName] = ({ root, args, context, info = { fieldName, fieldNodes: [], returnType: namedReturnType, parentType: rootType, path: { typename: rootType.name, key: fieldName, prev: undefined, }, schema: transformedSchema, fragments: {}, rootValue: root, operation: { kind: graphql_1.Kind.OPERATION_DEFINITION, operation: operationType, selectionSet: { kind: graphql_1.Kind.SELECTION_SET, selections: [], }, }, variableValues: {}, }, selectionSet, key, argsFromKeys, valuesFromResults, autoSelectionSetWithDepth, }) => { inContextSdkLogger?.debug(`Called with`, { args, key, }); const commonDelegateOptions = { schema: rawSourceSubSchemaConfig, rootValue: root, operation: operationType, fieldName, context, transformedSchema, info, transforms: [], }; // If there isn't an extraction of a value if (typeof selectionSet !== 'function') { commonDelegateOptions.returnType = rootTypeField.type; } if (shouldHaveSelectionSet) { let selectionCount = 0; for (const fieldNode of info.fieldNodes) { if (fieldNode.selectionSet != null) { selectionCount += fieldNode.selectionSet.selections.length; } } if (selectionCount === 0) { if (!selectionSet) { if (autoSelectionSetWithDepth) { const operationNode = (0, utils_2.buildOperationNodeForField)({ schema: transformedSchema, kind: operationType, depthLimit: autoSelectionSetWithDepth, field: fieldName, }); selectionSet = (0, graphql_1.print)(operationNode.selectionSet.selections[0].selectionSet); } else { throw new Error(`You have to provide 'selectionSet' for context.${rawSource.name}.${rootType.name}.${fieldName}`); } } commonDelegateOptions.info = { ...info, fieldNodes: [ { ...info.fieldNodes[0], selectionSet: { kind: graphql_1.Kind.SELECTION_SET, selections: [ { kind: graphql_1.Kind.FIELD, name: { kind: graphql_1.Kind.NAME, value: '__typename', }, }, ], }, }, ...info.fieldNodes.slice(1), ], }; } } if (key && argsFromKeys) { const batchDelegationOptions = { ...commonDelegateOptions, key, argsFromKeys, valuesFromResults, }; if (selectionSet) { const selectionSetFactory = normalizeSelectionSetParamOrFactory(selectionSet); const path = [fieldName]; const wrapQueryTransform = new wrap_1.WrapQuery(path, selectionSetFactory, identical); batchDelegationOptions.transforms = [wrapQueryTransform]; } const onDelegateHookDones = []; const onDelegatePayload = { ...batchDelegationOptions, sourceName: rawSource.name, typeName: rootType.name, fieldName, }; const onDelegateResult$ = (0, utils_1.iterateAsync)(onDelegateHooks, onDelegateHook => onDelegateHook(onDelegatePayload), onDelegateHookDones); if ((0, utils_2.isPromise)(onDelegateResult$)) { return onDelegateResult$.then(() => handleIterationResult(batch_delegate_1.batchDelegateToSchema, batchDelegationOptions, onDelegateHookDones)); } return handleIterationResult(batch_delegate_1.batchDelegateToSchema, batchDelegationOptions, onDelegateHookDones); } else { const regularDelegateOptions = { ...commonDelegateOptions, args, }; if (selectionSet) { const selectionSetFactory = normalizeSelectionSetParamOrFactory(selectionSet); const path = [fieldName]; const wrapQueryTransform = new wrap_1.WrapQuery(path, selectionSetFactory, valuesFromResults || identical); regularDelegateOptions.transforms = [wrapQueryTransform]; } const onDelegateHookDones = []; const onDelegatePayload = { ...regularDelegateOptions, sourceName: rawSource.name, typeName: rootType.name, fieldName, }; const onDelegateResult$ = (0, utils_1.iterateAsync)(onDelegateHooks, onDelegateHook => onDelegateHook(onDelegatePayload), onDelegateHookDones); if ((0, utils_2.isPromise)(onDelegateResult$)) { return onDelegateResult$.then(() => handleIterationResult(delegate_1.delegateToSchema, regularDelegateOptions, onDelegateHookDones)); } return handleIterationResult(delegate_1.delegateToSchema, regularDelegateOptions, onDelegateHookDones); } }; } } } inContextSDK[rawSource.name] = rawSourceContext; } return inContextSDK; } exports.getInContextSDK = getInContextSDK; function getSelectionSetFromDocumentNode(documentNode) { const operationDefinition = documentNode.definitions.find(definition => definition.kind === graphql_1.Kind.OPERATION_DEFINITION); if (!operationDefinition) { throw new Error('DocumentNode must contain an OperationDefinitionNode'); } return operationDefinition.selectionSet; } function normalizeSelectionSetParam(selectionSetParam) { if (typeof selectionSetParam === 'string') { const documentNode = (0, utils_1.parseWithCache)(selectionSetParam); return getSelectionSetFromDocumentNode(documentNode); } if ((0, utils_2.isDocumentNode)(selectionSetParam)) { return getSelectionSetFromDocumentNode(selectionSetParam); } return selectionSetParam; } const normalizeSelectionSetParamFactory = (0, utils_2.memoize1)(function normalizeSelectionSetParamFactory(selectionSetParamFactory) { const memoizedSelectionSetFactory = (0, utils_2.memoize1)(selectionSetParamFactory); return function selectionSetFactory(subtree) { const selectionSetParam = memoizedSelectionSetFactory(subtree); return normalizeSelectionSetParam(selectionSetParam); }; }); function normalizeSelectionSetParamOrFactory(selectionSetParamOrFactory) { if (typeof selectionSetParamOrFactory === 'function') { return normalizeSelectionSetParamFactory(selectionSetParamOrFactory); } return () => normalizeSelectionSetParam(selectionSetParamOrFactory); } function identical(val) { return val; } function handleIterationResult(delegateFn, delegateOptions, onDelegateHookDones) { const delegationResult$ = delegateFn(delegateOptions); if ((0, utils_2.isPromise)(delegationResult$)) { return delegationResult$.then(delegationResult => handleOnDelegateDone(delegationResult, onDelegateHookDones)); } return handleOnDelegateDone(delegationResult$, onDelegateHookDones); } function handleOnDelegateDone(delegationResult, onDelegateHookDones) { function setResult(newResult) { delegationResult = newResult; } const onDelegateDoneResult$ = (0, utils_1.iterateAsync)(onDelegateHookDones, onDelegateHookDone => onDelegateHookDone({ result: delegationResult, setResult, })); if ((0, utils_2.isPromise)(onDelegateDoneResult$)) { return onDelegateDoneResult$.then(() => delegationResult); } return delegationResult; }