UNPKG

graphql

Version:

A Query Language and Runtime which can target any service.

165 lines (130 loc) 5.71 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.undefinedFieldMessage = undefinedFieldMessage; exports.FieldsOnCorrectType = FieldsOnCorrectType; var _GraphQLError = require("../../error/GraphQLError"); var _suggestionList = _interopRequireDefault(require("../../jsutils/suggestionList")); var _quotedOrList = _interopRequireDefault(require("../../jsutils/quotedOrList")); var _definition = require("../../type/definition"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Copyright (c) 2015-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * strict */ function undefinedFieldMessage(fieldName, type, suggestedTypeNames, suggestedFieldNames) { var message = "Cannot query field \"".concat(fieldName, "\" on type \"").concat(type, "\"."); if (suggestedTypeNames.length !== 0) { var suggestions = (0, _quotedOrList.default)(suggestedTypeNames); message += " Did you mean to use an inline fragment on ".concat(suggestions, "?"); } else if (suggestedFieldNames.length !== 0) { message += " Did you mean ".concat((0, _quotedOrList.default)(suggestedFieldNames), "?"); } return message; } /** * Fields on correct type * * A GraphQL document is only valid if all fields selected are defined by the * parent type, or are an allowed meta field such as __typename. */ function FieldsOnCorrectType(context) { return { Field: function Field(node) { var type = context.getParentType(); if (type) { var fieldDef = context.getFieldDef(); if (!fieldDef) { // This field doesn't exist, lets look for suggestions. var schema = context.getSchema(); var fieldName = node.name.value; // First determine if there are any suggested types to condition on. var suggestedTypeNames = getSuggestedTypeNames(schema, type, fieldName); // If there are no suggested types, then perhaps this was a typo? var suggestedFieldNames = suggestedTypeNames.length !== 0 ? [] : getSuggestedFieldNames(schema, type, fieldName); // Report an error, including helpful suggestions. context.reportError(new _GraphQLError.GraphQLError(undefinedFieldMessage(fieldName, type.name, suggestedTypeNames, suggestedFieldNames), [node])); } } } }; } /** * Go through all of the implementations of type, as well as the interfaces that * they implement. If any of those types include the provided field, suggest * them, sorted by how often the type is referenced, starting with Interfaces. */ function getSuggestedTypeNames(schema, type, fieldName) { if ((0, _definition.isAbstractType)(type)) { var suggestedObjectTypes = []; var interfaceUsageCount = Object.create(null); var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = schema.getPossibleTypes(type)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var possibleType = _step.value; if (!possibleType.getFields()[fieldName]) { continue; } // This object type defines this field. suggestedObjectTypes.push(possibleType.name); var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = possibleType.getInterfaces()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var possibleInterface = _step2.value; if (!possibleInterface.getFields()[fieldName]) { continue; } // This interface type defines this field. interfaceUsageCount[possibleInterface.name] = (interfaceUsageCount[possibleInterface.name] || 0) + 1; } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return != null) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } // Suggest interface types based on how common they are. } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } var suggestedInterfaceTypes = Object.keys(interfaceUsageCount).sort(function (a, b) { return interfaceUsageCount[b] - interfaceUsageCount[a]; }); // Suggest both interface and object types. return suggestedInterfaceTypes.concat(suggestedObjectTypes); } // Otherwise, must be an Object type, which does not have possible fields. return []; } /** * For the field name provided, determine if there are any similar field names * that may be the result of a typo. */ function getSuggestedFieldNames(schema, type, fieldName) { if ((0, _definition.isObjectType)(type) || (0, _definition.isInterfaceType)(type)) { var possibleFieldNames = Object.keys(type.getFields()); return (0, _suggestionList.default)(fieldName, possibleFieldNames); } // Otherwise, must be a Union type, which does not define fields. return []; }