| "use strict"; |
| |
| Object.defineProperty(exports, "__esModule", { |
| value: true |
| }); |
| exports.execute = execute; |
| exports.assertValidExecutionArguments = assertValidExecutionArguments; |
| exports.buildExecutionContext = buildExecutionContext; |
| exports.collectFields = collectFields; |
| exports.buildResolveInfo = buildResolveInfo; |
| exports.resolveFieldValueOrError = resolveFieldValueOrError; |
| exports.getFieldDef = getFieldDef; |
| exports.defaultFieldResolver = exports.defaultTypeResolver = void 0; |
| |
| var _arrayFrom = _interopRequireDefault(require("../polyfills/arrayFrom")); |
| |
| var _inspect = _interopRequireDefault(require("../jsutils/inspect")); |
| |
| var _memoize = _interopRequireDefault(require("../jsutils/memoize3")); |
| |
| var _invariant = _interopRequireDefault(require("../jsutils/invariant")); |
| |
| var _devAssert = _interopRequireDefault(require("../jsutils/devAssert")); |
| |
| var _isPromise = _interopRequireDefault(require("../jsutils/isPromise")); |
| |
| var _isObjectLike = _interopRequireDefault(require("../jsutils/isObjectLike")); |
| |
| var _isCollection = _interopRequireDefault(require("../jsutils/isCollection")); |
| |
| var _promiseReduce = _interopRequireDefault(require("../jsutils/promiseReduce")); |
| |
| var _promiseForObject = _interopRequireDefault(require("../jsutils/promiseForObject")); |
| |
| var _Path = require("../jsutils/Path"); |
| |
| var _GraphQLError = require("../error/GraphQLError"); |
| |
| var _locatedError = require("../error/locatedError"); |
| |
| var _kinds = require("../language/kinds"); |
| |
| var _validate = require("../type/validate"); |
| |
| var _introspection = require("../type/introspection"); |
| |
| var _directives = require("../type/directives"); |
| |
| var _definition = require("../type/definition"); |
| |
| var _typeFromAST = require("../utilities/typeFromAST"); |
| |
| var _getOperationRootType = require("../utilities/getOperationRootType"); |
| |
| var _values = require("./values"); |
| |
| function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } |
| |
| function execute(argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, typeResolver) { |
| /* eslint-enable no-redeclare */ |
| // Extract arguments from object args if provided. |
| return arguments.length === 1 ? executeImpl(argsOrSchema) : executeImpl({ |
| schema: argsOrSchema, |
| document: document, |
| rootValue: rootValue, |
| contextValue: contextValue, |
| variableValues: variableValues, |
| operationName: operationName, |
| fieldResolver: fieldResolver, |
| typeResolver: typeResolver |
| }); |
| } |
| |
| function executeImpl(args) { |
| var schema = args.schema, |
| document = args.document, |
| rootValue = args.rootValue, |
| contextValue = args.contextValue, |
| variableValues = args.variableValues, |
| operationName = args.operationName, |
| fieldResolver = args.fieldResolver, |
| typeResolver = args.typeResolver; // If arguments are missing or incorrect, throw an error. |
| |
| assertValidExecutionArguments(schema, document, variableValues); // If a valid execution context cannot be created due to incorrect arguments, |
| // a "Response" with only errors is returned. |
| |
| var exeContext = buildExecutionContext(schema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, typeResolver); // Return early errors if execution context failed. |
| |
| if (Array.isArray(exeContext)) { |
| return { |
| errors: exeContext |
| }; |
| } // Return a Promise that will eventually resolve to the data described by |
| // The "Response" section of the GraphQL specification. |
| // |
| // If errors are encountered while executing a GraphQL field, only that |
| // field and its descendants will be omitted, and sibling fields will still |
| // be executed. An execution which encounters errors will still result in a |
| // resolved Promise. |
| |
| |
| var data = executeOperation(exeContext, exeContext.operation, rootValue); |
| return buildResponse(exeContext, data); |
| } |
| /** |
| * Given a completed execution context and data, build the { errors, data } |
| * response defined by the "Response" section of the GraphQL specification. |
| */ |
| |
| |
| function buildResponse(exeContext, data) { |
| if ((0, _isPromise.default)(data)) { |
| return data.then(function (resolved) { |
| return buildResponse(exeContext, resolved); |
| }); |
| } |
| |
| return exeContext.errors.length === 0 ? { |
| data: data |
| } : { |
| errors: exeContext.errors, |
| data: data |
| }; |
| } |
| /** |
| * Essential assertions before executing to provide developer feedback for |
| * improper use of the GraphQL library. |
| * |
| * @internal |
| */ |
| |
| |
| function assertValidExecutionArguments(schema, document, rawVariableValues) { |
| document || (0, _devAssert.default)(0, 'Must provide document.'); // If the schema used for execution is invalid, throw an error. |
| |
| (0, _validate.assertValidSchema)(schema); // Variables, if provided, must be an object. |
| |
| rawVariableValues == null || (0, _isObjectLike.default)(rawVariableValues) || (0, _devAssert.default)(0, 'Variables must be provided as an Object where each property is a variable value. Perhaps look to see if an unparsed JSON string was provided.'); |
| } |
| /** |
| * Constructs a ExecutionContext object from the arguments passed to |
| * execute, which we will pass throughout the other execution methods. |
| * |
| * Throws a GraphQLError if a valid execution context cannot be created. |
| * |
| * @internal |
| */ |
| |
| |
| function buildExecutionContext(schema, document, rootValue, contextValue, rawVariableValues, operationName, fieldResolver, typeResolver) { |
| var _definition$name, _operation$variableDe; |
| |
| var operation; |
| var fragments = Object.create(null); |
| |
| for (var _i2 = 0, _document$definitions2 = document.definitions; _i2 < _document$definitions2.length; _i2++) { |
| var definition = _document$definitions2[_i2]; |
| |
| switch (definition.kind) { |
| case _kinds.Kind.OPERATION_DEFINITION: |
| if (operationName == null) { |
| if (operation !== undefined) { |
| return [new _GraphQLError.GraphQLError('Must provide operation name if query contains multiple operations.')]; |
| } |
| |
| operation = definition; |
| } else if (((_definition$name = definition.name) === null || _definition$name === void 0 ? void 0 : _definition$name.value) === operationName) { |
| operation = definition; |
| } |
| |
| break; |
| |
| case _kinds.Kind.FRAGMENT_DEFINITION: |
| fragments[definition.name.value] = definition; |
| break; |
| } |
| } |
| |
| if (!operation) { |
| if (operationName != null) { |
| return [new _GraphQLError.GraphQLError("Unknown operation named \"".concat(operationName, "\"."))]; |
| } |
| |
| return [new _GraphQLError.GraphQLError('Must provide an operation.')]; |
| } |
| /* istanbul ignore next (See https://github.com/graphql/graphql-js/issues/2203) */ |
| |
| |
| var variableDefinitions = (_operation$variableDe = operation.variableDefinitions) !== null && _operation$variableDe !== void 0 ? _operation$variableDe : []; |
| var coercedVariableValues = (0, _values.getVariableValues)(schema, variableDefinitions, rawVariableValues !== null && rawVariableValues !== void 0 ? rawVariableValues : {}, { |
| maxErrors: 50 |
| }); |
| |
| if (coercedVariableValues.errors) { |
| return coercedVariableValues.errors; |
| } |
| |
| return { |
| schema: schema, |
| fragments: fragments, |
| rootValue: rootValue, |
| contextValue: contextValue, |
| operation: operation, |
| variableValues: coercedVariableValues.coerced, |
| fieldResolver: fieldResolver !== null && fieldResolver !== void 0 ? fieldResolver : defaultFieldResolver, |
| typeResolver: typeResolver !== null && typeResolver !== void 0 ? typeResolver : defaultTypeResolver, |
| errors: [] |
| }; |
| } |
| /** |
| * Implements the "Evaluating operations" section of the spec. |
| */ |
| |
| |
| function executeOperation(exeContext, operation, rootValue) { |
| var type = (0, _getOperationRootType.getOperationRootType)(exeContext.schema, operation); |
| var fields = collectFields(exeContext, type, operation.selectionSet, Object.create(null), Object.create(null)); |
| var path = undefined; // Errors from sub-fields of a NonNull type may propagate to the top level, |
| // at which point we still log the error and null the parent field, which |
| // in this case is the entire response. |
| // |
| // Similar to completeValueCatchingError. |
| |
| try { |
| var result = operation.operation === 'mutation' ? executeFieldsSerially(exeContext, type, rootValue, path, fields) : executeFields(exeContext, type, rootValue, path, fields); |
| |
| if ((0, _isPromise.default)(result)) { |
| return result.then(undefined, function (error) { |
| exeContext.errors.push(error); |
| return Promise.resolve(null); |
| }); |
| } |
| |
| return result; |
| } catch (error) { |
| exeContext.errors.push(error); |
| return null; |
| } |
| } |
| /** |
| * Implements the "Evaluating selection sets" section of the spec |
| * for "write" mode. |
| */ |
| |
| |
| function executeFieldsSerially(exeContext, parentType, sourceValue, path, fields) { |
| return (0, _promiseReduce.default)(Object.keys(fields), function (results, responseName) { |
| var fieldNodes = fields[responseName]; |
| var fieldPath = (0, _Path.addPath)(path, responseName); |
| var result = resolveField(exeContext, parentType, sourceValue, fieldNodes, fieldPath); |
| |
| if (result === undefined) { |
| return results; |
| } |
| |
| if ((0, _isPromise.default)(result)) { |
| return result.then(function (resolvedResult) { |
| results[responseName] = resolvedResult; |
| return results; |
| }); |
| } |
| |
| results[responseName] = result; |
| return results; |
| }, Object.create(null)); |
| } |
| /** |
| * Implements the "Evaluating selection sets" section of the spec |
| * for "read" mode. |
| */ |
| |
| |
| function executeFields(exeContext, parentType, sourceValue, path, fields) { |
| var results = Object.create(null); |
| var containsPromise = false; |
| |
| for (var _i4 = 0, _Object$keys2 = Object.keys(fields); _i4 < _Object$keys2.length; _i4++) { |
| var responseName = _Object$keys2[_i4]; |
| var fieldNodes = fields[responseName]; |
| var fieldPath = (0, _Path.addPath)(path, responseName); |
| var result = resolveField(exeContext, parentType, sourceValue, fieldNodes, fieldPath); |
| |
| if (result !== undefined) { |
| results[responseName] = result; |
| |
| if (!containsPromise && (0, _isPromise.default)(result)) { |
| containsPromise = true; |
| } |
| } |
| } // If there are no promises, we can just return the object |
| |
| |
| if (!containsPromise) { |
| return results; |
| } // Otherwise, results is a map from field name to the result of resolving that |
| // field, which is possibly a promise. Return a promise that will return this |
| // same map, but with any promises replaced with the values they resolved to. |
| |
| |
| return (0, _promiseForObject.default)(results); |
| } |
| /** |
| * Given a selectionSet, adds all of the fields in that selection to |
| * the passed in map of fields, and returns it at the end. |
| * |
| * CollectFields requires the "runtime type" of an object. For a field which |
| * returns an Interface or Union type, the "runtime type" will be the actual |
| * Object type returned by that field. |
| * |
| * @internal |
| */ |
| |
| |
| function collectFields(exeContext, runtimeType, selectionSet, fields, visitedFragmentNames) { |
| for (var _i6 = 0, _selectionSet$selecti2 = selectionSet.selections; _i6 < _selectionSet$selecti2.length; _i6++) { |
| var selection = _selectionSet$selecti2[_i6]; |
| |
| switch (selection.kind) { |
| case _kinds.Kind.FIELD: |
| { |
| if (!shouldIncludeNode(exeContext, selection)) { |
| continue; |
| } |
| |
| var name = getFieldEntryKey(selection); |
| |
| if (!fields[name]) { |
| fields[name] = []; |
| } |
| |
| fields[name].push(selection); |
| break; |
| } |
| |
| case _kinds.Kind.INLINE_FRAGMENT: |
| { |
| if (!shouldIncludeNode(exeContext, selection) || !doesFragmentConditionMatch(exeContext, selection, runtimeType)) { |
| continue; |
| } |
| |
| collectFields(exeContext, runtimeType, selection.selectionSet, fields, visitedFragmentNames); |
| break; |
| } |
| |
| case _kinds.Kind.FRAGMENT_SPREAD: |
| { |
| var fragName = selection.name.value; |
| |
| if (visitedFragmentNames[fragName] || !shouldIncludeNode(exeContext, selection)) { |
| continue; |
| } |
| |
| visitedFragmentNames[fragName] = true; |
| var fragment = exeContext.fragments[fragName]; |
| |
| if (!fragment || !doesFragmentConditionMatch(exeContext, fragment, runtimeType)) { |
| continue; |
| } |
| |
| collectFields(exeContext, runtimeType, fragment.selectionSet, fields, visitedFragmentNames); |
| break; |
| } |
| } |
| } |
| |
| return fields; |
| } |
| /** |
| * Determines if a field should be included based on the @include and @skip |
| * directives, where @skip has higher precedence than @include. |
| */ |
| |
| |
| function shouldIncludeNode(exeContext, node) { |
| var skip = (0, _values.getDirectiveValues)(_directives.GraphQLSkipDirective, node, exeContext.variableValues); |
| |
| if ((skip === null || skip === void 0 ? void 0 : skip.if) === true) { |
| return false; |
| } |
| |
| var include = (0, _values.getDirectiveValues)(_directives.GraphQLIncludeDirective, node, exeContext.variableValues); |
| |
| if ((include === null || include === void 0 ? void 0 : include.if) === false) { |
| return false; |
| } |
| |
| return true; |
| } |
| /** |
| * Determines if a fragment is applicable to the given type. |
| */ |
| |
| |
| function doesFragmentConditionMatch(exeContext, fragment, type) { |
| var typeConditionNode = fragment.typeCondition; |
| |
| if (!typeConditionNode) { |
| return true; |
| } |
| |
| var conditionalType = (0, _typeFromAST.typeFromAST)(exeContext.schema, typeConditionNode); |
| |
| if (conditionalType === type) { |
| return true; |
| } |
| |
| if ((0, _definition.isAbstractType)(conditionalType)) { |
| return exeContext.schema.isSubType(conditionalType, type); |
| } |
| |
| return false; |
| } |
| /** |
| * Implements the logic to compute the key of a given field's entry |
| */ |
| |
| |
| function getFieldEntryKey(node) { |
| return node.alias ? node.alias.value : node.name.value; |
| } |
| /** |
| * Resolves the field on the given source object. In particular, this |
| * figures out the value that the field returns by calling its resolve function, |
| * then calls completeValue to complete promises, serialize scalars, or execute |
| * the sub-selection-set for objects. |
| */ |
| |
| |
| function resolveField(exeContext, parentType, source, fieldNodes, path) { |
| var _fieldDef$resolve; |
| |
| var fieldNode = fieldNodes[0]; |
| var fieldName = fieldNode.name.value; |
| var fieldDef = getFieldDef(exeContext.schema, parentType, fieldName); |
| |
| if (!fieldDef) { |
| return; |
| } |
| |
| var resolveFn = (_fieldDef$resolve = fieldDef.resolve) !== null && _fieldDef$resolve !== void 0 ? _fieldDef$resolve : exeContext.fieldResolver; |
| var info = buildResolveInfo(exeContext, fieldDef, fieldNodes, parentType, path); // Get the resolve function, regardless of if its result is normal |
| // or abrupt (error). |
| |
| var result = resolveFieldValueOrError(exeContext, fieldDef, fieldNodes, resolveFn, source, info); |
| return completeValueCatchingError(exeContext, fieldDef.type, fieldNodes, info, path, result); |
| } |
| /** |
| * @internal |
| */ |
| |
| |
| function buildResolveInfo(exeContext, fieldDef, fieldNodes, parentType, path) { |
| // The resolve function's optional fourth argument is a collection of |
| // information about the current execution state. |
| return { |
| fieldName: fieldDef.name, |
| fieldNodes: fieldNodes, |
| returnType: fieldDef.type, |
| parentType: parentType, |
| path: path, |
| schema: exeContext.schema, |
| fragments: exeContext.fragments, |
| rootValue: exeContext.rootValue, |
| operation: exeContext.operation, |
| variableValues: exeContext.variableValues |
| }; |
| } |
| /** |
| * Isolates the "ReturnOrAbrupt" behavior to not de-opt the `resolveField` |
| * function. Returns the result of resolveFn or the abrupt-return Error object. |
| * |
| * @internal |
| */ |
| |
| |
| function resolveFieldValueOrError(exeContext, fieldDef, fieldNodes, resolveFn, source, info) { |
| try { |
| // Build a JS object of arguments from the field.arguments AST, using the |
| // variables scope to fulfill any variable references. |
| // TODO: find a way to memoize, in case this field is within a List type. |
| var args = (0, _values.getArgumentValues)(fieldDef, fieldNodes[0], exeContext.variableValues); // The resolve function's optional third argument is a context value that |
| // is provided to every resolve function within an execution. It is commonly |
| // used to represent an authenticated user, or request-specific caches. |
| |
| var _contextValue = exeContext.contextValue; |
| var result = resolveFn(source, args, _contextValue, info); |
| return (0, _isPromise.default)(result) ? result.then(undefined, asErrorInstance) : result; |
| } catch (error) { |
| return asErrorInstance(error); |
| } |
| } // Sometimes a non-error is thrown, wrap it as an Error instance to ensure a |
| // consistent Error interface. |
| |
| |
| function asErrorInstance(error) { |
| if (error instanceof Error) { |
| return error; |
| } |
| |
| return new Error('Unexpected error value: ' + (0, _inspect.default)(error)); |
| } // This is a small wrapper around completeValue which detects and logs errors |
| // in the execution context. |
| |
| |
| function completeValueCatchingError(exeContext, returnType, fieldNodes, info, path, result) { |
| try { |
| var completed; |
| |
| if ((0, _isPromise.default)(result)) { |
| completed = result.then(function (resolved) { |
| return completeValue(exeContext, returnType, fieldNodes, info, path, resolved); |
| }); |
| } else { |
| completed = completeValue(exeContext, returnType, fieldNodes, info, path, result); |
| } |
| |
| if ((0, _isPromise.default)(completed)) { |
| // Note: we don't rely on a `catch` method, but we do expect "thenable" |
| // to take a second callback for the error case. |
| return completed.then(undefined, function (error) { |
| return handleFieldError(error, fieldNodes, path, returnType, exeContext); |
| }); |
| } |
| |
| return completed; |
| } catch (error) { |
| return handleFieldError(error, fieldNodes, path, returnType, exeContext); |
| } |
| } |
| |
| function handleFieldError(rawError, fieldNodes, path, returnType, exeContext) { |
| var error = (0, _locatedError.locatedError)(asErrorInstance(rawError), fieldNodes, (0, _Path.pathToArray)(path)); // If the field type is non-nullable, then it is resolved without any |
| // protection from errors, however it still properly locates the error. |
| |
| if ((0, _definition.isNonNullType)(returnType)) { |
| throw error; |
| } // Otherwise, error protection is applied, logging the error and resolving |
| // a null value for this field if one is encountered. |
| |
| |
| exeContext.errors.push(error); |
| return null; |
| } |
| /** |
| * Implements the instructions for completeValue as defined in the |
| * "Field entries" section of the spec. |
| * |
| * If the field type is Non-Null, then this recursively completes the value |
| * for the inner type. It throws a field error if that completion returns null, |
| * as per the "Nullability" section of the spec. |
| * |
| * If the field type is a List, then this recursively completes the value |
| * for the inner type on each item in the list. |
| * |
| * If the field type is a Scalar or Enum, ensures the completed value is a legal |
| * value of the type by calling the `serialize` method of GraphQL type |
| * definition. |
| * |
| * If the field is an abstract type, determine the runtime type of the value |
| * and then complete based on that type |
| * |
| * Otherwise, the field type expects a sub-selection set, and will complete the |
| * value by evaluating all sub-selections. |
| */ |
| |
| |
| function completeValue(exeContext, returnType, fieldNodes, info, path, result) { |
| // If result is an Error, throw a located error. |
| if (result instanceof Error) { |
| throw result; |
| } // If field type is NonNull, complete for inner type, and throw field error |
| // if result is null. |
| |
| |
| if ((0, _definition.isNonNullType)(returnType)) { |
| var completed = completeValue(exeContext, returnType.ofType, fieldNodes, info, path, result); |
| |
| if (completed === null) { |
| throw new Error("Cannot return null for non-nullable field ".concat(info.parentType.name, ".").concat(info.fieldName, ".")); |
| } |
| |
| return completed; |
| } // If result value is null or undefined then return null. |
| |
| |
| if (result == null) { |
| return null; |
| } // If field type is List, complete each item in the list with the inner type |
| |
| |
| if ((0, _definition.isListType)(returnType)) { |
| return completeListValue(exeContext, returnType, fieldNodes, info, path, result); |
| } // If field type is a leaf type, Scalar or Enum, serialize to a valid value, |
| // returning null if serialization is not possible. |
| |
| |
| if ((0, _definition.isLeafType)(returnType)) { |
| return completeLeafValue(returnType, result); |
| } // If field type is an abstract type, Interface or Union, determine the |
| // runtime Object type and complete for that type. |
| |
| |
| if ((0, _definition.isAbstractType)(returnType)) { |
| return completeAbstractValue(exeContext, returnType, fieldNodes, info, path, result); |
| } // If field type is Object, execute and complete all sub-selections. |
| |
| |
| /* istanbul ignore else */ |
| if ((0, _definition.isObjectType)(returnType)) { |
| return completeObjectValue(exeContext, returnType, fieldNodes, info, path, result); |
| } // Not reachable. All possible output types have been considered. |
| |
| |
| /* istanbul ignore next */ |
| (0, _invariant.default)(false, 'Cannot complete value of unexpected output type: ' + (0, _inspect.default)(returnType)); |
| } |
| /** |
| * Complete a list value by completing each item in the list with the |
| * inner type |
| */ |
| |
| |
| function completeListValue(exeContext, returnType, fieldNodes, info, path, result) { |
| if (!(0, _isCollection.default)(result)) { |
| throw new _GraphQLError.GraphQLError("Expected Iterable, but did not find one for field \"".concat(info.parentType.name, ".").concat(info.fieldName, "\".")); |
| } // This is specified as a simple map, however we're optimizing the path |
| // where the list contains no Promises by avoiding creating another Promise. |
| |
| |
| var itemType = returnType.ofType; |
| var containsPromise = false; |
| var completedResults = (0, _arrayFrom.default)(result, function (item, index) { |
| // No need to modify the info object containing the path, |
| // since from here on it is not ever accessed by resolver functions. |
| var fieldPath = (0, _Path.addPath)(path, index); |
| var completedItem = completeValueCatchingError(exeContext, itemType, fieldNodes, info, fieldPath, item); |
| |
| if (!containsPromise && (0, _isPromise.default)(completedItem)) { |
| containsPromise = true; |
| } |
| |
| return completedItem; |
| }); |
| return containsPromise ? Promise.all(completedResults) : completedResults; |
| } |
| /** |
| * Complete a Scalar or Enum by serializing to a valid value, returning |
| * null if serialization is not possible. |
| */ |
| |
| |
| function completeLeafValue(returnType, result) { |
| var serializedResult = returnType.serialize(result); |
| |
| if (serializedResult === undefined) { |
| throw new Error("Expected a value of type \"".concat((0, _inspect.default)(returnType), "\" but ") + "received: ".concat((0, _inspect.default)(result))); |
| } |
| |
| return serializedResult; |
| } |
| /** |
| * Complete a value of an abstract type by determining the runtime object type |
| * of that value, then complete the value for that type. |
| */ |
| |
| |
| function completeAbstractValue(exeContext, returnType, fieldNodes, info, path, result) { |
| var _returnType$resolveTy; |
| |
| var resolveTypeFn = (_returnType$resolveTy = returnType.resolveType) !== null && _returnType$resolveTy !== void 0 ? _returnType$resolveTy : exeContext.typeResolver; |
| var contextValue = exeContext.contextValue; |
| var runtimeType = resolveTypeFn(result, contextValue, info, returnType); |
| |
| if ((0, _isPromise.default)(runtimeType)) { |
| return runtimeType.then(function (resolvedRuntimeType) { |
| return completeObjectValue(exeContext, ensureValidRuntimeType(resolvedRuntimeType, exeContext, returnType, fieldNodes, info, result), fieldNodes, info, path, result); |
| }); |
| } |
| |
| return completeObjectValue(exeContext, ensureValidRuntimeType(runtimeType, exeContext, returnType, fieldNodes, info, result), fieldNodes, info, path, result); |
| } |
| |
| function ensureValidRuntimeType(runtimeTypeOrName, exeContext, returnType, fieldNodes, info, result) { |
| var runtimeType = typeof runtimeTypeOrName === 'string' ? exeContext.schema.getType(runtimeTypeOrName) : runtimeTypeOrName; |
| |
| if (!(0, _definition.isObjectType)(runtimeType)) { |
| throw new _GraphQLError.GraphQLError("Abstract type \"".concat(returnType.name, "\" must resolve to an Object type at runtime for field \"").concat(info.parentType.name, ".").concat(info.fieldName, "\" with ") + "value ".concat((0, _inspect.default)(result), ", received \"").concat((0, _inspect.default)(runtimeType), "\". ") + "Either the \"".concat(returnType.name, "\" type should provide a \"resolveType\" function or each possible type should provide an \"isTypeOf\" function."), fieldNodes); |
| } |
| |
| if (!exeContext.schema.isSubType(returnType, runtimeType)) { |
| throw new _GraphQLError.GraphQLError("Runtime Object type \"".concat(runtimeType.name, "\" is not a possible type for \"").concat(returnType.name, "\"."), fieldNodes); |
| } |
| |
| return runtimeType; |
| } |
| /** |
| * Complete an Object value by executing all sub-selections. |
| */ |
| |
| |
| function completeObjectValue(exeContext, returnType, fieldNodes, info, path, result) { |
| // If there is an isTypeOf predicate function, call it with the |
| // current result. If isTypeOf returns false, then raise an error rather |
| // than continuing execution. |
| if (returnType.isTypeOf) { |
| var isTypeOf = returnType.isTypeOf(result, exeContext.contextValue, info); |
| |
| if ((0, _isPromise.default)(isTypeOf)) { |
| return isTypeOf.then(function (resolvedIsTypeOf) { |
| if (!resolvedIsTypeOf) { |
| throw invalidReturnTypeError(returnType, result, fieldNodes); |
| } |
| |
| return collectAndExecuteSubfields(exeContext, returnType, fieldNodes, path, result); |
| }); |
| } |
| |
| if (!isTypeOf) { |
| throw invalidReturnTypeError(returnType, result, fieldNodes); |
| } |
| } |
| |
| return collectAndExecuteSubfields(exeContext, returnType, fieldNodes, path, result); |
| } |
| |
| function invalidReturnTypeError(returnType, result, fieldNodes) { |
| return new _GraphQLError.GraphQLError("Expected value of type \"".concat(returnType.name, "\" but got: ").concat((0, _inspect.default)(result), "."), fieldNodes); |
| } |
| |
| function collectAndExecuteSubfields(exeContext, returnType, fieldNodes, path, result) { |
| // Collect sub-fields to execute to complete this value. |
| var subFieldNodes = collectSubfields(exeContext, returnType, fieldNodes); |
| return executeFields(exeContext, returnType, result, path, subFieldNodes); |
| } |
| /** |
| * A memoized collection of relevant subfields with regard to the return |
| * type. Memoizing ensures the subfields are not repeatedly calculated, which |
| * saves overhead when resolving lists of values. |
| */ |
| |
| |
| var collectSubfields = (0, _memoize.default)(_collectSubfields); |
| |
| function _collectSubfields(exeContext, returnType, fieldNodes) { |
| var subFieldNodes = Object.create(null); |
| var visitedFragmentNames = Object.create(null); |
| |
| for (var _i8 = 0; _i8 < fieldNodes.length; _i8++) { |
| var node = fieldNodes[_i8]; |
| |
| if (node.selectionSet) { |
| subFieldNodes = collectFields(exeContext, returnType, node.selectionSet, subFieldNodes, visitedFragmentNames); |
| } |
| } |
| |
| return subFieldNodes; |
| } |
| /** |
| * If a resolveType function is not given, then a default resolve behavior is |
| * used which attempts two strategies: |
| * |
| * First, See if the provided value has a `__typename` field defined, if so, use |
| * that value as name of the resolved type. |
| * |
| * Otherwise, test each possible type for the abstract type by calling |
| * isTypeOf for the object being coerced, returning the first type that matches. |
| */ |
| |
| |
| var defaultTypeResolver = function defaultTypeResolver(value, contextValue, info, abstractType) { |
| // First, look for `__typename`. |
| if ((0, _isObjectLike.default)(value) && typeof value.__typename === 'string') { |
| return value.__typename; |
| } // Otherwise, test each possible type. |
| |
| |
| var possibleTypes = info.schema.getPossibleTypes(abstractType); |
| var promisedIsTypeOfResults = []; |
| |
| for (var i = 0; i < possibleTypes.length; i++) { |
| var type = possibleTypes[i]; |
| |
| if (type.isTypeOf) { |
| var isTypeOfResult = type.isTypeOf(value, contextValue, info); |
| |
| if ((0, _isPromise.default)(isTypeOfResult)) { |
| promisedIsTypeOfResults[i] = isTypeOfResult; |
| } else if (isTypeOfResult) { |
| return type; |
| } |
| } |
| } |
| |
| if (promisedIsTypeOfResults.length) { |
| return Promise.all(promisedIsTypeOfResults).then(function (isTypeOfResults) { |
| for (var _i9 = 0; _i9 < isTypeOfResults.length; _i9++) { |
| if (isTypeOfResults[_i9]) { |
| return possibleTypes[_i9]; |
| } |
| } |
| }); |
| } |
| }; |
| /** |
| * If a resolve function is not given, then a default resolve behavior is used |
| * which takes the property of the source object of the same name as the field |
| * and returns it as the result, or if it's a function, returns the result |
| * of calling that function while passing along args and context value. |
| */ |
| |
| |
| exports.defaultTypeResolver = defaultTypeResolver; |
| |
| var defaultFieldResolver = function defaultFieldResolver(source, args, contextValue, info) { |
| // ensure source is a value for which property access is acceptable. |
| if ((0, _isObjectLike.default)(source) || typeof source === 'function') { |
| var property = source[info.fieldName]; |
| |
| if (typeof property === 'function') { |
| return source[info.fieldName](args, contextValue, info); |
| } |
| |
| return property; |
| } |
| }; |
| /** |
| * This method looks up the field on the given type definition. |
| * It has special casing for the two introspection fields, __schema |
| * and __typename. __typename is special because it can always be |
| * queried as a field, even in situations where no other fields |
| * are allowed, like on a Union. __schema could get automatically |
| * added to the query type, but that would require mutating type |
| * definitions, which would cause issues. |
| * |
| * @internal |
| */ |
| |
| |
| exports.defaultFieldResolver = defaultFieldResolver; |
| |
| function getFieldDef(schema, parentType, fieldName) { |
| if (fieldName === _introspection.SchemaMetaFieldDef.name && schema.getQueryType() === parentType) { |
| return _introspection.SchemaMetaFieldDef; |
| } else if (fieldName === _introspection.TypeMetaFieldDef.name && schema.getQueryType() === parentType) { |
| return _introspection.TypeMetaFieldDef; |
| } else if (fieldName === _introspection.TypeNameMetaFieldDef.name) { |
| return _introspection.TypeNameMetaFieldDef; |
| } |
| |
| return parentType.getFields()[fieldName]; |
| } |