diff options
Diffstat (limited to 'school/node_modules/graphql/validation/rules/OverlappingFieldsCanBeMergedRule.mjs')
-rw-r--r-- | school/node_modules/graphql/validation/rules/OverlappingFieldsCanBeMergedRule.mjs | 568 |
1 files changed, 0 insertions, 568 deletions
diff --git a/school/node_modules/graphql/validation/rules/OverlappingFieldsCanBeMergedRule.mjs b/school/node_modules/graphql/validation/rules/OverlappingFieldsCanBeMergedRule.mjs deleted file mode 100644 index afc5243..0000000 --- a/school/node_modules/graphql/validation/rules/OverlappingFieldsCanBeMergedRule.mjs +++ /dev/null @@ -1,568 +0,0 @@ -import find from "../../polyfills/find.mjs"; -import objectEntries from "../../polyfills/objectEntries.mjs"; -import inspect from "../../jsutils/inspect.mjs"; -import { GraphQLError } from "../../error/GraphQLError.mjs"; -import { Kind } from "../../language/kinds.mjs"; -import { print } from "../../language/printer.mjs"; -import { getNamedType, isNonNullType, isLeafType, isObjectType, isListType, isInterfaceType } from "../../type/definition.mjs"; -import { typeFromAST } from "../../utilities/typeFromAST.mjs"; - -function reasonMessage(reason) { - if (Array.isArray(reason)) { - return reason.map(function (_ref) { - var responseName = _ref[0], - subReason = _ref[1]; - return "subfields \"".concat(responseName, "\" conflict because ") + reasonMessage(subReason); - }).join(' and '); - } - - return reason; -} -/** - * Overlapping fields can be merged - * - * A selection set is only valid if all fields (including spreading any - * fragments) either correspond to distinct response names or can be merged - * without ambiguity. - */ - - -export function OverlappingFieldsCanBeMergedRule(context) { - // A memoization for when two fragments are compared "between" each other for - // conflicts. Two fragments may be compared many times, so memoizing this can - // dramatically improve the performance of this validator. - var comparedFragmentPairs = new PairSet(); // A cache for the "field map" and list of fragment names found in any given - // selection set. Selection sets may be asked for this information multiple - // times, so this improves the performance of this validator. - - var cachedFieldsAndFragmentNames = new Map(); - return { - SelectionSet: function SelectionSet(selectionSet) { - var conflicts = findConflictsWithinSelectionSet(context, cachedFieldsAndFragmentNames, comparedFragmentPairs, context.getParentType(), selectionSet); - - for (var _i2 = 0; _i2 < conflicts.length; _i2++) { - var _ref3 = conflicts[_i2]; - var _ref2$ = _ref3[0]; - var responseName = _ref2$[0]; - var reason = _ref2$[1]; - var fields1 = _ref3[1]; - var fields2 = _ref3[2]; - var reasonMsg = reasonMessage(reason); - context.reportError(new GraphQLError("Fields \"".concat(responseName, "\" conflict because ").concat(reasonMsg, ". Use different aliases on the fields to fetch both if this was intentional."), fields1.concat(fields2))); - } - } - }; -} - -/** - * Algorithm: - * - * Conflicts occur when two fields exist in a query which will produce the same - * response name, but represent differing values, thus creating a conflict. - * The algorithm below finds all conflicts via making a series of comparisons - * between fields. In order to compare as few fields as possible, this makes - * a series of comparisons "within" sets of fields and "between" sets of fields. - * - * Given any selection set, a collection produces both a set of fields by - * also including all inline fragments, as well as a list of fragments - * referenced by fragment spreads. - * - * A) Each selection set represented in the document first compares "within" its - * collected set of fields, finding any conflicts between every pair of - * overlapping fields. - * Note: This is the *only time* that a the fields "within" a set are compared - * to each other. After this only fields "between" sets are compared. - * - * B) Also, if any fragment is referenced in a selection set, then a - * comparison is made "between" the original set of fields and the - * referenced fragment. - * - * C) Also, if multiple fragments are referenced, then comparisons - * are made "between" each referenced fragment. - * - * D) When comparing "between" a set of fields and a referenced fragment, first - * a comparison is made between each field in the original set of fields and - * each field in the the referenced set of fields. - * - * E) Also, if any fragment is referenced in the referenced selection set, - * then a comparison is made "between" the original set of fields and the - * referenced fragment (recursively referring to step D). - * - * F) When comparing "between" two fragments, first a comparison is made between - * each field in the first referenced set of fields and each field in the the - * second referenced set of fields. - * - * G) Also, any fragments referenced by the first must be compared to the - * second, and any fragments referenced by the second must be compared to the - * first (recursively referring to step F). - * - * H) When comparing two fields, if both have selection sets, then a comparison - * is made "between" both selection sets, first comparing the set of fields in - * the first selection set with the set of fields in the second. - * - * I) Also, if any fragment is referenced in either selection set, then a - * comparison is made "between" the other set of fields and the - * referenced fragment. - * - * J) Also, if two fragments are referenced in both selection sets, then a - * comparison is made "between" the two fragments. - * - */ -// Find all conflicts found "within" a selection set, including those found -// via spreading in fragments. Called when visiting each SelectionSet in the -// GraphQL Document. -function findConflictsWithinSelectionSet(context, cachedFieldsAndFragmentNames, comparedFragmentPairs, parentType, selectionSet) { - var conflicts = []; - - var _getFieldsAndFragment = getFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, parentType, selectionSet), - fieldMap = _getFieldsAndFragment[0], - fragmentNames = _getFieldsAndFragment[1]; // (A) Find find all conflicts "within" the fields of this selection set. - // Note: this is the *only place* `collectConflictsWithin` is called. - - - collectConflictsWithin(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, fieldMap); - - if (fragmentNames.length !== 0) { - // (B) Then collect conflicts between these fields and those represented by - // each spread fragment name found. - for (var i = 0; i < fragmentNames.length; i++) { - collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, false, fieldMap, fragmentNames[i]); // (C) Then compare this fragment with all other fragments found in this - // selection set to collect conflicts between fragments spread together. - // This compares each item in the list of fragment names to every other - // item in that same list (except for itself). - - for (var j = i + 1; j < fragmentNames.length; j++) { - collectConflictsBetweenFragments(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, false, fragmentNames[i], fragmentNames[j]); - } - } - } - - return conflicts; -} // Collect all conflicts found between a set of fields and a fragment reference -// including via spreading in any nested fragments. - - -function collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap, fragmentName) { - var fragment = context.getFragment(fragmentName); - - if (!fragment) { - return; - } - - var _getReferencedFieldsA = getReferencedFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, fragment), - fieldMap2 = _getReferencedFieldsA[0], - fragmentNames2 = _getReferencedFieldsA[1]; // Do not compare a fragment's fieldMap to itself. - - - if (fieldMap === fieldMap2) { - return; - } // (D) First collect any conflicts between the provided collection of fields - // and the collection of fields represented by the given fragment. - - - collectConflictsBetween(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap, fieldMap2); // (E) Then collect any conflicts between the provided collection of fields - // and any fragment names found in the given fragment. - - for (var i = 0; i < fragmentNames2.length; i++) { - collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap, fragmentNames2[i]); - } -} // Collect all conflicts found between two fragments, including via spreading in -// any nested fragments. - - -function collectConflictsBetweenFragments(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fragmentName1, fragmentName2) { - // No need to compare a fragment to itself. - if (fragmentName1 === fragmentName2) { - return; - } // Memoize so two fragments are not compared for conflicts more than once. - - - if (comparedFragmentPairs.has(fragmentName1, fragmentName2, areMutuallyExclusive)) { - return; - } - - comparedFragmentPairs.add(fragmentName1, fragmentName2, areMutuallyExclusive); - var fragment1 = context.getFragment(fragmentName1); - var fragment2 = context.getFragment(fragmentName2); - - if (!fragment1 || !fragment2) { - return; - } - - var _getReferencedFieldsA2 = getReferencedFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, fragment1), - fieldMap1 = _getReferencedFieldsA2[0], - fragmentNames1 = _getReferencedFieldsA2[1]; - - var _getReferencedFieldsA3 = getReferencedFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, fragment2), - fieldMap2 = _getReferencedFieldsA3[0], - fragmentNames2 = _getReferencedFieldsA3[1]; // (F) First, collect all conflicts between these two collections of fields - // (not including any nested fragments). - - - collectConflictsBetween(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap1, fieldMap2); // (G) Then collect conflicts between the first fragment and any nested - // fragments spread in the second fragment. - - for (var j = 0; j < fragmentNames2.length; j++) { - collectConflictsBetweenFragments(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fragmentName1, fragmentNames2[j]); - } // (G) Then collect conflicts between the second fragment and any nested - // fragments spread in the first fragment. - - - for (var i = 0; i < fragmentNames1.length; i++) { - collectConflictsBetweenFragments(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fragmentNames1[i], fragmentName2); - } -} // Find all conflicts found between two selection sets, including those found -// via spreading in fragments. Called when determining if conflicts exist -// between the sub-fields of two overlapping fields. - - -function findConflictsBetweenSubSelectionSets(context, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, parentType1, selectionSet1, parentType2, selectionSet2) { - var conflicts = []; - - var _getFieldsAndFragment2 = getFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, parentType1, selectionSet1), - fieldMap1 = _getFieldsAndFragment2[0], - fragmentNames1 = _getFieldsAndFragment2[1]; - - var _getFieldsAndFragment3 = getFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, parentType2, selectionSet2), - fieldMap2 = _getFieldsAndFragment3[0], - fragmentNames2 = _getFieldsAndFragment3[1]; // (H) First, collect all conflicts between these two collections of field. - - - collectConflictsBetween(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap1, fieldMap2); // (I) Then collect conflicts between the first collection of fields and - // those referenced by each fragment name associated with the second. - - if (fragmentNames2.length !== 0) { - for (var j = 0; j < fragmentNames2.length; j++) { - collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap1, fragmentNames2[j]); - } - } // (I) Then collect conflicts between the second collection of fields and - // those referenced by each fragment name associated with the first. - - - if (fragmentNames1.length !== 0) { - for (var i = 0; i < fragmentNames1.length; i++) { - collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap2, fragmentNames1[i]); - } - } // (J) Also collect conflicts between any fragment names by the first and - // fragment names by the second. This compares each item in the first set of - // names to each item in the second set of names. - - - for (var _i3 = 0; _i3 < fragmentNames1.length; _i3++) { - for (var _j = 0; _j < fragmentNames2.length; _j++) { - collectConflictsBetweenFragments(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fragmentNames1[_i3], fragmentNames2[_j]); - } - } - - return conflicts; -} // Collect all Conflicts "within" one collection of fields. - - -function collectConflictsWithin(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, fieldMap) { - // A field map is a keyed collection, where each key represents a response - // name and the value at that key is a list of all fields which provide that - // response name. For every response name, if there are multiple fields, they - // must be compared to find a potential conflict. - for (var _i5 = 0, _objectEntries2 = objectEntries(fieldMap); _i5 < _objectEntries2.length; _i5++) { - var _ref5 = _objectEntries2[_i5]; - var responseName = _ref5[0]; - var fields = _ref5[1]; - - // This compares every field in the list to every other field in this list - // (except to itself). If the list only has one item, nothing needs to - // be compared. - if (fields.length > 1) { - for (var i = 0; i < fields.length; i++) { - for (var j = i + 1; j < fields.length; j++) { - var conflict = findConflict(context, cachedFieldsAndFragmentNames, comparedFragmentPairs, false, // within one collection is never mutually exclusive - responseName, fields[i], fields[j]); - - if (conflict) { - conflicts.push(conflict); - } - } - } - } - } -} // Collect all Conflicts between two collections of fields. This is similar to, -// but different from the `collectConflictsWithin` function above. This check -// assumes that `collectConflictsWithin` has already been called on each -// provided collection of fields. This is true because this validator traverses -// each individual selection set. - - -function collectConflictsBetween(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, parentFieldsAreMutuallyExclusive, fieldMap1, fieldMap2) { - // A field map is a keyed collection, where each key represents a response - // name and the value at that key is a list of all fields which provide that - // response name. For any response name which appears in both provided field - // maps, each field from the first field map must be compared to every field - // in the second field map to find potential conflicts. - for (var _i7 = 0, _Object$keys2 = Object.keys(fieldMap1); _i7 < _Object$keys2.length; _i7++) { - var responseName = _Object$keys2[_i7]; - var fields2 = fieldMap2[responseName]; - - if (fields2) { - var fields1 = fieldMap1[responseName]; - - for (var i = 0; i < fields1.length; i++) { - for (var j = 0; j < fields2.length; j++) { - var conflict = findConflict(context, cachedFieldsAndFragmentNames, comparedFragmentPairs, parentFieldsAreMutuallyExclusive, responseName, fields1[i], fields2[j]); - - if (conflict) { - conflicts.push(conflict); - } - } - } - } - } -} // Determines if there is a conflict between two particular fields, including -// comparing their sub-fields. - - -function findConflict(context, cachedFieldsAndFragmentNames, comparedFragmentPairs, parentFieldsAreMutuallyExclusive, responseName, field1, field2) { - var parentType1 = field1[0], - node1 = field1[1], - def1 = field1[2]; - var parentType2 = field2[0], - node2 = field2[1], - def2 = field2[2]; // If it is known that two fields could not possibly apply at the same - // time, due to the parent types, then it is safe to permit them to diverge - // in aliased field or arguments used as they will not present any ambiguity - // by differing. - // It is known that two parent types could never overlap if they are - // different Object types. Interface or Union types might overlap - if not - // in the current state of the schema, then perhaps in some future version, - // thus may not safely diverge. - - var areMutuallyExclusive = parentFieldsAreMutuallyExclusive || parentType1 !== parentType2 && isObjectType(parentType1) && isObjectType(parentType2); - - if (!areMutuallyExclusive) { - var _node1$arguments, _node2$arguments; - - // Two aliases must refer to the same field. - var name1 = node1.name.value; - var name2 = node2.name.value; - - if (name1 !== name2) { - return [[responseName, "\"".concat(name1, "\" and \"").concat(name2, "\" are different fields")], [node1], [node2]]; - } // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203') - - - var args1 = (_node1$arguments = node1.arguments) !== null && _node1$arguments !== void 0 ? _node1$arguments : []; // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203') - - var args2 = (_node2$arguments = node2.arguments) !== null && _node2$arguments !== void 0 ? _node2$arguments : []; // Two field calls must have the same arguments. - - if (!sameArguments(args1, args2)) { - return [[responseName, 'they have differing arguments'], [node1], [node2]]; - } - } // The return type for each field. - - - var type1 = def1 === null || def1 === void 0 ? void 0 : def1.type; - var type2 = def2 === null || def2 === void 0 ? void 0 : def2.type; - - if (type1 && type2 && doTypesConflict(type1, type2)) { - return [[responseName, "they return conflicting types \"".concat(inspect(type1), "\" and \"").concat(inspect(type2), "\"")], [node1], [node2]]; - } // Collect and compare sub-fields. Use the same "visited fragment names" list - // for both collections so fields in a fragment reference are never - // compared to themselves. - - - var selectionSet1 = node1.selectionSet; - var selectionSet2 = node2.selectionSet; - - if (selectionSet1 && selectionSet2) { - var conflicts = findConflictsBetweenSubSelectionSets(context, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, getNamedType(type1), selectionSet1, getNamedType(type2), selectionSet2); - return subfieldConflicts(conflicts, responseName, node1, node2); - } -} - -function sameArguments(arguments1, arguments2) { - if (arguments1.length !== arguments2.length) { - return false; - } - - return arguments1.every(function (argument1) { - var argument2 = find(arguments2, function (argument) { - return argument.name.value === argument1.name.value; - }); - - if (!argument2) { - return false; - } - - return sameValue(argument1.value, argument2.value); - }); -} - -function sameValue(value1, value2) { - return print(value1) === print(value2); -} // Two types conflict if both types could not apply to a value simultaneously. -// Composite types are ignored as their individual field types will be compared -// later recursively. However List and Non-Null types must match. - - -function doTypesConflict(type1, type2) { - if (isListType(type1)) { - return isListType(type2) ? doTypesConflict(type1.ofType, type2.ofType) : true; - } - - if (isListType(type2)) { - return true; - } - - if (isNonNullType(type1)) { - return isNonNullType(type2) ? doTypesConflict(type1.ofType, type2.ofType) : true; - } - - if (isNonNullType(type2)) { - return true; - } - - if (isLeafType(type1) || isLeafType(type2)) { - return type1 !== type2; - } - - return false; -} // Given a selection set, return the collection of fields (a mapping of response -// name to field nodes and definitions) as well as a list of fragment names -// referenced via fragment spreads. - - -function getFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, parentType, selectionSet) { - var cached = cachedFieldsAndFragmentNames.get(selectionSet); - - if (!cached) { - var nodeAndDefs = Object.create(null); - var fragmentNames = Object.create(null); - - _collectFieldsAndFragmentNames(context, parentType, selectionSet, nodeAndDefs, fragmentNames); - - cached = [nodeAndDefs, Object.keys(fragmentNames)]; - cachedFieldsAndFragmentNames.set(selectionSet, cached); - } - - return cached; -} // Given a reference to a fragment, return the represented collection of fields -// as well as a list of nested fragment names referenced via fragment spreads. - - -function getReferencedFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, fragment) { - // Short-circuit building a type from the node if possible. - var cached = cachedFieldsAndFragmentNames.get(fragment.selectionSet); - - if (cached) { - return cached; - } - - var fragmentType = typeFromAST(context.getSchema(), fragment.typeCondition); - return getFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, fragmentType, fragment.selectionSet); -} - -function _collectFieldsAndFragmentNames(context, parentType, selectionSet, nodeAndDefs, fragmentNames) { - for (var _i9 = 0, _selectionSet$selecti2 = selectionSet.selections; _i9 < _selectionSet$selecti2.length; _i9++) { - var selection = _selectionSet$selecti2[_i9]; - - switch (selection.kind) { - case Kind.FIELD: - { - var fieldName = selection.name.value; - var fieldDef = void 0; - - if (isObjectType(parentType) || isInterfaceType(parentType)) { - fieldDef = parentType.getFields()[fieldName]; - } - - var responseName = selection.alias ? selection.alias.value : fieldName; - - if (!nodeAndDefs[responseName]) { - nodeAndDefs[responseName] = []; - } - - nodeAndDefs[responseName].push([parentType, selection, fieldDef]); - break; - } - - case Kind.FRAGMENT_SPREAD: - fragmentNames[selection.name.value] = true; - break; - - case Kind.INLINE_FRAGMENT: - { - var typeCondition = selection.typeCondition; - var inlineFragmentType = typeCondition ? typeFromAST(context.getSchema(), typeCondition) : parentType; - - _collectFieldsAndFragmentNames(context, inlineFragmentType, selection.selectionSet, nodeAndDefs, fragmentNames); - - break; - } - } - } -} // Given a series of Conflicts which occurred between two sub-fields, generate -// a single Conflict. - - -function subfieldConflicts(conflicts, responseName, node1, node2) { - if (conflicts.length > 0) { - return [[responseName, conflicts.map(function (_ref6) { - var reason = _ref6[0]; - return reason; - })], conflicts.reduce(function (allFields, _ref7) { - var fields1 = _ref7[1]; - return allFields.concat(fields1); - }, [node1]), conflicts.reduce(function (allFields, _ref8) { - var fields2 = _ref8[2]; - return allFields.concat(fields2); - }, [node2])]; - } -} -/** - * A way to keep track of pairs of things when the ordering of the pair does - * not matter. We do this by maintaining a sort of double adjacency sets. - */ - - -var PairSet = /*#__PURE__*/function () { - function PairSet() { - this._data = Object.create(null); - } - - var _proto = PairSet.prototype; - - _proto.has = function has(a, b, areMutuallyExclusive) { - var first = this._data[a]; - var result = first && first[b]; - - if (result === undefined) { - return false; - } // areMutuallyExclusive being false is a superset of being true, - // hence if we want to know if this PairSet "has" these two with no - // exclusivity, we have to ensure it was added as such. - - - if (areMutuallyExclusive === false) { - return result === false; - } - - return true; - }; - - _proto.add = function add(a, b, areMutuallyExclusive) { - this._pairSetAdd(a, b, areMutuallyExclusive); - - this._pairSetAdd(b, a, areMutuallyExclusive); - }; - - _proto._pairSetAdd = function _pairSetAdd(a, b, areMutuallyExclusive) { - var map = this._data[a]; - - if (!map) { - map = Object.create(null); - this._data[a] = map; - } - - map[b] = areMutuallyExclusive; - }; - - return PairSet; -}(); |