UNPKG

@graphql-tools/delegate

Version:

A set of utils for faster development of GraphQL tools

92 lines (91 loc) 4.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.resolveExternalValue = void 0; const graphql_1 = require("graphql"); const mergeFields_js_1 = require("./mergeFields.js"); function resolveExternalValue(result, unpathedErrors, subschema, context, info, returnType = getReturnType(info), skipTypeMerging) { const type = (0, graphql_1.getNullableType)(returnType); if (result instanceof Error) { return result; } if (result == null) { return reportUnpathedErrorsViaNull(unpathedErrors); } if ('parseValue' in type) { return type.parseValue(result); } else if ((0, graphql_1.isCompositeType)(type)) { return resolveExternalObject(type, result, unpathedErrors, subschema, context, info, skipTypeMerging); } else if ((0, graphql_1.isListType)(type)) { if (Array.isArray(result)) { return resolveExternalList(type, result, unpathedErrors, subschema, context, info, skipTypeMerging); } return resolveExternalValue(result, unpathedErrors, subschema, context, info, type.ofType, skipTypeMerging); } } exports.resolveExternalValue = resolveExternalValue; function resolveExternalObject(type, object, unpathedErrors, subschema, context, info, skipTypeMerging) { // if we have already resolved this object, for example, when the identical object appears twice // in a list, see https://github.com/ardatan/graphql-tools/issues/2304 if (!(0, mergeFields_js_1.isExternalObject)(object)) { (0, mergeFields_js_1.annotateExternalObject)(object, unpathedErrors, subschema, Object.create(null)); } if (skipTypeMerging || info == null) { return object; } const stitchingInfo = info.schema.extensions?.['stitchingInfo']; if (stitchingInfo == null) { return object; } // Within the stitching context, delegation to a stitched GraphQLSchema or SubschemaConfig // will be redirected to the appropriate Subschema object, from which merge targets can be queried. let mergedTypeInfo; const possibleTypeNames = [object.__typename, type.name]; for (const possibleTypeName of possibleTypeNames) { if (possibleTypeName != null && stitchingInfo.mergedTypes[possibleTypeName]?.targetSubschemas?.get(subschema) ?.length) { mergedTypeInfo = stitchingInfo.mergedTypes[possibleTypeName]; break; } } // If there are no merge targets from the subschema, return. if (!mergedTypeInfo) { return object; } return (0, mergeFields_js_1.mergeFields)(mergedTypeInfo, object, subschema, context, info); } function resolveExternalList(type, list, unpathedErrors, subschema, context, info, skipTypeMerging) { return list.map(listMember => resolveExternalValue(listMember, unpathedErrors, subschema, context, info, type.ofType, skipTypeMerging)); } const reportedErrors = new WeakMap(); function reportUnpathedErrorsViaNull(unpathedErrors) { if (unpathedErrors.length) { const unreportedErrors = []; for (const error of unpathedErrors) { if (!reportedErrors.has(error)) { unreportedErrors.push(error); reportedErrors.set(error, true); } } if (unreportedErrors.length) { if (unreportedErrors.length === 1) { return unreportedErrors[0]; } const combinedError = new AggregateError(unreportedErrors, unreportedErrors.map(error => error.message).join(', \n')); // We cast path as any for GraphQL.js 14 compat // locatedError path argument must be defined, but it is just forwarded to a constructor that allows a undefined value // https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/locatedError.js#L25 // https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/GraphQLError.js#L19 return (0, graphql_1.locatedError)(combinedError, undefined, unreportedErrors[0].path); } } return null; } function getReturnType(info) { if (info == null) { throw new Error(`Return type cannot be inferred without a source schema.`); } return info.returnType; }