@graphql-inspector/action 3.1.2 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.js +4528 -83
  2. package/index.mjs +4528 -83
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -1971,6 +1971,18 @@ function readName(lexer, start) {
1971
1971
  );
1972
1972
  }
1973
1973
 
1974
+ /**
1975
+ * Configuration options to control parser behavior
1976
+ */
1977
+
1978
+ /**
1979
+ * Given a GraphQL source, parses it into a Document.
1980
+ * Throws GraphQLError if a syntax error is encountered.
1981
+ */
1982
+ function parse(source, options) {
1983
+ const parser = new Parser(source, options);
1984
+ return parser.parseDocument();
1985
+ }
1974
1986
  /**
1975
1987
  * Given a string containing a GraphQL value (ex. `[42]`), parse the AST for
1976
1988
  * that value.
@@ -3690,6 +3702,85 @@ function visit(root, visitor, visitorKeys = QueryDocumentKeys) {
3690
3702
 
3691
3703
  return newRoot;
3692
3704
  }
3705
+ /**
3706
+ * Creates a new visitor instance which delegates to many visitors to run in
3707
+ * parallel. Each visitor will be visited for each node before moving on.
3708
+ *
3709
+ * If a prior visitor edits a node, no following visitors will see that node.
3710
+ */
3711
+
3712
+ function visitInParallel(visitors) {
3713
+ const skipping = new Array(visitors.length).fill(null);
3714
+ const mergedVisitor = Object.create(null);
3715
+
3716
+ for (const kind of Object.values(Kind)) {
3717
+ let hasVisitor = false;
3718
+ const enterList = new Array(visitors.length).fill(undefined);
3719
+ const leaveList = new Array(visitors.length).fill(undefined);
3720
+
3721
+ for (let i = 0; i < visitors.length; ++i) {
3722
+ const { enter, leave } = getEnterLeaveForKind(visitors[i], kind);
3723
+ hasVisitor || (hasVisitor = enter != null || leave != null);
3724
+ enterList[i] = enter;
3725
+ leaveList[i] = leave;
3726
+ }
3727
+
3728
+ if (!hasVisitor) {
3729
+ continue;
3730
+ }
3731
+
3732
+ const mergedEnterLeave = {
3733
+ enter(...args) {
3734
+ const node = args[0];
3735
+
3736
+ for (let i = 0; i < visitors.length; i++) {
3737
+ if (skipping[i] === null) {
3738
+ var _enterList$i;
3739
+
3740
+ const result =
3741
+ (_enterList$i = enterList[i]) === null || _enterList$i === void 0
3742
+ ? void 0
3743
+ : _enterList$i.apply(visitors[i], args);
3744
+
3745
+ if (result === false) {
3746
+ skipping[i] = node;
3747
+ } else if (result === BREAK) {
3748
+ skipping[i] = BREAK;
3749
+ } else if (result !== undefined) {
3750
+ return result;
3751
+ }
3752
+ }
3753
+ }
3754
+ },
3755
+
3756
+ leave(...args) {
3757
+ const node = args[0];
3758
+
3759
+ for (let i = 0; i < visitors.length; i++) {
3760
+ if (skipping[i] === null) {
3761
+ var _leaveList$i;
3762
+
3763
+ const result =
3764
+ (_leaveList$i = leaveList[i]) === null || _leaveList$i === void 0
3765
+ ? void 0
3766
+ : _leaveList$i.apply(visitors[i], args);
3767
+
3768
+ if (result === BREAK) {
3769
+ skipping[i] = BREAK;
3770
+ } else if (result !== undefined && result !== false) {
3771
+ return result;
3772
+ }
3773
+ } else if (skipping[i] === node) {
3774
+ skipping[i] = null;
3775
+ }
3776
+ }
3777
+ },
3778
+ };
3779
+ mergedVisitor[kind] = mergedEnterLeave;
3780
+ }
3781
+
3782
+ return mergedVisitor;
3783
+ }
3693
3784
  /**
3694
3785
  * Given a visitor instance and a node kind, return EnterLeaveVisitor for that kind.
3695
3786
  */
@@ -4746,6 +4837,13 @@ function isLeafType(type) {
4746
4837
  * These types may describe the parent context of a selection set.
4747
4838
  */
4748
4839
 
4840
+ function isCompositeType(type) {
4841
+ return isObjectType(type) || isInterfaceType(type) || isUnionType(type);
4842
+ }
4843
+ /**
4844
+ * These types may describe the parent context of a selection set.
4845
+ */
4846
+
4749
4847
  function isAbstractType(type) {
4750
4848
  return isInterfaceType(type) || isUnionType(type);
4751
4849
  }
@@ -4853,6 +4951,11 @@ function assertNullableType(type) {
4853
4951
 
4854
4952
  return type;
4855
4953
  }
4954
+ function getNullableType(type) {
4955
+ if (type) {
4956
+ return isNonNullType(type) ? type.ofType : type;
4957
+ }
4958
+ }
4856
4959
  function getNamedType(type) {
4857
4960
  if (type) {
4858
4961
  let unwrappedType = type;
@@ -5214,6 +5317,9 @@ function argsToArgsConfig(args) {
5214
5317
  }),
5215
5318
  );
5216
5319
  }
5320
+ function isRequiredArgument(arg) {
5321
+ return isNonNullType(arg.type) && arg.defaultValue === undefined;
5322
+ }
5217
5323
 
5218
5324
  /**
5219
5325
  * Interface Type Definition
@@ -5671,6 +5777,90 @@ function defineInputFieldMap(config) {
5671
5777
  });
5672
5778
  }
5673
5779
 
5780
+ function isRequiredInputField(field) {
5781
+ return isNonNullType(field.type) && field.defaultValue === undefined;
5782
+ }
5783
+
5784
+ /**
5785
+ * Provided a type and a super type, return true if the first type is either
5786
+ * equal or a subset of the second super type (covariant).
5787
+ */
5788
+
5789
+ function isTypeSubTypeOf(schema, maybeSubType, superType) {
5790
+ // Equivalent type is a valid subtype
5791
+ if (maybeSubType === superType) {
5792
+ return true;
5793
+ } // If superType is non-null, maybeSubType must also be non-null.
5794
+
5795
+ if (isNonNullType(superType)) {
5796
+ if (isNonNullType(maybeSubType)) {
5797
+ return isTypeSubTypeOf(schema, maybeSubType.ofType, superType.ofType);
5798
+ }
5799
+
5800
+ return false;
5801
+ }
5802
+
5803
+ if (isNonNullType(maybeSubType)) {
5804
+ // If superType is nullable, maybeSubType may be non-null or nullable.
5805
+ return isTypeSubTypeOf(schema, maybeSubType.ofType, superType);
5806
+ } // If superType type is a list, maybeSubType type must also be a list.
5807
+
5808
+ if (isListType(superType)) {
5809
+ if (isListType(maybeSubType)) {
5810
+ return isTypeSubTypeOf(schema, maybeSubType.ofType, superType.ofType);
5811
+ }
5812
+
5813
+ return false;
5814
+ }
5815
+
5816
+ if (isListType(maybeSubType)) {
5817
+ // If superType is not a list, maybeSubType must also be not a list.
5818
+ return false;
5819
+ } // If superType type is an abstract type, check if it is super type of maybeSubType.
5820
+ // Otherwise, the child type is not a valid subtype of the parent type.
5821
+
5822
+ return (
5823
+ isAbstractType(superType) &&
5824
+ (isInterfaceType(maybeSubType) || isObjectType(maybeSubType)) &&
5825
+ schema.isSubType(superType, maybeSubType)
5826
+ );
5827
+ }
5828
+ /**
5829
+ * Provided two composite types, determine if they "overlap". Two composite
5830
+ * types overlap when the Sets of possible concrete types for each intersect.
5831
+ *
5832
+ * This is often used to determine if a fragment of a given type could possibly
5833
+ * be visited in a context of another type.
5834
+ *
5835
+ * This function is commutative.
5836
+ */
5837
+
5838
+ function doTypesOverlap(schema, typeA, typeB) {
5839
+ // Equivalent types overlap
5840
+ if (typeA === typeB) {
5841
+ return true;
5842
+ }
5843
+
5844
+ if (isAbstractType(typeA)) {
5845
+ if (isAbstractType(typeB)) {
5846
+ // If both types are abstract, then determine if there is any intersection
5847
+ // between possible concrete types of each.
5848
+ return schema
5849
+ .getPossibleTypes(typeA)
5850
+ .some((type) => schema.isSubType(typeB, type));
5851
+ } // Determine if the latter type is a possible concrete type of the former.
5852
+
5853
+ return schema.isSubType(typeA, typeB);
5854
+ }
5855
+
5856
+ if (isAbstractType(typeB)) {
5857
+ // Determine if the former type is a possible concrete type of the latter.
5858
+ return schema.isSubType(typeB, typeA);
5859
+ } // Otherwise the types do not overlap.
5860
+
5861
+ return false;
5862
+ }
5863
+
5674
5864
  /**
5675
5865
  * Returns true if the provided object is an Object (i.e. not a string literal)
5676
5866
  * and implements the Iterator protocol.
@@ -7197,6 +7387,166 @@ function collectReferencedTypes(type, typeSet) {
7197
7387
  return typeSet;
7198
7388
  }
7199
7389
 
7390
+ /**
7391
+ * Given a Schema and an AST node describing a type, return a GraphQLType
7392
+ * definition which applies to that type. For example, if provided the parsed
7393
+ * AST node for `[User]`, a GraphQLList instance will be returned, containing
7394
+ * the type called "User" found in the schema. If a type called "User" is not
7395
+ * found in the schema, then undefined will be returned.
7396
+ */
7397
+
7398
+ function typeFromAST(schema, typeNode) {
7399
+ let innerType;
7400
+
7401
+ if (typeNode.kind === Kind.LIST_TYPE) {
7402
+ innerType = typeFromAST(schema, typeNode.type);
7403
+ return innerType && new GraphQLList(innerType);
7404
+ }
7405
+
7406
+ if (typeNode.kind === Kind.NON_NULL_TYPE) {
7407
+ innerType = typeFromAST(schema, typeNode.type);
7408
+ return innerType && new GraphQLNonNull(innerType);
7409
+ } // istanbul ignore else (See: 'https://github.com/graphql/graphql-js/issues/2618')
7410
+
7411
+ if (typeNode.kind === Kind.NAMED_TYPE) {
7412
+ return schema.getType(typeNode.name.value);
7413
+ } // istanbul ignore next (Not reachable. All possible type nodes have been considered)
7414
+
7415
+ invariant(false, 'Unexpected type node: ' + inspect(typeNode));
7416
+ }
7417
+
7418
+ function isExecutableDefinitionNode(node) {
7419
+ return (
7420
+ node.kind === Kind.OPERATION_DEFINITION ||
7421
+ node.kind === Kind.FRAGMENT_DEFINITION
7422
+ );
7423
+ }
7424
+ function isTypeSystemDefinitionNode(node) {
7425
+ return (
7426
+ node.kind === Kind.SCHEMA_DEFINITION ||
7427
+ isTypeDefinitionNode(node) ||
7428
+ node.kind === Kind.DIRECTIVE_DEFINITION
7429
+ );
7430
+ }
7431
+ function isTypeDefinitionNode(node) {
7432
+ return (
7433
+ node.kind === Kind.SCALAR_TYPE_DEFINITION ||
7434
+ node.kind === Kind.OBJECT_TYPE_DEFINITION ||
7435
+ node.kind === Kind.INTERFACE_TYPE_DEFINITION ||
7436
+ node.kind === Kind.UNION_TYPE_DEFINITION ||
7437
+ node.kind === Kind.ENUM_TYPE_DEFINITION ||
7438
+ node.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION
7439
+ );
7440
+ }
7441
+ function isTypeSystemExtensionNode(node) {
7442
+ return node.kind === Kind.SCHEMA_EXTENSION || isTypeExtensionNode(node);
7443
+ }
7444
+ function isTypeExtensionNode(node) {
7445
+ return (
7446
+ node.kind === Kind.SCALAR_TYPE_EXTENSION ||
7447
+ node.kind === Kind.OBJECT_TYPE_EXTENSION ||
7448
+ node.kind === Kind.INTERFACE_TYPE_EXTENSION ||
7449
+ node.kind === Kind.UNION_TYPE_EXTENSION ||
7450
+ node.kind === Kind.ENUM_TYPE_EXTENSION ||
7451
+ node.kind === Kind.INPUT_OBJECT_TYPE_EXTENSION
7452
+ );
7453
+ }
7454
+
7455
+ /**
7456
+ * Executable definitions
7457
+ *
7458
+ * A GraphQL document is only valid for execution if all definitions are either
7459
+ * operation or fragment definitions.
7460
+ *
7461
+ * See https://spec.graphql.org/draft/#sec-Executable-Definitions
7462
+ */
7463
+ function ExecutableDefinitionsRule(context) {
7464
+ return {
7465
+ Document(node) {
7466
+ for (const definition of node.definitions) {
7467
+ if (!isExecutableDefinitionNode(definition)) {
7468
+ const defName =
7469
+ definition.kind === Kind.SCHEMA_DEFINITION ||
7470
+ definition.kind === Kind.SCHEMA_EXTENSION
7471
+ ? 'schema'
7472
+ : '"' + definition.name.value + '"';
7473
+ context.reportError(
7474
+ new GraphQLError(
7475
+ `The ${defName} definition is not executable.`,
7476
+ definition,
7477
+ ),
7478
+ );
7479
+ }
7480
+ }
7481
+
7482
+ return false;
7483
+ },
7484
+ };
7485
+ }
7486
+
7487
+ /**
7488
+ * Unique operation names
7489
+ *
7490
+ * A GraphQL document is only valid if all defined operations have unique names.
7491
+ *
7492
+ * See https://spec.graphql.org/draft/#sec-Operation-Name-Uniqueness
7493
+ */
7494
+ function UniqueOperationNamesRule(context) {
7495
+ const knownOperationNames = Object.create(null);
7496
+ return {
7497
+ OperationDefinition(node) {
7498
+ const operationName = node.name;
7499
+
7500
+ if (operationName) {
7501
+ if (knownOperationNames[operationName.value]) {
7502
+ context.reportError(
7503
+ new GraphQLError(
7504
+ `There can be only one operation named "${operationName.value}".`,
7505
+ [knownOperationNames[operationName.value], operationName],
7506
+ ),
7507
+ );
7508
+ } else {
7509
+ knownOperationNames[operationName.value] = operationName;
7510
+ }
7511
+ }
7512
+
7513
+ return false;
7514
+ },
7515
+
7516
+ FragmentDefinition: () => false,
7517
+ };
7518
+ }
7519
+
7520
+ /**
7521
+ * Lone anonymous operation
7522
+ *
7523
+ * A GraphQL document is only valid if when it contains an anonymous operation
7524
+ * (the query short-hand) that it contains only that one operation definition.
7525
+ *
7526
+ * See https://spec.graphql.org/draft/#sec-Lone-Anonymous-Operation
7527
+ */
7528
+ function LoneAnonymousOperationRule(context) {
7529
+ let operationCount = 0;
7530
+ return {
7531
+ Document(node) {
7532
+ operationCount = node.definitions.filter(
7533
+ (definition) => definition.kind === Kind.OPERATION_DEFINITION,
7534
+ ).length;
7535
+ },
7536
+
7537
+ OperationDefinition(node) {
7538
+ if (!node.name && operationCount > 1) {
7539
+ context.reportError(
7540
+ new GraphQLError(
7541
+ 'This anonymous operation must be the only defined operation.',
7542
+ node,
7543
+ ),
7544
+ );
7545
+ }
7546
+ },
7547
+ };
7548
+ }
7549
+
7200
7550
  /**
7201
7551
  * Produces a JavaScript value given a GraphQL Value AST.
7202
7552
  *
@@ -7358,109 +7708,3397 @@ function isMissingVariable(valueNode, variables) {
7358
7708
  }
7359
7709
 
7360
7710
  /**
7361
- * Build a GraphQLSchema for use by client tools.
7711
+ * Prepares an object map of argument values given a list of argument
7712
+ * definitions and list of argument AST nodes.
7362
7713
  *
7363
- * Given the result of a client running the introspection query, creates and
7364
- * returns a GraphQLSchema instance which can be then used with all graphql-js
7365
- * tools, but cannot be used to execute a query, as introspection does not
7366
- * represent the "resolver", "parse" or "serialize" functions or any other
7367
- * server-internal mechanisms.
7714
+ * Note: The returned value is a plain Object with a prototype, since it is
7715
+ * exposed to user code. Care should be taken to not pull values from the
7716
+ * Object prototype.
7368
7717
  *
7369
- * This function expects a complete introspection result. Don't forget to check
7370
- * the "errors" field of a server response before calling this function.
7718
+ * @internal
7371
7719
  */
7372
7720
 
7373
- function buildClientSchema(introspection, options) {
7374
- (isObjectLike(introspection) && isObjectLike(introspection.__schema)) ||
7375
- devAssert(
7376
- false,
7377
- `Invalid or incomplete introspection result. Ensure that you are passing "data" property of introspection response and no "errors" was returned alongside: ${inspect(
7378
- introspection,
7379
- )}.`,
7380
- ); // Get the schema from the introspection result.
7721
+ function getArgumentValues(def, node, variableValues) {
7722
+ var _node$arguments;
7381
7723
 
7382
- const schemaIntrospection = introspection.__schema; // Iterate through all types, getting the type definition for each.
7724
+ const coercedValues = {}; // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
7383
7725
 
7384
- const typeMap = keyValMap(
7385
- schemaIntrospection.types,
7386
- (typeIntrospection) => typeIntrospection.name,
7387
- (typeIntrospection) => buildType(typeIntrospection),
7388
- ); // Include standard types only if they are used.
7726
+ const argumentNodes =
7727
+ (_node$arguments = node.arguments) !== null && _node$arguments !== void 0
7728
+ ? _node$arguments
7729
+ : [];
7730
+ const argNodeMap = keyMap(argumentNodes, (arg) => arg.name.value);
7731
+
7732
+ for (const argDef of def.args) {
7733
+ const name = argDef.name;
7734
+ const argType = argDef.type;
7735
+ const argumentNode = argNodeMap[name];
7736
+
7737
+ if (!argumentNode) {
7738
+ if (argDef.defaultValue !== undefined) {
7739
+ coercedValues[name] = argDef.defaultValue;
7740
+ } else if (isNonNullType(argType)) {
7741
+ throw new GraphQLError(
7742
+ `Argument "${name}" of required type "${inspect(argType)}" ` +
7743
+ 'was not provided.',
7744
+ node,
7745
+ );
7746
+ }
7389
7747
 
7390
- for (const stdType of [...specifiedScalarTypes, ...introspectionTypes]) {
7391
- if (typeMap[stdType.name]) {
7392
- typeMap[stdType.name] = stdType;
7748
+ continue;
7393
7749
  }
7394
- } // Get the root Query, Mutation, and Subscription types.
7395
-
7396
- const queryType = schemaIntrospection.queryType
7397
- ? getObjectType(schemaIntrospection.queryType)
7398
- : null;
7399
- const mutationType = schemaIntrospection.mutationType
7400
- ? getObjectType(schemaIntrospection.mutationType)
7401
- : null;
7402
- const subscriptionType = schemaIntrospection.subscriptionType
7403
- ? getObjectType(schemaIntrospection.subscriptionType)
7404
- : null; // Get the directives supported by Introspection, assuming empty-set if
7405
- // directives were not queried for.
7406
7750
 
7407
- const directives = schemaIntrospection.directives
7408
- ? schemaIntrospection.directives.map(buildDirective)
7409
- : []; // Then produce and return a Schema with these types.
7751
+ const valueNode = argumentNode.value;
7752
+ let isNull = valueNode.kind === Kind.NULL;
7410
7753
 
7411
- return new GraphQLSchema({
7412
- description: schemaIntrospection.description,
7413
- query: queryType,
7414
- mutation: mutationType,
7415
- subscription: subscriptionType,
7416
- types: Object.values(typeMap),
7417
- directives,
7418
- assumeValid:
7419
- options === null || options === void 0 ? void 0 : options.assumeValid,
7420
- }); // Given a type reference in introspection, return the GraphQLType instance.
7421
- // preferring cached instances before building new instances.
7754
+ if (valueNode.kind === Kind.VARIABLE) {
7755
+ const variableName = valueNode.name.value;
7422
7756
 
7423
- function getType(typeRef) {
7424
- if (typeRef.kind === TypeKind.LIST) {
7425
- const itemRef = typeRef.ofType;
7757
+ if (
7758
+ variableValues == null ||
7759
+ !hasOwnProperty(variableValues, variableName)
7760
+ ) {
7761
+ if (argDef.defaultValue !== undefined) {
7762
+ coercedValues[name] = argDef.defaultValue;
7763
+ } else if (isNonNullType(argType)) {
7764
+ throw new GraphQLError(
7765
+ `Argument "${name}" of required type "${inspect(argType)}" ` +
7766
+ `was provided the variable "$${variableName}" which was not provided a runtime value.`,
7767
+ valueNode,
7768
+ );
7769
+ }
7426
7770
 
7427
- if (!itemRef) {
7428
- throw new Error('Decorated type deeper than introspection query.');
7771
+ continue;
7429
7772
  }
7430
7773
 
7431
- return new GraphQLList(getType(itemRef));
7774
+ isNull = variableValues[variableName] == null;
7432
7775
  }
7433
7776
 
7434
- if (typeRef.kind === TypeKind.NON_NULL) {
7435
- const nullableRef = typeRef.ofType;
7777
+ if (isNull && isNonNullType(argType)) {
7778
+ throw new GraphQLError(
7779
+ `Argument "${name}" of non-null type "${inspect(argType)}" ` +
7780
+ 'must not be null.',
7781
+ valueNode,
7782
+ );
7783
+ }
7436
7784
 
7437
- if (!nullableRef) {
7438
- throw new Error('Decorated type deeper than introspection query.');
7439
- }
7785
+ const coercedValue = valueFromAST(valueNode, argType, variableValues);
7440
7786
 
7441
- const nullableType = getType(nullableRef);
7442
- return new GraphQLNonNull(assertNullableType(nullableType));
7787
+ if (coercedValue === undefined) {
7788
+ // Note: ValuesOfCorrectTypeRule validation should catch this before
7789
+ // execution. This is a runtime check to ensure execution does not
7790
+ // continue with an invalid argument value.
7791
+ throw new GraphQLError(
7792
+ `Argument "${name}" has invalid value ${print(valueNode)}.`,
7793
+ valueNode,
7794
+ );
7443
7795
  }
7444
7796
 
7445
- return getNamedType(typeRef);
7797
+ coercedValues[name] = coercedValue;
7446
7798
  }
7447
7799
 
7448
- function getNamedType(typeRef) {
7449
- const typeName = typeRef.name;
7450
-
7451
- if (!typeName) {
7452
- throw new Error(`Unknown type reference: ${inspect(typeRef)}.`);
7453
- }
7800
+ return coercedValues;
7801
+ }
7802
+ /**
7803
+ * Prepares an object map of argument values given a directive definition
7804
+ * and a AST node which may contain directives. Optionally also accepts a map
7805
+ * of variable values.
7806
+ *
7807
+ * If the directive does not exist on the node, returns undefined.
7808
+ *
7809
+ * Note: The returned value is a plain Object with a prototype, since it is
7810
+ * exposed to user code. Care should be taken to not pull values from the
7811
+ * Object prototype.
7812
+ */
7454
7813
 
7455
- const type = typeMap[typeName];
7814
+ function getDirectiveValues(directiveDef, node, variableValues) {
7815
+ var _node$directives;
7456
7816
 
7457
- if (!type) {
7458
- throw new Error(
7459
- `Invalid or incomplete schema, unknown type: ${typeName}. Ensure that a full introspection query is used in order to build a client schema.`,
7460
- );
7461
- }
7817
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
7818
+ const directiveNode =
7819
+ (_node$directives = node.directives) === null || _node$directives === void 0
7820
+ ? void 0
7821
+ : _node$directives.find(
7822
+ (directive) => directive.name.value === directiveDef.name,
7823
+ );
7462
7824
 
7463
- return type;
7825
+ if (directiveNode) {
7826
+ return getArgumentValues(directiveDef, directiveNode, variableValues);
7827
+ }
7828
+ }
7829
+
7830
+ function hasOwnProperty(obj, prop) {
7831
+ return Object.prototype.hasOwnProperty.call(obj, prop);
7832
+ }
7833
+
7834
+ /**
7835
+ * Given a selectionSet, collect all of the fields and returns it at the end.
7836
+ *
7837
+ * CollectFields requires the "runtime type" of an object. For a field which
7838
+ * returns an Interface or Union type, the "runtime type" will be the actual
7839
+ * Object type returned by that field.
7840
+ *
7841
+ * @internal
7842
+ */
7843
+
7844
+ function collectFields(
7845
+ schema,
7846
+ fragments,
7847
+ variableValues,
7848
+ runtimeType,
7849
+ selectionSet,
7850
+ ) {
7851
+ const fields = new Map();
7852
+ collectFieldsImpl(
7853
+ schema,
7854
+ fragments,
7855
+ variableValues,
7856
+ runtimeType,
7857
+ selectionSet,
7858
+ fields,
7859
+ new Set(),
7860
+ );
7861
+ return fields;
7862
+ }
7863
+
7864
+ function collectFieldsImpl(
7865
+ schema,
7866
+ fragments,
7867
+ variableValues,
7868
+ runtimeType,
7869
+ selectionSet,
7870
+ fields,
7871
+ visitedFragmentNames,
7872
+ ) {
7873
+ for (const selection of selectionSet.selections) {
7874
+ switch (selection.kind) {
7875
+ case Kind.FIELD: {
7876
+ if (!shouldIncludeNode(variableValues, selection)) {
7877
+ continue;
7878
+ }
7879
+
7880
+ const name = getFieldEntryKey(selection);
7881
+ const fieldList = fields.get(name);
7882
+
7883
+ if (fieldList !== undefined) {
7884
+ fieldList.push(selection);
7885
+ } else {
7886
+ fields.set(name, [selection]);
7887
+ }
7888
+
7889
+ break;
7890
+ }
7891
+
7892
+ case Kind.INLINE_FRAGMENT: {
7893
+ if (
7894
+ !shouldIncludeNode(variableValues, selection) ||
7895
+ !doesFragmentConditionMatch(schema, selection, runtimeType)
7896
+ ) {
7897
+ continue;
7898
+ }
7899
+
7900
+ collectFieldsImpl(
7901
+ schema,
7902
+ fragments,
7903
+ variableValues,
7904
+ runtimeType,
7905
+ selection.selectionSet,
7906
+ fields,
7907
+ visitedFragmentNames,
7908
+ );
7909
+ break;
7910
+ }
7911
+
7912
+ case Kind.FRAGMENT_SPREAD: {
7913
+ const fragName = selection.name.value;
7914
+
7915
+ if (
7916
+ visitedFragmentNames.has(fragName) ||
7917
+ !shouldIncludeNode(variableValues, selection)
7918
+ ) {
7919
+ continue;
7920
+ }
7921
+
7922
+ visitedFragmentNames.add(fragName);
7923
+ const fragment = fragments[fragName];
7924
+
7925
+ if (
7926
+ !fragment ||
7927
+ !doesFragmentConditionMatch(schema, fragment, runtimeType)
7928
+ ) {
7929
+ continue;
7930
+ }
7931
+
7932
+ collectFieldsImpl(
7933
+ schema,
7934
+ fragments,
7935
+ variableValues,
7936
+ runtimeType,
7937
+ fragment.selectionSet,
7938
+ fields,
7939
+ visitedFragmentNames,
7940
+ );
7941
+ break;
7942
+ }
7943
+ }
7944
+ }
7945
+ }
7946
+ /**
7947
+ * Determines if a field should be included based on the `@include` and `@skip`
7948
+ * directives, where `@skip` has higher precedence than `@include`.
7949
+ */
7950
+
7951
+ function shouldIncludeNode(variableValues, node) {
7952
+ const skip = getDirectiveValues(GraphQLSkipDirective, node, variableValues);
7953
+
7954
+ if ((skip === null || skip === void 0 ? void 0 : skip.if) === true) {
7955
+ return false;
7956
+ }
7957
+
7958
+ const include = getDirectiveValues(
7959
+ GraphQLIncludeDirective,
7960
+ node,
7961
+ variableValues,
7962
+ );
7963
+
7964
+ if (
7965
+ (include === null || include === void 0 ? void 0 : include.if) === false
7966
+ ) {
7967
+ return false;
7968
+ }
7969
+
7970
+ return true;
7971
+ }
7972
+ /**
7973
+ * Determines if a fragment is applicable to the given type.
7974
+ */
7975
+
7976
+ function doesFragmentConditionMatch(schema, fragment, type) {
7977
+ const typeConditionNode = fragment.typeCondition;
7978
+
7979
+ if (!typeConditionNode) {
7980
+ return true;
7981
+ }
7982
+
7983
+ const conditionalType = typeFromAST(schema, typeConditionNode);
7984
+
7985
+ if (conditionalType === type) {
7986
+ return true;
7987
+ }
7988
+
7989
+ if (isAbstractType(conditionalType)) {
7990
+ return schema.isSubType(conditionalType, type);
7991
+ }
7992
+
7993
+ return false;
7994
+ }
7995
+ /**
7996
+ * Implements the logic to compute the key of a given field's entry
7997
+ */
7998
+
7999
+ function getFieldEntryKey(node) {
8000
+ return node.alias ? node.alias.value : node.name.value;
8001
+ }
8002
+
8003
+ /**
8004
+ * Subscriptions must only include a non-introspection field.
8005
+ *
8006
+ * A GraphQL subscription is valid only if it contains a single root field and
8007
+ * that root field is not an introspection field.
8008
+ *
8009
+ * See https://spec.graphql.org/draft/#sec-Single-root-field
8010
+ */
8011
+ function SingleFieldSubscriptionsRule(context) {
8012
+ return {
8013
+ OperationDefinition(node) {
8014
+ if (node.operation === 'subscription') {
8015
+ const schema = context.getSchema();
8016
+ const subscriptionType = schema.getSubscriptionType();
8017
+
8018
+ if (subscriptionType) {
8019
+ const operationName = node.name ? node.name.value : null;
8020
+ const variableValues = Object.create(null);
8021
+ const document = context.getDocument();
8022
+ const fragments = Object.create(null);
8023
+
8024
+ for (const definition of document.definitions) {
8025
+ if (definition.kind === Kind.FRAGMENT_DEFINITION) {
8026
+ fragments[definition.name.value] = definition;
8027
+ }
8028
+ }
8029
+
8030
+ const fields = collectFields(
8031
+ schema,
8032
+ fragments,
8033
+ variableValues,
8034
+ subscriptionType,
8035
+ node.selectionSet,
8036
+ );
8037
+
8038
+ if (fields.size > 1) {
8039
+ const fieldSelectionLists = [...fields.values()];
8040
+ const extraFieldSelectionLists = fieldSelectionLists.slice(1);
8041
+ const extraFieldSelections = extraFieldSelectionLists.flat();
8042
+ context.reportError(
8043
+ new GraphQLError(
8044
+ operationName != null
8045
+ ? `Subscription "${operationName}" must select only one top level field.`
8046
+ : 'Anonymous Subscription must select only one top level field.',
8047
+ extraFieldSelections,
8048
+ ),
8049
+ );
8050
+ }
8051
+
8052
+ for (const fieldNodes of fields.values()) {
8053
+ const field = fieldNodes[0];
8054
+ const fieldName = field.name.value;
8055
+
8056
+ if (fieldName.startsWith('__')) {
8057
+ context.reportError(
8058
+ new GraphQLError(
8059
+ operationName != null
8060
+ ? `Subscription "${operationName}" must not select an introspection top level field.`
8061
+ : 'Anonymous Subscription must not select an introspection top level field.',
8062
+ fieldNodes,
8063
+ ),
8064
+ );
8065
+ }
8066
+ }
8067
+ }
8068
+ }
8069
+ },
8070
+ };
8071
+ }
8072
+
8073
+ /**
8074
+ * Known type names
8075
+ *
8076
+ * A GraphQL document is only valid if referenced types (specifically
8077
+ * variable definitions and fragment conditions) are defined by the type schema.
8078
+ *
8079
+ * See https://spec.graphql.org/draft/#sec-Fragment-Spread-Type-Existence
8080
+ */
8081
+ function KnownTypeNamesRule(context) {
8082
+ const schema = context.getSchema();
8083
+ const existingTypesMap = schema ? schema.getTypeMap() : Object.create(null);
8084
+ const definedTypes = Object.create(null);
8085
+
8086
+ for (const def of context.getDocument().definitions) {
8087
+ if (isTypeDefinitionNode(def)) {
8088
+ definedTypes[def.name.value] = true;
8089
+ }
8090
+ }
8091
+
8092
+ const typeNames = [
8093
+ ...Object.keys(existingTypesMap),
8094
+ ...Object.keys(definedTypes),
8095
+ ];
8096
+ return {
8097
+ NamedType(node, _1, parent, _2, ancestors) {
8098
+ const typeName = node.name.value;
8099
+
8100
+ if (!existingTypesMap[typeName] && !definedTypes[typeName]) {
8101
+ var _ancestors$;
8102
+
8103
+ const definitionNode =
8104
+ (_ancestors$ = ancestors[2]) !== null && _ancestors$ !== void 0
8105
+ ? _ancestors$
8106
+ : parent;
8107
+ const isSDL = definitionNode != null && isSDLNode(definitionNode);
8108
+
8109
+ if (isSDL && standardTypeNames.includes(typeName)) {
8110
+ return;
8111
+ }
8112
+
8113
+ const suggestedTypes = suggestionList(
8114
+ typeName,
8115
+ isSDL ? standardTypeNames.concat(typeNames) : typeNames,
8116
+ );
8117
+ context.reportError(
8118
+ new GraphQLError(
8119
+ `Unknown type "${typeName}".` + didYouMean(suggestedTypes),
8120
+ node,
8121
+ ),
8122
+ );
8123
+ }
8124
+ },
8125
+ };
8126
+ }
8127
+ const standardTypeNames = [...specifiedScalarTypes, ...introspectionTypes].map(
8128
+ (type) => type.name,
8129
+ );
8130
+
8131
+ function isSDLNode(value) {
8132
+ return (
8133
+ 'kind' in value &&
8134
+ (isTypeSystemDefinitionNode(value) || isTypeSystemExtensionNode(value))
8135
+ );
8136
+ }
8137
+
8138
+ /**
8139
+ * Fragments on composite type
8140
+ *
8141
+ * Fragments use a type condition to determine if they apply, since fragments
8142
+ * can only be spread into a composite type (object, interface, or union), the
8143
+ * type condition must also be a composite type.
8144
+ *
8145
+ * See https://spec.graphql.org/draft/#sec-Fragments-On-Composite-Types
8146
+ */
8147
+ function FragmentsOnCompositeTypesRule(context) {
8148
+ return {
8149
+ InlineFragment(node) {
8150
+ const typeCondition = node.typeCondition;
8151
+
8152
+ if (typeCondition) {
8153
+ const type = typeFromAST(context.getSchema(), typeCondition);
8154
+
8155
+ if (type && !isCompositeType(type)) {
8156
+ const typeStr = print(typeCondition);
8157
+ context.reportError(
8158
+ new GraphQLError(
8159
+ `Fragment cannot condition on non composite type "${typeStr}".`,
8160
+ typeCondition,
8161
+ ),
8162
+ );
8163
+ }
8164
+ }
8165
+ },
8166
+
8167
+ FragmentDefinition(node) {
8168
+ const type = typeFromAST(context.getSchema(), node.typeCondition);
8169
+
8170
+ if (type && !isCompositeType(type)) {
8171
+ const typeStr = print(node.typeCondition);
8172
+ context.reportError(
8173
+ new GraphQLError(
8174
+ `Fragment "${node.name.value}" cannot condition on non composite type "${typeStr}".`,
8175
+ node.typeCondition,
8176
+ ),
8177
+ );
8178
+ }
8179
+ },
8180
+ };
8181
+ }
8182
+
8183
+ /**
8184
+ * Variables are input types
8185
+ *
8186
+ * A GraphQL operation is only valid if all the variables it defines are of
8187
+ * input types (scalar, enum, or input object).
8188
+ *
8189
+ * See https://spec.graphql.org/draft/#sec-Variables-Are-Input-Types
8190
+ */
8191
+ function VariablesAreInputTypesRule(context) {
8192
+ return {
8193
+ VariableDefinition(node) {
8194
+ const type = typeFromAST(context.getSchema(), node.type);
8195
+
8196
+ if (type !== undefined && !isInputType(type)) {
8197
+ const variableName = node.variable.name.value;
8198
+ const typeName = print(node.type);
8199
+ context.reportError(
8200
+ new GraphQLError(
8201
+ `Variable "$${variableName}" cannot be non-input type "${typeName}".`,
8202
+ node.type,
8203
+ ),
8204
+ );
8205
+ }
8206
+ },
8207
+ };
8208
+ }
8209
+
8210
+ /**
8211
+ * Scalar leafs
8212
+ *
8213
+ * A GraphQL document is valid only if all leaf fields (fields without
8214
+ * sub selections) are of scalar or enum types.
8215
+ */
8216
+ function ScalarLeafsRule(context) {
8217
+ return {
8218
+ Field(node) {
8219
+ const type = context.getType();
8220
+ const selectionSet = node.selectionSet;
8221
+
8222
+ if (type) {
8223
+ if (isLeafType(getNamedType(type))) {
8224
+ if (selectionSet) {
8225
+ const fieldName = node.name.value;
8226
+ const typeStr = inspect(type);
8227
+ context.reportError(
8228
+ new GraphQLError(
8229
+ `Field "${fieldName}" must not have a selection since type "${typeStr}" has no subfields.`,
8230
+ selectionSet,
8231
+ ),
8232
+ );
8233
+ }
8234
+ } else if (!selectionSet) {
8235
+ const fieldName = node.name.value;
8236
+ const typeStr = inspect(type);
8237
+ context.reportError(
8238
+ new GraphQLError(
8239
+ `Field "${fieldName}" of type "${typeStr}" must have a selection of subfields. Did you mean "${fieldName} { ... }"?`,
8240
+ node,
8241
+ ),
8242
+ );
8243
+ }
8244
+ }
8245
+ },
8246
+ };
8247
+ }
8248
+
8249
+ /**
8250
+ * Fields on correct type
8251
+ *
8252
+ * A GraphQL document is only valid if all fields selected are defined by the
8253
+ * parent type, or are an allowed meta field such as __typename.
8254
+ *
8255
+ * See https://spec.graphql.org/draft/#sec-Field-Selections
8256
+ */
8257
+ function FieldsOnCorrectTypeRule(context) {
8258
+ return {
8259
+ Field(node) {
8260
+ const type = context.getParentType();
8261
+
8262
+ if (type) {
8263
+ const fieldDef = context.getFieldDef();
8264
+
8265
+ if (!fieldDef) {
8266
+ // This field doesn't exist, lets look for suggestions.
8267
+ const schema = context.getSchema();
8268
+ const fieldName = node.name.value; // First determine if there are any suggested types to condition on.
8269
+
8270
+ let suggestion = didYouMean(
8271
+ 'to use an inline fragment on',
8272
+ getSuggestedTypeNames(schema, type, fieldName),
8273
+ ); // If there are no suggested types, then perhaps this was a typo?
8274
+
8275
+ if (suggestion === '') {
8276
+ suggestion = didYouMean(getSuggestedFieldNames(type, fieldName));
8277
+ } // Report an error, including helpful suggestions.
8278
+
8279
+ context.reportError(
8280
+ new GraphQLError(
8281
+ `Cannot query field "${fieldName}" on type "${type.name}".` +
8282
+ suggestion,
8283
+ node,
8284
+ ),
8285
+ );
8286
+ }
8287
+ }
8288
+ },
8289
+ };
8290
+ }
8291
+ /**
8292
+ * Go through all of the implementations of type, as well as the interfaces that
8293
+ * they implement. If any of those types include the provided field, suggest them,
8294
+ * sorted by how often the type is referenced.
8295
+ */
8296
+
8297
+ function getSuggestedTypeNames(schema, type, fieldName) {
8298
+ if (!isAbstractType(type)) {
8299
+ // Must be an Object type, which does not have possible fields.
8300
+ return [];
8301
+ }
8302
+
8303
+ const suggestedTypes = new Set();
8304
+ const usageCount = Object.create(null);
8305
+
8306
+ for (const possibleType of schema.getPossibleTypes(type)) {
8307
+ if (!possibleType.getFields()[fieldName]) {
8308
+ continue;
8309
+ } // This object type defines this field.
8310
+
8311
+ suggestedTypes.add(possibleType);
8312
+ usageCount[possibleType.name] = 1;
8313
+
8314
+ for (const possibleInterface of possibleType.getInterfaces()) {
8315
+ var _usageCount$possibleI;
8316
+
8317
+ if (!possibleInterface.getFields()[fieldName]) {
8318
+ continue;
8319
+ } // This interface type defines this field.
8320
+
8321
+ suggestedTypes.add(possibleInterface);
8322
+ usageCount[possibleInterface.name] =
8323
+ ((_usageCount$possibleI = usageCount[possibleInterface.name]) !==
8324
+ null && _usageCount$possibleI !== void 0
8325
+ ? _usageCount$possibleI
8326
+ : 0) + 1;
8327
+ }
8328
+ }
8329
+
8330
+ return [...suggestedTypes]
8331
+ .sort((typeA, typeB) => {
8332
+ // Suggest both interface and object types based on how common they are.
8333
+ const usageCountDiff = usageCount[typeB.name] - usageCount[typeA.name];
8334
+
8335
+ if (usageCountDiff !== 0) {
8336
+ return usageCountDiff;
8337
+ } // Suggest super types first followed by subtypes
8338
+
8339
+ if (isInterfaceType(typeA) && schema.isSubType(typeA, typeB)) {
8340
+ return -1;
8341
+ }
8342
+
8343
+ if (isInterfaceType(typeB) && schema.isSubType(typeB, typeA)) {
8344
+ return 1;
8345
+ }
8346
+
8347
+ return naturalCompare(typeA.name, typeB.name);
8348
+ })
8349
+ .map((x) => x.name);
8350
+ }
8351
+ /**
8352
+ * For the field name provided, determine if there are any similar field names
8353
+ * that may be the result of a typo.
8354
+ */
8355
+
8356
+ function getSuggestedFieldNames(type, fieldName) {
8357
+ if (isObjectType(type) || isInterfaceType(type)) {
8358
+ const possibleFieldNames = Object.keys(type.getFields());
8359
+ return suggestionList(fieldName, possibleFieldNames);
8360
+ } // Otherwise, must be a Union type, which does not define fields.
8361
+
8362
+ return [];
8363
+ }
8364
+
8365
+ /**
8366
+ * Unique fragment names
8367
+ *
8368
+ * A GraphQL document is only valid if all defined fragments have unique names.
8369
+ *
8370
+ * See https://spec.graphql.org/draft/#sec-Fragment-Name-Uniqueness
8371
+ */
8372
+ function UniqueFragmentNamesRule(context) {
8373
+ const knownFragmentNames = Object.create(null);
8374
+ return {
8375
+ OperationDefinition: () => false,
8376
+
8377
+ FragmentDefinition(node) {
8378
+ const fragmentName = node.name.value;
8379
+
8380
+ if (knownFragmentNames[fragmentName]) {
8381
+ context.reportError(
8382
+ new GraphQLError(
8383
+ `There can be only one fragment named "${fragmentName}".`,
8384
+ [knownFragmentNames[fragmentName], node.name],
8385
+ ),
8386
+ );
8387
+ } else {
8388
+ knownFragmentNames[fragmentName] = node.name;
8389
+ }
8390
+
8391
+ return false;
8392
+ },
8393
+ };
8394
+ }
8395
+
8396
+ /**
8397
+ * Known fragment names
8398
+ *
8399
+ * A GraphQL document is only valid if all `...Fragment` fragment spreads refer
8400
+ * to fragments defined in the same document.
8401
+ *
8402
+ * See https://spec.graphql.org/draft/#sec-Fragment-spread-target-defined
8403
+ */
8404
+ function KnownFragmentNamesRule(context) {
8405
+ return {
8406
+ FragmentSpread(node) {
8407
+ const fragmentName = node.name.value;
8408
+ const fragment = context.getFragment(fragmentName);
8409
+
8410
+ if (!fragment) {
8411
+ context.reportError(
8412
+ new GraphQLError(`Unknown fragment "${fragmentName}".`, node.name),
8413
+ );
8414
+ }
8415
+ },
8416
+ };
8417
+ }
8418
+
8419
+ /**
8420
+ * No unused fragments
8421
+ *
8422
+ * A GraphQL document is only valid if all fragment definitions are spread
8423
+ * within operations, or spread within other fragments spread within operations.
8424
+ *
8425
+ * See https://spec.graphql.org/draft/#sec-Fragments-Must-Be-Used
8426
+ */
8427
+ function NoUnusedFragmentsRule(context) {
8428
+ const operationDefs = [];
8429
+ const fragmentDefs = [];
8430
+ return {
8431
+ OperationDefinition(node) {
8432
+ operationDefs.push(node);
8433
+ return false;
8434
+ },
8435
+
8436
+ FragmentDefinition(node) {
8437
+ fragmentDefs.push(node);
8438
+ return false;
8439
+ },
8440
+
8441
+ Document: {
8442
+ leave() {
8443
+ const fragmentNameUsed = Object.create(null);
8444
+
8445
+ for (const operation of operationDefs) {
8446
+ for (const fragment of context.getRecursivelyReferencedFragments(
8447
+ operation,
8448
+ )) {
8449
+ fragmentNameUsed[fragment.name.value] = true;
8450
+ }
8451
+ }
8452
+
8453
+ for (const fragmentDef of fragmentDefs) {
8454
+ const fragName = fragmentDef.name.value;
8455
+
8456
+ if (fragmentNameUsed[fragName] !== true) {
8457
+ context.reportError(
8458
+ new GraphQLError(
8459
+ `Fragment "${fragName}" is never used.`,
8460
+ fragmentDef,
8461
+ ),
8462
+ );
8463
+ }
8464
+ }
8465
+ },
8466
+ },
8467
+ };
8468
+ }
8469
+
8470
+ /**
8471
+ * Possible fragment spread
8472
+ *
8473
+ * A fragment spread is only valid if the type condition could ever possibly
8474
+ * be true: if there is a non-empty intersection of the possible parent types,
8475
+ * and possible types which pass the type condition.
8476
+ */
8477
+ function PossibleFragmentSpreadsRule(context) {
8478
+ return {
8479
+ InlineFragment(node) {
8480
+ const fragType = context.getType();
8481
+ const parentType = context.getParentType();
8482
+
8483
+ if (
8484
+ isCompositeType(fragType) &&
8485
+ isCompositeType(parentType) &&
8486
+ !doTypesOverlap(context.getSchema(), fragType, parentType)
8487
+ ) {
8488
+ const parentTypeStr = inspect(parentType);
8489
+ const fragTypeStr = inspect(fragType);
8490
+ context.reportError(
8491
+ new GraphQLError(
8492
+ `Fragment cannot be spread here as objects of type "${parentTypeStr}" can never be of type "${fragTypeStr}".`,
8493
+ node,
8494
+ ),
8495
+ );
8496
+ }
8497
+ },
8498
+
8499
+ FragmentSpread(node) {
8500
+ const fragName = node.name.value;
8501
+ const fragType = getFragmentType(context, fragName);
8502
+ const parentType = context.getParentType();
8503
+
8504
+ if (
8505
+ fragType &&
8506
+ parentType &&
8507
+ !doTypesOverlap(context.getSchema(), fragType, parentType)
8508
+ ) {
8509
+ const parentTypeStr = inspect(parentType);
8510
+ const fragTypeStr = inspect(fragType);
8511
+ context.reportError(
8512
+ new GraphQLError(
8513
+ `Fragment "${fragName}" cannot be spread here as objects of type "${parentTypeStr}" can never be of type "${fragTypeStr}".`,
8514
+ node,
8515
+ ),
8516
+ );
8517
+ }
8518
+ },
8519
+ };
8520
+ }
8521
+
8522
+ function getFragmentType(context, name) {
8523
+ const frag = context.getFragment(name);
8524
+
8525
+ if (frag) {
8526
+ const type = typeFromAST(context.getSchema(), frag.typeCondition);
8527
+
8528
+ if (isCompositeType(type)) {
8529
+ return type;
8530
+ }
8531
+ }
8532
+ }
8533
+
8534
+ /**
8535
+ * No fragment cycles
8536
+ *
8537
+ * The graph of fragment spreads must not form any cycles including spreading itself.
8538
+ * Otherwise an operation could infinitely spread or infinitely execute on cycles in the underlying data.
8539
+ *
8540
+ * See https://spec.graphql.org/draft/#sec-Fragment-spreads-must-not-form-cycles
8541
+ */
8542
+ function NoFragmentCyclesRule(context) {
8543
+ // Tracks already visited fragments to maintain O(N) and to ensure that cycles
8544
+ // are not redundantly reported.
8545
+ const visitedFrags = Object.create(null); // Array of AST nodes used to produce meaningful errors
8546
+
8547
+ const spreadPath = []; // Position in the spread path
8548
+
8549
+ const spreadPathIndexByName = Object.create(null);
8550
+ return {
8551
+ OperationDefinition: () => false,
8552
+
8553
+ FragmentDefinition(node) {
8554
+ detectCycleRecursive(node);
8555
+ return false;
8556
+ },
8557
+ }; // This does a straight-forward DFS to find cycles.
8558
+ // It does not terminate when a cycle was found but continues to explore
8559
+ // the graph to find all possible cycles.
8560
+
8561
+ function detectCycleRecursive(fragment) {
8562
+ if (visitedFrags[fragment.name.value]) {
8563
+ return;
8564
+ }
8565
+
8566
+ const fragmentName = fragment.name.value;
8567
+ visitedFrags[fragmentName] = true;
8568
+ const spreadNodes = context.getFragmentSpreads(fragment.selectionSet);
8569
+
8570
+ if (spreadNodes.length === 0) {
8571
+ return;
8572
+ }
8573
+
8574
+ spreadPathIndexByName[fragmentName] = spreadPath.length;
8575
+
8576
+ for (const spreadNode of spreadNodes) {
8577
+ const spreadName = spreadNode.name.value;
8578
+ const cycleIndex = spreadPathIndexByName[spreadName];
8579
+ spreadPath.push(spreadNode);
8580
+
8581
+ if (cycleIndex === undefined) {
8582
+ const spreadFragment = context.getFragment(spreadName);
8583
+
8584
+ if (spreadFragment) {
8585
+ detectCycleRecursive(spreadFragment);
8586
+ }
8587
+ } else {
8588
+ const cyclePath = spreadPath.slice(cycleIndex);
8589
+ const viaPath = cyclePath
8590
+ .slice(0, -1)
8591
+ .map((s) => '"' + s.name.value + '"')
8592
+ .join(', ');
8593
+ context.reportError(
8594
+ new GraphQLError(
8595
+ `Cannot spread fragment "${spreadName}" within itself` +
8596
+ (viaPath !== '' ? ` via ${viaPath}.` : '.'),
8597
+ cyclePath,
8598
+ ),
8599
+ );
8600
+ }
8601
+
8602
+ spreadPath.pop();
8603
+ }
8604
+
8605
+ spreadPathIndexByName[fragmentName] = undefined;
8606
+ }
8607
+ }
8608
+
8609
+ /**
8610
+ * Groups array items into a Map, given a function to produce grouping key.
8611
+ */
8612
+ function groupBy(list, keyFn) {
8613
+ const result = new Map();
8614
+
8615
+ for (const item of list) {
8616
+ const key = keyFn(item);
8617
+ const group = result.get(key);
8618
+
8619
+ if (group === undefined) {
8620
+ result.set(key, [item]);
8621
+ } else {
8622
+ group.push(item);
8623
+ }
8624
+ }
8625
+
8626
+ return result;
8627
+ }
8628
+
8629
+ /**
8630
+ * Unique variable names
8631
+ *
8632
+ * A GraphQL operation is only valid if all its variables are uniquely named.
8633
+ */
8634
+ function UniqueVariableNamesRule(context) {
8635
+ return {
8636
+ OperationDefinition(operationNode) {
8637
+ var _operationNode$variab;
8638
+
8639
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
8640
+ const variableDefinitions =
8641
+ (_operationNode$variab = operationNode.variableDefinitions) !== null &&
8642
+ _operationNode$variab !== void 0
8643
+ ? _operationNode$variab
8644
+ : [];
8645
+ const seenVariableDefinitions = groupBy(
8646
+ variableDefinitions,
8647
+ (node) => node.variable.name.value,
8648
+ );
8649
+
8650
+ for (const [variableName, variableNodes] of seenVariableDefinitions) {
8651
+ if (variableNodes.length > 1) {
8652
+ context.reportError(
8653
+ new GraphQLError(
8654
+ `There can be only one variable named "$${variableName}".`,
8655
+ variableNodes.map((node) => node.variable.name),
8656
+ ),
8657
+ );
8658
+ }
8659
+ }
8660
+ },
8661
+ };
8662
+ }
8663
+
8664
+ /**
8665
+ * No undefined variables
8666
+ *
8667
+ * A GraphQL operation is only valid if all variables encountered, both directly
8668
+ * and via fragment spreads, are defined by that operation.
8669
+ *
8670
+ * See https://spec.graphql.org/draft/#sec-All-Variable-Uses-Defined
8671
+ */
8672
+ function NoUndefinedVariablesRule(context) {
8673
+ let variableNameDefined = Object.create(null);
8674
+ return {
8675
+ OperationDefinition: {
8676
+ enter() {
8677
+ variableNameDefined = Object.create(null);
8678
+ },
8679
+
8680
+ leave(operation) {
8681
+ const usages = context.getRecursiveVariableUsages(operation);
8682
+
8683
+ for (const { node } of usages) {
8684
+ const varName = node.name.value;
8685
+
8686
+ if (variableNameDefined[varName] !== true) {
8687
+ context.reportError(
8688
+ new GraphQLError(
8689
+ operation.name
8690
+ ? `Variable "$${varName}" is not defined by operation "${operation.name.value}".`
8691
+ : `Variable "$${varName}" is not defined.`,
8692
+ [node, operation],
8693
+ ),
8694
+ );
8695
+ }
8696
+ }
8697
+ },
8698
+ },
8699
+
8700
+ VariableDefinition(node) {
8701
+ variableNameDefined[node.variable.name.value] = true;
8702
+ },
8703
+ };
8704
+ }
8705
+
8706
+ /**
8707
+ * No unused variables
8708
+ *
8709
+ * A GraphQL operation is only valid if all variables defined by an operation
8710
+ * are used, either directly or within a spread fragment.
8711
+ *
8712
+ * See https://spec.graphql.org/draft/#sec-All-Variables-Used
8713
+ */
8714
+ function NoUnusedVariablesRule(context) {
8715
+ let variableDefs = [];
8716
+ return {
8717
+ OperationDefinition: {
8718
+ enter() {
8719
+ variableDefs = [];
8720
+ },
8721
+
8722
+ leave(operation) {
8723
+ const variableNameUsed = Object.create(null);
8724
+ const usages = context.getRecursiveVariableUsages(operation);
8725
+
8726
+ for (const { node } of usages) {
8727
+ variableNameUsed[node.name.value] = true;
8728
+ }
8729
+
8730
+ for (const variableDef of variableDefs) {
8731
+ const variableName = variableDef.variable.name.value;
8732
+
8733
+ if (variableNameUsed[variableName] !== true) {
8734
+ context.reportError(
8735
+ new GraphQLError(
8736
+ operation.name
8737
+ ? `Variable "$${variableName}" is never used in operation "${operation.name.value}".`
8738
+ : `Variable "$${variableName}" is never used.`,
8739
+ variableDef,
8740
+ ),
8741
+ );
8742
+ }
8743
+ }
8744
+ },
8745
+ },
8746
+
8747
+ VariableDefinition(def) {
8748
+ variableDefs.push(def);
8749
+ },
8750
+ };
8751
+ }
8752
+
8753
+ /**
8754
+ * Known directives
8755
+ *
8756
+ * A GraphQL document is only valid if all `@directives` are known by the
8757
+ * schema and legally positioned.
8758
+ *
8759
+ * See https://spec.graphql.org/draft/#sec-Directives-Are-Defined
8760
+ */
8761
+ function KnownDirectivesRule(context) {
8762
+ const locationsMap = Object.create(null);
8763
+ const schema = context.getSchema();
8764
+ const definedDirectives = schema
8765
+ ? schema.getDirectives()
8766
+ : specifiedDirectives;
8767
+
8768
+ for (const directive of definedDirectives) {
8769
+ locationsMap[directive.name] = directive.locations;
8770
+ }
8771
+
8772
+ const astDefinitions = context.getDocument().definitions;
8773
+
8774
+ for (const def of astDefinitions) {
8775
+ if (def.kind === Kind.DIRECTIVE_DEFINITION) {
8776
+ locationsMap[def.name.value] = def.locations.map((name) => name.value);
8777
+ }
8778
+ }
8779
+
8780
+ return {
8781
+ Directive(node, _key, _parent, _path, ancestors) {
8782
+ const name = node.name.value;
8783
+ const locations = locationsMap[name];
8784
+
8785
+ if (!locations) {
8786
+ context.reportError(
8787
+ new GraphQLError(`Unknown directive "@${name}".`, node),
8788
+ );
8789
+ return;
8790
+ }
8791
+
8792
+ const candidateLocation = getDirectiveLocationForASTPath(ancestors);
8793
+
8794
+ if (candidateLocation && !locations.includes(candidateLocation)) {
8795
+ context.reportError(
8796
+ new GraphQLError(
8797
+ `Directive "@${name}" may not be used on ${candidateLocation}.`,
8798
+ node,
8799
+ ),
8800
+ );
8801
+ }
8802
+ },
8803
+ };
8804
+ }
8805
+
8806
+ function getDirectiveLocationForASTPath(ancestors) {
8807
+ const appliedTo = ancestors[ancestors.length - 1];
8808
+ 'kind' in appliedTo || invariant(false);
8809
+
8810
+ switch (appliedTo.kind) {
8811
+ case Kind.OPERATION_DEFINITION:
8812
+ return getDirectiveLocationForOperation(appliedTo.operation);
8813
+
8814
+ case Kind.FIELD:
8815
+ return DirectiveLocation.FIELD;
8816
+
8817
+ case Kind.FRAGMENT_SPREAD:
8818
+ return DirectiveLocation.FRAGMENT_SPREAD;
8819
+
8820
+ case Kind.INLINE_FRAGMENT:
8821
+ return DirectiveLocation.INLINE_FRAGMENT;
8822
+
8823
+ case Kind.FRAGMENT_DEFINITION:
8824
+ return DirectiveLocation.FRAGMENT_DEFINITION;
8825
+
8826
+ case Kind.VARIABLE_DEFINITION:
8827
+ return DirectiveLocation.VARIABLE_DEFINITION;
8828
+
8829
+ case Kind.SCHEMA_DEFINITION:
8830
+ case Kind.SCHEMA_EXTENSION:
8831
+ return DirectiveLocation.SCHEMA;
8832
+
8833
+ case Kind.SCALAR_TYPE_DEFINITION:
8834
+ case Kind.SCALAR_TYPE_EXTENSION:
8835
+ return DirectiveLocation.SCALAR;
8836
+
8837
+ case Kind.OBJECT_TYPE_DEFINITION:
8838
+ case Kind.OBJECT_TYPE_EXTENSION:
8839
+ return DirectiveLocation.OBJECT;
8840
+
8841
+ case Kind.FIELD_DEFINITION:
8842
+ return DirectiveLocation.FIELD_DEFINITION;
8843
+
8844
+ case Kind.INTERFACE_TYPE_DEFINITION:
8845
+ case Kind.INTERFACE_TYPE_EXTENSION:
8846
+ return DirectiveLocation.INTERFACE;
8847
+
8848
+ case Kind.UNION_TYPE_DEFINITION:
8849
+ case Kind.UNION_TYPE_EXTENSION:
8850
+ return DirectiveLocation.UNION;
8851
+
8852
+ case Kind.ENUM_TYPE_DEFINITION:
8853
+ case Kind.ENUM_TYPE_EXTENSION:
8854
+ return DirectiveLocation.ENUM;
8855
+
8856
+ case Kind.ENUM_VALUE_DEFINITION:
8857
+ return DirectiveLocation.ENUM_VALUE;
8858
+
8859
+ case Kind.INPUT_OBJECT_TYPE_DEFINITION:
8860
+ case Kind.INPUT_OBJECT_TYPE_EXTENSION:
8861
+ return DirectiveLocation.INPUT_OBJECT;
8862
+
8863
+ case Kind.INPUT_VALUE_DEFINITION: {
8864
+ const parentNode = ancestors[ancestors.length - 3];
8865
+ 'kind' in parentNode || invariant(false);
8866
+ return parentNode.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION
8867
+ ? DirectiveLocation.INPUT_FIELD_DEFINITION
8868
+ : DirectiveLocation.ARGUMENT_DEFINITION;
8869
+ }
8870
+ }
8871
+ }
8872
+
8873
+ function getDirectiveLocationForOperation(operation) {
8874
+ switch (operation) {
8875
+ case OperationTypeNode.QUERY:
8876
+ return DirectiveLocation.QUERY;
8877
+
8878
+ case OperationTypeNode.MUTATION:
8879
+ return DirectiveLocation.MUTATION;
8880
+
8881
+ case OperationTypeNode.SUBSCRIPTION:
8882
+ return DirectiveLocation.SUBSCRIPTION;
8883
+ } // istanbul ignore next (Not reachable. All possible types have been considered)
8884
+
8885
+ invariant(false, 'Unexpected operation: ' + inspect(operation));
8886
+ }
8887
+
8888
+ /**
8889
+ * Unique directive names per location
8890
+ *
8891
+ * A GraphQL document is only valid if all non-repeatable directives at
8892
+ * a given location are uniquely named.
8893
+ *
8894
+ * See https://spec.graphql.org/draft/#sec-Directives-Are-Unique-Per-Location
8895
+ */
8896
+ function UniqueDirectivesPerLocationRule(context) {
8897
+ const uniqueDirectiveMap = Object.create(null);
8898
+ const schema = context.getSchema();
8899
+ const definedDirectives = schema
8900
+ ? schema.getDirectives()
8901
+ : specifiedDirectives;
8902
+
8903
+ for (const directive of definedDirectives) {
8904
+ uniqueDirectiveMap[directive.name] = !directive.isRepeatable;
8905
+ }
8906
+
8907
+ const astDefinitions = context.getDocument().definitions;
8908
+
8909
+ for (const def of astDefinitions) {
8910
+ if (def.kind === Kind.DIRECTIVE_DEFINITION) {
8911
+ uniqueDirectiveMap[def.name.value] = !def.repeatable;
8912
+ }
8913
+ }
8914
+
8915
+ const schemaDirectives = Object.create(null);
8916
+ const typeDirectivesMap = Object.create(null);
8917
+ return {
8918
+ // Many different AST nodes may contain directives. Rather than listing
8919
+ // them all, just listen for entering any node, and check to see if it
8920
+ // defines any directives.
8921
+ enter(node) {
8922
+ if (!('directives' in node) || !node.directives) {
8923
+ return;
8924
+ }
8925
+
8926
+ let seenDirectives;
8927
+
8928
+ if (
8929
+ node.kind === Kind.SCHEMA_DEFINITION ||
8930
+ node.kind === Kind.SCHEMA_EXTENSION
8931
+ ) {
8932
+ seenDirectives = schemaDirectives;
8933
+ } else if (isTypeDefinitionNode(node) || isTypeExtensionNode(node)) {
8934
+ const typeName = node.name.value;
8935
+ seenDirectives = typeDirectivesMap[typeName];
8936
+
8937
+ if (seenDirectives === undefined) {
8938
+ typeDirectivesMap[typeName] = seenDirectives = Object.create(null);
8939
+ }
8940
+ } else {
8941
+ seenDirectives = Object.create(null);
8942
+ }
8943
+
8944
+ for (const directive of node.directives) {
8945
+ const directiveName = directive.name.value;
8946
+
8947
+ if (uniqueDirectiveMap[directiveName]) {
8948
+ if (seenDirectives[directiveName]) {
8949
+ context.reportError(
8950
+ new GraphQLError(
8951
+ `The directive "@${directiveName}" can only be used once at this location.`,
8952
+ [seenDirectives[directiveName], directive],
8953
+ ),
8954
+ );
8955
+ } else {
8956
+ seenDirectives[directiveName] = directive;
8957
+ }
8958
+ }
8959
+ }
8960
+ },
8961
+ };
8962
+ }
8963
+
8964
+ /**
8965
+ * Known argument names
8966
+ *
8967
+ * A GraphQL field is only valid if all supplied arguments are defined by
8968
+ * that field.
8969
+ *
8970
+ * See https://spec.graphql.org/draft/#sec-Argument-Names
8971
+ * See https://spec.graphql.org/draft/#sec-Directives-Are-In-Valid-Locations
8972
+ */
8973
+ function KnownArgumentNamesRule(context) {
8974
+ return {
8975
+ // eslint-disable-next-line new-cap
8976
+ ...KnownArgumentNamesOnDirectivesRule(context),
8977
+
8978
+ Argument(argNode) {
8979
+ const argDef = context.getArgument();
8980
+ const fieldDef = context.getFieldDef();
8981
+ const parentType = context.getParentType();
8982
+
8983
+ if (!argDef && fieldDef && parentType) {
8984
+ const argName = argNode.name.value;
8985
+ const knownArgsNames = fieldDef.args.map((arg) => arg.name);
8986
+ const suggestions = suggestionList(argName, knownArgsNames);
8987
+ context.reportError(
8988
+ new GraphQLError(
8989
+ `Unknown argument "${argName}" on field "${parentType.name}.${fieldDef.name}".` +
8990
+ didYouMean(suggestions),
8991
+ argNode,
8992
+ ),
8993
+ );
8994
+ }
8995
+ },
8996
+ };
8997
+ }
8998
+ /**
8999
+ * @internal
9000
+ */
9001
+
9002
+ function KnownArgumentNamesOnDirectivesRule(context) {
9003
+ const directiveArgs = Object.create(null);
9004
+ const schema = context.getSchema();
9005
+ const definedDirectives = schema
9006
+ ? schema.getDirectives()
9007
+ : specifiedDirectives;
9008
+
9009
+ for (const directive of definedDirectives) {
9010
+ directiveArgs[directive.name] = directive.args.map((arg) => arg.name);
9011
+ }
9012
+
9013
+ const astDefinitions = context.getDocument().definitions;
9014
+
9015
+ for (const def of astDefinitions) {
9016
+ if (def.kind === Kind.DIRECTIVE_DEFINITION) {
9017
+ var _def$arguments;
9018
+
9019
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
9020
+ const argsNodes =
9021
+ (_def$arguments = def.arguments) !== null && _def$arguments !== void 0
9022
+ ? _def$arguments
9023
+ : [];
9024
+ directiveArgs[def.name.value] = argsNodes.map((arg) => arg.name.value);
9025
+ }
9026
+ }
9027
+
9028
+ return {
9029
+ Directive(directiveNode) {
9030
+ const directiveName = directiveNode.name.value;
9031
+ const knownArgs = directiveArgs[directiveName];
9032
+
9033
+ if (directiveNode.arguments && knownArgs) {
9034
+ for (const argNode of directiveNode.arguments) {
9035
+ const argName = argNode.name.value;
9036
+
9037
+ if (!knownArgs.includes(argName)) {
9038
+ const suggestions = suggestionList(argName, knownArgs);
9039
+ context.reportError(
9040
+ new GraphQLError(
9041
+ `Unknown argument "${argName}" on directive "@${directiveName}".` +
9042
+ didYouMean(suggestions),
9043
+ argNode,
9044
+ ),
9045
+ );
9046
+ }
9047
+ }
9048
+ }
9049
+
9050
+ return false;
9051
+ },
9052
+ };
9053
+ }
9054
+
9055
+ /**
9056
+ * Unique argument names
9057
+ *
9058
+ * A GraphQL field or directive is only valid if all supplied arguments are
9059
+ * uniquely named.
9060
+ *
9061
+ * See https://spec.graphql.org/draft/#sec-Argument-Names
9062
+ */
9063
+ function UniqueArgumentNamesRule(context) {
9064
+ return {
9065
+ Field: checkArgUniqueness,
9066
+ Directive: checkArgUniqueness,
9067
+ };
9068
+
9069
+ function checkArgUniqueness(parentNode) {
9070
+ var _parentNode$arguments;
9071
+
9072
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
9073
+ const argumentNodes =
9074
+ (_parentNode$arguments = parentNode.arguments) !== null &&
9075
+ _parentNode$arguments !== void 0
9076
+ ? _parentNode$arguments
9077
+ : [];
9078
+ const seenArgs = groupBy(argumentNodes, (arg) => arg.name.value);
9079
+
9080
+ for (const [argName, argNodes] of seenArgs) {
9081
+ if (argNodes.length > 1) {
9082
+ context.reportError(
9083
+ new GraphQLError(
9084
+ `There can be only one argument named "${argName}".`,
9085
+ argNodes.map((node) => node.name),
9086
+ ),
9087
+ );
9088
+ }
9089
+ }
9090
+ }
9091
+ }
9092
+
9093
+ /**
9094
+ * Value literals of correct type
9095
+ *
9096
+ * A GraphQL document is only valid if all value literals are of the type
9097
+ * expected at their position.
9098
+ *
9099
+ * See https://spec.graphql.org/draft/#sec-Values-of-Correct-Type
9100
+ */
9101
+ function ValuesOfCorrectTypeRule(context) {
9102
+ return {
9103
+ ListValue(node) {
9104
+ // Note: TypeInfo will traverse into a list's item type, so look to the
9105
+ // parent input type to check if it is a list.
9106
+ const type = getNullableType(context.getParentInputType());
9107
+
9108
+ if (!isListType(type)) {
9109
+ isValidValueNode(context, node);
9110
+ return false; // Don't traverse further.
9111
+ }
9112
+ },
9113
+
9114
+ ObjectValue(node) {
9115
+ const type = getNamedType(context.getInputType());
9116
+
9117
+ if (!isInputObjectType(type)) {
9118
+ isValidValueNode(context, node);
9119
+ return false; // Don't traverse further.
9120
+ } // Ensure every required field exists.
9121
+
9122
+ const fieldNodeMap = keyMap(node.fields, (field) => field.name.value);
9123
+
9124
+ for (const fieldDef of Object.values(type.getFields())) {
9125
+ const fieldNode = fieldNodeMap[fieldDef.name];
9126
+
9127
+ if (!fieldNode && isRequiredInputField(fieldDef)) {
9128
+ const typeStr = inspect(fieldDef.type);
9129
+ context.reportError(
9130
+ new GraphQLError(
9131
+ `Field "${type.name}.${fieldDef.name}" of required type "${typeStr}" was not provided.`,
9132
+ node,
9133
+ ),
9134
+ );
9135
+ }
9136
+ }
9137
+ },
9138
+
9139
+ ObjectField(node) {
9140
+ const parentType = getNamedType(context.getParentInputType());
9141
+ const fieldType = context.getInputType();
9142
+
9143
+ if (!fieldType && isInputObjectType(parentType)) {
9144
+ const suggestions = suggestionList(
9145
+ node.name.value,
9146
+ Object.keys(parentType.getFields()),
9147
+ );
9148
+ context.reportError(
9149
+ new GraphQLError(
9150
+ `Field "${node.name.value}" is not defined by type "${parentType.name}".` +
9151
+ didYouMean(suggestions),
9152
+ node,
9153
+ ),
9154
+ );
9155
+ }
9156
+ },
9157
+
9158
+ NullValue(node) {
9159
+ const type = context.getInputType();
9160
+
9161
+ if (isNonNullType(type)) {
9162
+ context.reportError(
9163
+ new GraphQLError(
9164
+ `Expected value of type "${inspect(type)}", found ${print(node)}.`,
9165
+ node,
9166
+ ),
9167
+ );
9168
+ }
9169
+ },
9170
+
9171
+ EnumValue: (node) => isValidValueNode(context, node),
9172
+ IntValue: (node) => isValidValueNode(context, node),
9173
+ FloatValue: (node) => isValidValueNode(context, node),
9174
+ StringValue: (node) => isValidValueNode(context, node),
9175
+ BooleanValue: (node) => isValidValueNode(context, node),
9176
+ };
9177
+ }
9178
+ /**
9179
+ * Any value literal may be a valid representation of a Scalar, depending on
9180
+ * that scalar type.
9181
+ */
9182
+
9183
+ function isValidValueNode(context, node) {
9184
+ // Report any error at the full type expected by the location.
9185
+ const locationType = context.getInputType();
9186
+
9187
+ if (!locationType) {
9188
+ return;
9189
+ }
9190
+
9191
+ const type = getNamedType(locationType);
9192
+
9193
+ if (!isLeafType(type)) {
9194
+ const typeStr = inspect(locationType);
9195
+ context.reportError(
9196
+ new GraphQLError(
9197
+ `Expected value of type "${typeStr}", found ${print(node)}.`,
9198
+ node,
9199
+ ),
9200
+ );
9201
+ return;
9202
+ } // Scalars and Enums determine if a literal value is valid via parseLiteral(),
9203
+ // which may throw or return an invalid value to indicate failure.
9204
+
9205
+ try {
9206
+ const parseResult = type.parseLiteral(
9207
+ node,
9208
+ undefined,
9209
+ /* variables */
9210
+ );
9211
+
9212
+ if (parseResult === undefined) {
9213
+ const typeStr = inspect(locationType);
9214
+ context.reportError(
9215
+ new GraphQLError(
9216
+ `Expected value of type "${typeStr}", found ${print(node)}.`,
9217
+ node,
9218
+ ),
9219
+ );
9220
+ }
9221
+ } catch (error) {
9222
+ const typeStr = inspect(locationType);
9223
+
9224
+ if (error instanceof GraphQLError) {
9225
+ context.reportError(error);
9226
+ } else {
9227
+ context.reportError(
9228
+ new GraphQLError(
9229
+ `Expected value of type "${typeStr}", found ${print(node)}; ` +
9230
+ error.message,
9231
+ node,
9232
+ undefined,
9233
+ undefined,
9234
+ undefined,
9235
+ error,
9236
+ ),
9237
+ );
9238
+ }
9239
+ }
9240
+ }
9241
+
9242
+ /**
9243
+ * Provided required arguments
9244
+ *
9245
+ * A field or directive is only valid if all required (non-null without a
9246
+ * default value) field arguments have been provided.
9247
+ */
9248
+ function ProvidedRequiredArgumentsRule(context) {
9249
+ return {
9250
+ // eslint-disable-next-line new-cap
9251
+ ...ProvidedRequiredArgumentsOnDirectivesRule(context),
9252
+ Field: {
9253
+ // Validate on leave to allow for deeper errors to appear first.
9254
+ leave(fieldNode) {
9255
+ var _fieldNode$arguments;
9256
+
9257
+ const fieldDef = context.getFieldDef();
9258
+
9259
+ if (!fieldDef) {
9260
+ return false;
9261
+ }
9262
+
9263
+ const providedArgs = new Set( // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
9264
+ (_fieldNode$arguments = fieldNode.arguments) === null ||
9265
+ _fieldNode$arguments === void 0
9266
+ ? void 0
9267
+ : _fieldNode$arguments.map((arg) => arg.name.value),
9268
+ );
9269
+
9270
+ for (const argDef of fieldDef.args) {
9271
+ if (!providedArgs.has(argDef.name) && isRequiredArgument(argDef)) {
9272
+ const argTypeStr = inspect(argDef.type);
9273
+ context.reportError(
9274
+ new GraphQLError(
9275
+ `Field "${fieldDef.name}" argument "${argDef.name}" of type "${argTypeStr}" is required, but it was not provided.`,
9276
+ fieldNode,
9277
+ ),
9278
+ );
9279
+ }
9280
+ }
9281
+ },
9282
+ },
9283
+ };
9284
+ }
9285
+ /**
9286
+ * @internal
9287
+ */
9288
+
9289
+ function ProvidedRequiredArgumentsOnDirectivesRule(context) {
9290
+ var _schema$getDirectives;
9291
+
9292
+ const requiredArgsMap = Object.create(null);
9293
+ const schema = context.getSchema();
9294
+ const definedDirectives =
9295
+ (_schema$getDirectives =
9296
+ schema === null || schema === void 0
9297
+ ? void 0
9298
+ : schema.getDirectives()) !== null && _schema$getDirectives !== void 0
9299
+ ? _schema$getDirectives
9300
+ : specifiedDirectives;
9301
+
9302
+ for (const directive of definedDirectives) {
9303
+ requiredArgsMap[directive.name] = keyMap(
9304
+ directive.args.filter(isRequiredArgument),
9305
+ (arg) => arg.name,
9306
+ );
9307
+ }
9308
+
9309
+ const astDefinitions = context.getDocument().definitions;
9310
+
9311
+ for (const def of astDefinitions) {
9312
+ if (def.kind === Kind.DIRECTIVE_DEFINITION) {
9313
+ var _def$arguments;
9314
+
9315
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
9316
+ const argNodes =
9317
+ (_def$arguments = def.arguments) !== null && _def$arguments !== void 0
9318
+ ? _def$arguments
9319
+ : [];
9320
+ requiredArgsMap[def.name.value] = keyMap(
9321
+ argNodes.filter(isRequiredArgumentNode),
9322
+ (arg) => arg.name.value,
9323
+ );
9324
+ }
9325
+ }
9326
+
9327
+ return {
9328
+ Directive: {
9329
+ // Validate on leave to allow for deeper errors to appear first.
9330
+ leave(directiveNode) {
9331
+ const directiveName = directiveNode.name.value;
9332
+ const requiredArgs = requiredArgsMap[directiveName];
9333
+
9334
+ if (requiredArgs) {
9335
+ var _directiveNode$argume;
9336
+
9337
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
9338
+ const argNodes =
9339
+ (_directiveNode$argume = directiveNode.arguments) !== null &&
9340
+ _directiveNode$argume !== void 0
9341
+ ? _directiveNode$argume
9342
+ : [];
9343
+ const argNodeMap = new Set(argNodes.map((arg) => arg.name.value));
9344
+
9345
+ for (const [argName, argDef] of Object.entries(requiredArgs)) {
9346
+ if (!argNodeMap.has(argName)) {
9347
+ const argType = isType(argDef.type)
9348
+ ? inspect(argDef.type)
9349
+ : print(argDef.type);
9350
+ context.reportError(
9351
+ new GraphQLError(
9352
+ `Directive "@${directiveName}" argument "${argName}" of type "${argType}" is required, but it was not provided.`,
9353
+ directiveNode,
9354
+ ),
9355
+ );
9356
+ }
9357
+ }
9358
+ }
9359
+ },
9360
+ },
9361
+ };
9362
+ }
9363
+
9364
+ function isRequiredArgumentNode(arg) {
9365
+ return arg.type.kind === Kind.NON_NULL_TYPE && arg.defaultValue == null;
9366
+ }
9367
+
9368
+ /**
9369
+ * Variables in allowed position
9370
+ *
9371
+ * Variable usages must be compatible with the arguments they are passed to.
9372
+ *
9373
+ * See https://spec.graphql.org/draft/#sec-All-Variable-Usages-are-Allowed
9374
+ */
9375
+ function VariablesInAllowedPositionRule(context) {
9376
+ let varDefMap = Object.create(null);
9377
+ return {
9378
+ OperationDefinition: {
9379
+ enter() {
9380
+ varDefMap = Object.create(null);
9381
+ },
9382
+
9383
+ leave(operation) {
9384
+ const usages = context.getRecursiveVariableUsages(operation);
9385
+
9386
+ for (const { node, type, defaultValue } of usages) {
9387
+ const varName = node.name.value;
9388
+ const varDef = varDefMap[varName];
9389
+
9390
+ if (varDef && type) {
9391
+ // A var type is allowed if it is the same or more strict (e.g. is
9392
+ // a subtype of) than the expected type. It can be more strict if
9393
+ // the variable type is non-null when the expected type is nullable.
9394
+ // If both are list types, the variable item type can be more strict
9395
+ // than the expected item type (contravariant).
9396
+ const schema = context.getSchema();
9397
+ const varType = typeFromAST(schema, varDef.type);
9398
+
9399
+ if (
9400
+ varType &&
9401
+ !allowedVariableUsage(
9402
+ schema,
9403
+ varType,
9404
+ varDef.defaultValue,
9405
+ type,
9406
+ defaultValue,
9407
+ )
9408
+ ) {
9409
+ const varTypeStr = inspect(varType);
9410
+ const typeStr = inspect(type);
9411
+ context.reportError(
9412
+ new GraphQLError(
9413
+ `Variable "$${varName}" of type "${varTypeStr}" used in position expecting type "${typeStr}".`,
9414
+ [varDef, node],
9415
+ ),
9416
+ );
9417
+ }
9418
+ }
9419
+ }
9420
+ },
9421
+ },
9422
+
9423
+ VariableDefinition(node) {
9424
+ varDefMap[node.variable.name.value] = node;
9425
+ },
9426
+ };
9427
+ }
9428
+ /**
9429
+ * Returns true if the variable is allowed in the location it was found,
9430
+ * which includes considering if default values exist for either the variable
9431
+ * or the location at which it is located.
9432
+ */
9433
+
9434
+ function allowedVariableUsage(
9435
+ schema,
9436
+ varType,
9437
+ varDefaultValue,
9438
+ locationType,
9439
+ locationDefaultValue,
9440
+ ) {
9441
+ if (isNonNullType(locationType) && !isNonNullType(varType)) {
9442
+ const hasNonNullVariableDefaultValue =
9443
+ varDefaultValue != null && varDefaultValue.kind !== Kind.NULL;
9444
+ const hasLocationDefaultValue = locationDefaultValue !== undefined;
9445
+
9446
+ if (!hasNonNullVariableDefaultValue && !hasLocationDefaultValue) {
9447
+ return false;
9448
+ }
9449
+
9450
+ const nullableLocationType = locationType.ofType;
9451
+ return isTypeSubTypeOf(schema, varType, nullableLocationType);
9452
+ }
9453
+
9454
+ return isTypeSubTypeOf(schema, varType, locationType);
9455
+ }
9456
+
9457
+ function reasonMessage(reason) {
9458
+ if (Array.isArray(reason)) {
9459
+ return reason
9460
+ .map(
9461
+ ([responseName, subReason]) =>
9462
+ `subfields "${responseName}" conflict because ` +
9463
+ reasonMessage(subReason),
9464
+ )
9465
+ .join(' and ');
9466
+ }
9467
+
9468
+ return reason;
9469
+ }
9470
+ /**
9471
+ * Overlapping fields can be merged
9472
+ *
9473
+ * A selection set is only valid if all fields (including spreading any
9474
+ * fragments) either correspond to distinct response names or can be merged
9475
+ * without ambiguity.
9476
+ *
9477
+ * See https://spec.graphql.org/draft/#sec-Field-Selection-Merging
9478
+ */
9479
+
9480
+ function OverlappingFieldsCanBeMergedRule(context) {
9481
+ // A memoization for when two fragments are compared "between" each other for
9482
+ // conflicts. Two fragments may be compared many times, so memoizing this can
9483
+ // dramatically improve the performance of this validator.
9484
+ const comparedFragmentPairs = new PairSet(); // A cache for the "field map" and list of fragment names found in any given
9485
+ // selection set. Selection sets may be asked for this information multiple
9486
+ // times, so this improves the performance of this validator.
9487
+
9488
+ const cachedFieldsAndFragmentNames = new Map();
9489
+ return {
9490
+ SelectionSet(selectionSet) {
9491
+ const conflicts = findConflictsWithinSelectionSet(
9492
+ context,
9493
+ cachedFieldsAndFragmentNames,
9494
+ comparedFragmentPairs,
9495
+ context.getParentType(),
9496
+ selectionSet,
9497
+ );
9498
+
9499
+ for (const [[responseName, reason], fields1, fields2] of conflicts) {
9500
+ const reasonMsg = reasonMessage(reason);
9501
+ context.reportError(
9502
+ new GraphQLError(
9503
+ `Fields "${responseName}" conflict because ${reasonMsg}. Use different aliases on the fields to fetch both if this was intentional.`,
9504
+ fields1.concat(fields2),
9505
+ ),
9506
+ );
9507
+ }
9508
+ },
9509
+ };
9510
+ }
9511
+
9512
+ /**
9513
+ * Algorithm:
9514
+ *
9515
+ * Conflicts occur when two fields exist in a query which will produce the same
9516
+ * response name, but represent differing values, thus creating a conflict.
9517
+ * The algorithm below finds all conflicts via making a series of comparisons
9518
+ * between fields. In order to compare as few fields as possible, this makes
9519
+ * a series of comparisons "within" sets of fields and "between" sets of fields.
9520
+ *
9521
+ * Given any selection set, a collection produces both a set of fields by
9522
+ * also including all inline fragments, as well as a list of fragments
9523
+ * referenced by fragment spreads.
9524
+ *
9525
+ * A) Each selection set represented in the document first compares "within" its
9526
+ * collected set of fields, finding any conflicts between every pair of
9527
+ * overlapping fields.
9528
+ * Note: This is the *only time* that a the fields "within" a set are compared
9529
+ * to each other. After this only fields "between" sets are compared.
9530
+ *
9531
+ * B) Also, if any fragment is referenced in a selection set, then a
9532
+ * comparison is made "between" the original set of fields and the
9533
+ * referenced fragment.
9534
+ *
9535
+ * C) Also, if multiple fragments are referenced, then comparisons
9536
+ * are made "between" each referenced fragment.
9537
+ *
9538
+ * D) When comparing "between" a set of fields and a referenced fragment, first
9539
+ * a comparison is made between each field in the original set of fields and
9540
+ * each field in the the referenced set of fields.
9541
+ *
9542
+ * E) Also, if any fragment is referenced in the referenced selection set,
9543
+ * then a comparison is made "between" the original set of fields and the
9544
+ * referenced fragment (recursively referring to step D).
9545
+ *
9546
+ * F) When comparing "between" two fragments, first a comparison is made between
9547
+ * each field in the first referenced set of fields and each field in the the
9548
+ * second referenced set of fields.
9549
+ *
9550
+ * G) Also, any fragments referenced by the first must be compared to the
9551
+ * second, and any fragments referenced by the second must be compared to the
9552
+ * first (recursively referring to step F).
9553
+ *
9554
+ * H) When comparing two fields, if both have selection sets, then a comparison
9555
+ * is made "between" both selection sets, first comparing the set of fields in
9556
+ * the first selection set with the set of fields in the second.
9557
+ *
9558
+ * I) Also, if any fragment is referenced in either selection set, then a
9559
+ * comparison is made "between" the other set of fields and the
9560
+ * referenced fragment.
9561
+ *
9562
+ * J) Also, if two fragments are referenced in both selection sets, then a
9563
+ * comparison is made "between" the two fragments.
9564
+ *
9565
+ */
9566
+ // Find all conflicts found "within" a selection set, including those found
9567
+ // via spreading in fragments. Called when visiting each SelectionSet in the
9568
+ // GraphQL Document.
9569
+ function findConflictsWithinSelectionSet(
9570
+ context,
9571
+ cachedFieldsAndFragmentNames,
9572
+ comparedFragmentPairs,
9573
+ parentType,
9574
+ selectionSet,
9575
+ ) {
9576
+ const conflicts = [];
9577
+ const [fieldMap, fragmentNames] = getFieldsAndFragmentNames(
9578
+ context,
9579
+ cachedFieldsAndFragmentNames,
9580
+ parentType,
9581
+ selectionSet,
9582
+ ); // (A) Find find all conflicts "within" the fields of this selection set.
9583
+ // Note: this is the *only place* `collectConflictsWithin` is called.
9584
+
9585
+ collectConflictsWithin(
9586
+ context,
9587
+ conflicts,
9588
+ cachedFieldsAndFragmentNames,
9589
+ comparedFragmentPairs,
9590
+ fieldMap,
9591
+ );
9592
+
9593
+ if (fragmentNames.length !== 0) {
9594
+ // (B) Then collect conflicts between these fields and those represented by
9595
+ // each spread fragment name found.
9596
+ for (let i = 0; i < fragmentNames.length; i++) {
9597
+ collectConflictsBetweenFieldsAndFragment(
9598
+ context,
9599
+ conflicts,
9600
+ cachedFieldsAndFragmentNames,
9601
+ comparedFragmentPairs,
9602
+ false,
9603
+ fieldMap,
9604
+ fragmentNames[i],
9605
+ ); // (C) Then compare this fragment with all other fragments found in this
9606
+ // selection set to collect conflicts between fragments spread together.
9607
+ // This compares each item in the list of fragment names to every other
9608
+ // item in that same list (except for itself).
9609
+
9610
+ for (let j = i + 1; j < fragmentNames.length; j++) {
9611
+ collectConflictsBetweenFragments(
9612
+ context,
9613
+ conflicts,
9614
+ cachedFieldsAndFragmentNames,
9615
+ comparedFragmentPairs,
9616
+ false,
9617
+ fragmentNames[i],
9618
+ fragmentNames[j],
9619
+ );
9620
+ }
9621
+ }
9622
+ }
9623
+
9624
+ return conflicts;
9625
+ } // Collect all conflicts found between a set of fields and a fragment reference
9626
+ // including via spreading in any nested fragments.
9627
+
9628
+ function collectConflictsBetweenFieldsAndFragment(
9629
+ context,
9630
+ conflicts,
9631
+ cachedFieldsAndFragmentNames,
9632
+ comparedFragmentPairs,
9633
+ areMutuallyExclusive,
9634
+ fieldMap,
9635
+ fragmentName,
9636
+ ) {
9637
+ const fragment = context.getFragment(fragmentName);
9638
+
9639
+ if (!fragment) {
9640
+ return;
9641
+ }
9642
+
9643
+ const [fieldMap2, referencedFragmentNames] =
9644
+ getReferencedFieldsAndFragmentNames(
9645
+ context,
9646
+ cachedFieldsAndFragmentNames,
9647
+ fragment,
9648
+ ); // Do not compare a fragment's fieldMap to itself.
9649
+
9650
+ if (fieldMap === fieldMap2) {
9651
+ return;
9652
+ } // (D) First collect any conflicts between the provided collection of fields
9653
+ // and the collection of fields represented by the given fragment.
9654
+
9655
+ collectConflictsBetween(
9656
+ context,
9657
+ conflicts,
9658
+ cachedFieldsAndFragmentNames,
9659
+ comparedFragmentPairs,
9660
+ areMutuallyExclusive,
9661
+ fieldMap,
9662
+ fieldMap2,
9663
+ ); // (E) Then collect any conflicts between the provided collection of fields
9664
+ // and any fragment names found in the given fragment.
9665
+
9666
+ for (const referencedFragmentName of referencedFragmentNames) {
9667
+ collectConflictsBetweenFieldsAndFragment(
9668
+ context,
9669
+ conflicts,
9670
+ cachedFieldsAndFragmentNames,
9671
+ comparedFragmentPairs,
9672
+ areMutuallyExclusive,
9673
+ fieldMap,
9674
+ referencedFragmentName,
9675
+ );
9676
+ }
9677
+ } // Collect all conflicts found between two fragments, including via spreading in
9678
+ // any nested fragments.
9679
+
9680
+ function collectConflictsBetweenFragments(
9681
+ context,
9682
+ conflicts,
9683
+ cachedFieldsAndFragmentNames,
9684
+ comparedFragmentPairs,
9685
+ areMutuallyExclusive,
9686
+ fragmentName1,
9687
+ fragmentName2,
9688
+ ) {
9689
+ // No need to compare a fragment to itself.
9690
+ if (fragmentName1 === fragmentName2) {
9691
+ return;
9692
+ } // Memoize so two fragments are not compared for conflicts more than once.
9693
+
9694
+ if (
9695
+ comparedFragmentPairs.has(
9696
+ fragmentName1,
9697
+ fragmentName2,
9698
+ areMutuallyExclusive,
9699
+ )
9700
+ ) {
9701
+ return;
9702
+ }
9703
+
9704
+ comparedFragmentPairs.add(fragmentName1, fragmentName2, areMutuallyExclusive);
9705
+ const fragment1 = context.getFragment(fragmentName1);
9706
+ const fragment2 = context.getFragment(fragmentName2);
9707
+
9708
+ if (!fragment1 || !fragment2) {
9709
+ return;
9710
+ }
9711
+
9712
+ const [fieldMap1, referencedFragmentNames1] =
9713
+ getReferencedFieldsAndFragmentNames(
9714
+ context,
9715
+ cachedFieldsAndFragmentNames,
9716
+ fragment1,
9717
+ );
9718
+ const [fieldMap2, referencedFragmentNames2] =
9719
+ getReferencedFieldsAndFragmentNames(
9720
+ context,
9721
+ cachedFieldsAndFragmentNames,
9722
+ fragment2,
9723
+ ); // (F) First, collect all conflicts between these two collections of fields
9724
+ // (not including any nested fragments).
9725
+
9726
+ collectConflictsBetween(
9727
+ context,
9728
+ conflicts,
9729
+ cachedFieldsAndFragmentNames,
9730
+ comparedFragmentPairs,
9731
+ areMutuallyExclusive,
9732
+ fieldMap1,
9733
+ fieldMap2,
9734
+ ); // (G) Then collect conflicts between the first fragment and any nested
9735
+ // fragments spread in the second fragment.
9736
+
9737
+ for (const referencedFragmentName2 of referencedFragmentNames2) {
9738
+ collectConflictsBetweenFragments(
9739
+ context,
9740
+ conflicts,
9741
+ cachedFieldsAndFragmentNames,
9742
+ comparedFragmentPairs,
9743
+ areMutuallyExclusive,
9744
+ fragmentName1,
9745
+ referencedFragmentName2,
9746
+ );
9747
+ } // (G) Then collect conflicts between the second fragment and any nested
9748
+ // fragments spread in the first fragment.
9749
+
9750
+ for (const referencedFragmentName1 of referencedFragmentNames1) {
9751
+ collectConflictsBetweenFragments(
9752
+ context,
9753
+ conflicts,
9754
+ cachedFieldsAndFragmentNames,
9755
+ comparedFragmentPairs,
9756
+ areMutuallyExclusive,
9757
+ referencedFragmentName1,
9758
+ fragmentName2,
9759
+ );
9760
+ }
9761
+ } // Find all conflicts found between two selection sets, including those found
9762
+ // via spreading in fragments. Called when determining if conflicts exist
9763
+ // between the sub-fields of two overlapping fields.
9764
+
9765
+ function findConflictsBetweenSubSelectionSets(
9766
+ context,
9767
+ cachedFieldsAndFragmentNames,
9768
+ comparedFragmentPairs,
9769
+ areMutuallyExclusive,
9770
+ parentType1,
9771
+ selectionSet1,
9772
+ parentType2,
9773
+ selectionSet2,
9774
+ ) {
9775
+ const conflicts = [];
9776
+ const [fieldMap1, fragmentNames1] = getFieldsAndFragmentNames(
9777
+ context,
9778
+ cachedFieldsAndFragmentNames,
9779
+ parentType1,
9780
+ selectionSet1,
9781
+ );
9782
+ const [fieldMap2, fragmentNames2] = getFieldsAndFragmentNames(
9783
+ context,
9784
+ cachedFieldsAndFragmentNames,
9785
+ parentType2,
9786
+ selectionSet2,
9787
+ ); // (H) First, collect all conflicts between these two collections of field.
9788
+
9789
+ collectConflictsBetween(
9790
+ context,
9791
+ conflicts,
9792
+ cachedFieldsAndFragmentNames,
9793
+ comparedFragmentPairs,
9794
+ areMutuallyExclusive,
9795
+ fieldMap1,
9796
+ fieldMap2,
9797
+ ); // (I) Then collect conflicts between the first collection of fields and
9798
+ // those referenced by each fragment name associated with the second.
9799
+
9800
+ for (const fragmentName2 of fragmentNames2) {
9801
+ collectConflictsBetweenFieldsAndFragment(
9802
+ context,
9803
+ conflicts,
9804
+ cachedFieldsAndFragmentNames,
9805
+ comparedFragmentPairs,
9806
+ areMutuallyExclusive,
9807
+ fieldMap1,
9808
+ fragmentName2,
9809
+ );
9810
+ } // (I) Then collect conflicts between the second collection of fields and
9811
+ // those referenced by each fragment name associated with the first.
9812
+
9813
+ for (const fragmentName1 of fragmentNames1) {
9814
+ collectConflictsBetweenFieldsAndFragment(
9815
+ context,
9816
+ conflicts,
9817
+ cachedFieldsAndFragmentNames,
9818
+ comparedFragmentPairs,
9819
+ areMutuallyExclusive,
9820
+ fieldMap2,
9821
+ fragmentName1,
9822
+ );
9823
+ } // (J) Also collect conflicts between any fragment names by the first and
9824
+ // fragment names by the second. This compares each item in the first set of
9825
+ // names to each item in the second set of names.
9826
+
9827
+ for (const fragmentName1 of fragmentNames1) {
9828
+ for (const fragmentName2 of fragmentNames2) {
9829
+ collectConflictsBetweenFragments(
9830
+ context,
9831
+ conflicts,
9832
+ cachedFieldsAndFragmentNames,
9833
+ comparedFragmentPairs,
9834
+ areMutuallyExclusive,
9835
+ fragmentName1,
9836
+ fragmentName2,
9837
+ );
9838
+ }
9839
+ }
9840
+
9841
+ return conflicts;
9842
+ } // Collect all Conflicts "within" one collection of fields.
9843
+
9844
+ function collectConflictsWithin(
9845
+ context,
9846
+ conflicts,
9847
+ cachedFieldsAndFragmentNames,
9848
+ comparedFragmentPairs,
9849
+ fieldMap,
9850
+ ) {
9851
+ // A field map is a keyed collection, where each key represents a response
9852
+ // name and the value at that key is a list of all fields which provide that
9853
+ // response name. For every response name, if there are multiple fields, they
9854
+ // must be compared to find a potential conflict.
9855
+ for (const [responseName, fields] of Object.entries(fieldMap)) {
9856
+ // This compares every field in the list to every other field in this list
9857
+ // (except to itself). If the list only has one item, nothing needs to
9858
+ // be compared.
9859
+ if (fields.length > 1) {
9860
+ for (let i = 0; i < fields.length; i++) {
9861
+ for (let j = i + 1; j < fields.length; j++) {
9862
+ const conflict = findConflict(
9863
+ context,
9864
+ cachedFieldsAndFragmentNames,
9865
+ comparedFragmentPairs,
9866
+ false, // within one collection is never mutually exclusive
9867
+ responseName,
9868
+ fields[i],
9869
+ fields[j],
9870
+ );
9871
+
9872
+ if (conflict) {
9873
+ conflicts.push(conflict);
9874
+ }
9875
+ }
9876
+ }
9877
+ }
9878
+ }
9879
+ } // Collect all Conflicts between two collections of fields. This is similar to,
9880
+ // but different from the `collectConflictsWithin` function above. This check
9881
+ // assumes that `collectConflictsWithin` has already been called on each
9882
+ // provided collection of fields. This is true because this validator traverses
9883
+ // each individual selection set.
9884
+
9885
+ function collectConflictsBetween(
9886
+ context,
9887
+ conflicts,
9888
+ cachedFieldsAndFragmentNames,
9889
+ comparedFragmentPairs,
9890
+ parentFieldsAreMutuallyExclusive,
9891
+ fieldMap1,
9892
+ fieldMap2,
9893
+ ) {
9894
+ // A field map is a keyed collection, where each key represents a response
9895
+ // name and the value at that key is a list of all fields which provide that
9896
+ // response name. For any response name which appears in both provided field
9897
+ // maps, each field from the first field map must be compared to every field
9898
+ // in the second field map to find potential conflicts.
9899
+ for (const [responseName, fields1] of Object.entries(fieldMap1)) {
9900
+ const fields2 = fieldMap2[responseName];
9901
+
9902
+ if (fields2) {
9903
+ for (const field1 of fields1) {
9904
+ for (const field2 of fields2) {
9905
+ const conflict = findConflict(
9906
+ context,
9907
+ cachedFieldsAndFragmentNames,
9908
+ comparedFragmentPairs,
9909
+ parentFieldsAreMutuallyExclusive,
9910
+ responseName,
9911
+ field1,
9912
+ field2,
9913
+ );
9914
+
9915
+ if (conflict) {
9916
+ conflicts.push(conflict);
9917
+ }
9918
+ }
9919
+ }
9920
+ }
9921
+ }
9922
+ } // Determines if there is a conflict between two particular fields, including
9923
+ // comparing their sub-fields.
9924
+
9925
+ function findConflict(
9926
+ context,
9927
+ cachedFieldsAndFragmentNames,
9928
+ comparedFragmentPairs,
9929
+ parentFieldsAreMutuallyExclusive,
9930
+ responseName,
9931
+ field1,
9932
+ field2,
9933
+ ) {
9934
+ const [parentType1, node1, def1] = field1;
9935
+ const [parentType2, node2, def2] = field2; // If it is known that two fields could not possibly apply at the same
9936
+ // time, due to the parent types, then it is safe to permit them to diverge
9937
+ // in aliased field or arguments used as they will not present any ambiguity
9938
+ // by differing.
9939
+ // It is known that two parent types could never overlap if they are
9940
+ // different Object types. Interface or Union types might overlap - if not
9941
+ // in the current state of the schema, then perhaps in some future version,
9942
+ // thus may not safely diverge.
9943
+
9944
+ const areMutuallyExclusive =
9945
+ parentFieldsAreMutuallyExclusive ||
9946
+ (parentType1 !== parentType2 &&
9947
+ isObjectType(parentType1) &&
9948
+ isObjectType(parentType2));
9949
+
9950
+ if (!areMutuallyExclusive) {
9951
+ var _node1$arguments, _node2$arguments;
9952
+
9953
+ // Two aliases must refer to the same field.
9954
+ const name1 = node1.name.value;
9955
+ const name2 = node2.name.value;
9956
+
9957
+ if (name1 !== name2) {
9958
+ return [
9959
+ [responseName, `"${name1}" and "${name2}" are different fields`],
9960
+ [node1],
9961
+ [node2],
9962
+ ];
9963
+ } // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
9964
+
9965
+ const args1 =
9966
+ (_node1$arguments = node1.arguments) !== null &&
9967
+ _node1$arguments !== void 0
9968
+ ? _node1$arguments
9969
+ : []; // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
9970
+
9971
+ const args2 =
9972
+ (_node2$arguments = node2.arguments) !== null &&
9973
+ _node2$arguments !== void 0
9974
+ ? _node2$arguments
9975
+ : []; // Two field calls must have the same arguments.
9976
+
9977
+ if (!sameArguments(args1, args2)) {
9978
+ return [
9979
+ [responseName, 'they have differing arguments'],
9980
+ [node1],
9981
+ [node2],
9982
+ ];
9983
+ }
9984
+ } // The return type for each field.
9985
+
9986
+ const type1 = def1 === null || def1 === void 0 ? void 0 : def1.type;
9987
+ const type2 = def2 === null || def2 === void 0 ? void 0 : def2.type;
9988
+
9989
+ if (type1 && type2 && doTypesConflict(type1, type2)) {
9990
+ return [
9991
+ [
9992
+ responseName,
9993
+ `they return conflicting types "${inspect(type1)}" and "${inspect(
9994
+ type2,
9995
+ )}"`,
9996
+ ],
9997
+ [node1],
9998
+ [node2],
9999
+ ];
10000
+ } // Collect and compare sub-fields. Use the same "visited fragment names" list
10001
+ // for both collections so fields in a fragment reference are never
10002
+ // compared to themselves.
10003
+
10004
+ const selectionSet1 = node1.selectionSet;
10005
+ const selectionSet2 = node2.selectionSet;
10006
+
10007
+ if (selectionSet1 && selectionSet2) {
10008
+ const conflicts = findConflictsBetweenSubSelectionSets(
10009
+ context,
10010
+ cachedFieldsAndFragmentNames,
10011
+ comparedFragmentPairs,
10012
+ areMutuallyExclusive,
10013
+ getNamedType(type1),
10014
+ selectionSet1,
10015
+ getNamedType(type2),
10016
+ selectionSet2,
10017
+ );
10018
+ return subfieldConflicts(conflicts, responseName, node1, node2);
10019
+ }
10020
+ }
10021
+
10022
+ function sameArguments(arguments1, arguments2) {
10023
+ if (arguments1.length !== arguments2.length) {
10024
+ return false;
10025
+ }
10026
+
10027
+ return arguments1.every((argument1) => {
10028
+ const argument2 = arguments2.find(
10029
+ (argument) => argument.name.value === argument1.name.value,
10030
+ );
10031
+
10032
+ if (!argument2) {
10033
+ return false;
10034
+ }
10035
+
10036
+ return sameValue(argument1.value, argument2.value);
10037
+ });
10038
+ }
10039
+
10040
+ function sameValue(value1, value2) {
10041
+ return print(value1) === print(value2);
10042
+ } // Two types conflict if both types could not apply to a value simultaneously.
10043
+ // Composite types are ignored as their individual field types will be compared
10044
+ // later recursively. However List and Non-Null types must match.
10045
+
10046
+ function doTypesConflict(type1, type2) {
10047
+ if (isListType(type1)) {
10048
+ return isListType(type2)
10049
+ ? doTypesConflict(type1.ofType, type2.ofType)
10050
+ : true;
10051
+ }
10052
+
10053
+ if (isListType(type2)) {
10054
+ return true;
10055
+ }
10056
+
10057
+ if (isNonNullType(type1)) {
10058
+ return isNonNullType(type2)
10059
+ ? doTypesConflict(type1.ofType, type2.ofType)
10060
+ : true;
10061
+ }
10062
+
10063
+ if (isNonNullType(type2)) {
10064
+ return true;
10065
+ }
10066
+
10067
+ if (isLeafType(type1) || isLeafType(type2)) {
10068
+ return type1 !== type2;
10069
+ }
10070
+
10071
+ return false;
10072
+ } // Given a selection set, return the collection of fields (a mapping of response
10073
+ // name to field nodes and definitions) as well as a list of fragment names
10074
+ // referenced via fragment spreads.
10075
+
10076
+ function getFieldsAndFragmentNames(
10077
+ context,
10078
+ cachedFieldsAndFragmentNames,
10079
+ parentType,
10080
+ selectionSet,
10081
+ ) {
10082
+ const cached = cachedFieldsAndFragmentNames.get(selectionSet);
10083
+
10084
+ if (cached) {
10085
+ return cached;
10086
+ }
10087
+
10088
+ const nodeAndDefs = Object.create(null);
10089
+ const fragmentNames = Object.create(null);
10090
+
10091
+ _collectFieldsAndFragmentNames(
10092
+ context,
10093
+ parentType,
10094
+ selectionSet,
10095
+ nodeAndDefs,
10096
+ fragmentNames,
10097
+ );
10098
+
10099
+ const result = [nodeAndDefs, Object.keys(fragmentNames)];
10100
+ cachedFieldsAndFragmentNames.set(selectionSet, result);
10101
+ return result;
10102
+ } // Given a reference to a fragment, return the represented collection of fields
10103
+ // as well as a list of nested fragment names referenced via fragment spreads.
10104
+
10105
+ function getReferencedFieldsAndFragmentNames(
10106
+ context,
10107
+ cachedFieldsAndFragmentNames,
10108
+ fragment,
10109
+ ) {
10110
+ // Short-circuit building a type from the node if possible.
10111
+ const cached = cachedFieldsAndFragmentNames.get(fragment.selectionSet);
10112
+
10113
+ if (cached) {
10114
+ return cached;
10115
+ }
10116
+
10117
+ const fragmentType = typeFromAST(context.getSchema(), fragment.typeCondition);
10118
+ return getFieldsAndFragmentNames(
10119
+ context,
10120
+ cachedFieldsAndFragmentNames,
10121
+ fragmentType,
10122
+ fragment.selectionSet,
10123
+ );
10124
+ }
10125
+
10126
+ function _collectFieldsAndFragmentNames(
10127
+ context,
10128
+ parentType,
10129
+ selectionSet,
10130
+ nodeAndDefs,
10131
+ fragmentNames,
10132
+ ) {
10133
+ for (const selection of selectionSet.selections) {
10134
+ switch (selection.kind) {
10135
+ case Kind.FIELD: {
10136
+ const fieldName = selection.name.value;
10137
+ let fieldDef;
10138
+
10139
+ if (isObjectType(parentType) || isInterfaceType(parentType)) {
10140
+ fieldDef = parentType.getFields()[fieldName];
10141
+ }
10142
+
10143
+ const responseName = selection.alias
10144
+ ? selection.alias.value
10145
+ : fieldName;
10146
+
10147
+ if (!nodeAndDefs[responseName]) {
10148
+ nodeAndDefs[responseName] = [];
10149
+ }
10150
+
10151
+ nodeAndDefs[responseName].push([parentType, selection, fieldDef]);
10152
+ break;
10153
+ }
10154
+
10155
+ case Kind.FRAGMENT_SPREAD:
10156
+ fragmentNames[selection.name.value] = true;
10157
+ break;
10158
+
10159
+ case Kind.INLINE_FRAGMENT: {
10160
+ const typeCondition = selection.typeCondition;
10161
+ const inlineFragmentType = typeCondition
10162
+ ? typeFromAST(context.getSchema(), typeCondition)
10163
+ : parentType;
10164
+
10165
+ _collectFieldsAndFragmentNames(
10166
+ context,
10167
+ inlineFragmentType,
10168
+ selection.selectionSet,
10169
+ nodeAndDefs,
10170
+ fragmentNames,
10171
+ );
10172
+
10173
+ break;
10174
+ }
10175
+ }
10176
+ }
10177
+ } // Given a series of Conflicts which occurred between two sub-fields, generate
10178
+ // a single Conflict.
10179
+
10180
+ function subfieldConflicts(conflicts, responseName, node1, node2) {
10181
+ if (conflicts.length > 0) {
10182
+ return [
10183
+ [responseName, conflicts.map(([reason]) => reason)],
10184
+ [node1, ...conflicts.map(([, fields1]) => fields1).flat()],
10185
+ [node2, ...conflicts.map(([, , fields2]) => fields2).flat()],
10186
+ ];
10187
+ }
10188
+ }
10189
+ /**
10190
+ * A way to keep track of pairs of things when the ordering of the pair does not matter.
10191
+ */
10192
+
10193
+ class PairSet {
10194
+ constructor() {
10195
+ this._data = new Map();
10196
+ }
10197
+
10198
+ has(a, b, areMutuallyExclusive) {
10199
+ var _this$_data$get;
10200
+
10201
+ const [key1, key2] = a < b ? [a, b] : [b, a];
10202
+ const result =
10203
+ (_this$_data$get = this._data.get(key1)) === null ||
10204
+ _this$_data$get === void 0
10205
+ ? void 0
10206
+ : _this$_data$get.get(key2);
10207
+
10208
+ if (result === undefined) {
10209
+ return false;
10210
+ } // areMutuallyExclusive being false is a superset of being true, hence if
10211
+ // we want to know if this PairSet "has" these two with no exclusivity,
10212
+ // we have to ensure it was added as such.
10213
+
10214
+ return areMutuallyExclusive ? true : areMutuallyExclusive === result;
10215
+ }
10216
+
10217
+ add(a, b, areMutuallyExclusive) {
10218
+ const [key1, key2] = a < b ? [a, b] : [b, a];
10219
+
10220
+ const map = this._data.get(key1);
10221
+
10222
+ if (map === undefined) {
10223
+ this._data.set(key1, new Map([[key2, areMutuallyExclusive]]));
10224
+ } else {
10225
+ map.set(key2, areMutuallyExclusive);
10226
+ }
10227
+ }
10228
+ }
10229
+
10230
+ /**
10231
+ * Unique input field names
10232
+ *
10233
+ * A GraphQL input object value is only valid if all supplied fields are
10234
+ * uniquely named.
10235
+ *
10236
+ * See https://spec.graphql.org/draft/#sec-Input-Object-Field-Uniqueness
10237
+ */
10238
+ function UniqueInputFieldNamesRule(context) {
10239
+ const knownNameStack = [];
10240
+ let knownNames = Object.create(null);
10241
+ return {
10242
+ ObjectValue: {
10243
+ enter() {
10244
+ knownNameStack.push(knownNames);
10245
+ knownNames = Object.create(null);
10246
+ },
10247
+
10248
+ leave() {
10249
+ const prevKnownNames = knownNameStack.pop();
10250
+ prevKnownNames || invariant(false);
10251
+ knownNames = prevKnownNames;
10252
+ },
10253
+ },
10254
+
10255
+ ObjectField(node) {
10256
+ const fieldName = node.name.value;
10257
+
10258
+ if (knownNames[fieldName]) {
10259
+ context.reportError(
10260
+ new GraphQLError(
10261
+ `There can be only one input field named "${fieldName}".`,
10262
+ [knownNames[fieldName], node.name],
10263
+ ),
10264
+ );
10265
+ } else {
10266
+ knownNames[fieldName] = node.name;
10267
+ }
10268
+ },
10269
+ };
10270
+ }
10271
+
10272
+ /**
10273
+ * Lone Schema definition
10274
+ *
10275
+ * A GraphQL document is only valid if it contains only one schema definition.
10276
+ */
10277
+ function LoneSchemaDefinitionRule(context) {
10278
+ var _ref, _ref2, _oldSchema$astNode;
10279
+
10280
+ const oldSchema = context.getSchema();
10281
+ const alreadyDefined =
10282
+ (_ref =
10283
+ (_ref2 =
10284
+ (_oldSchema$astNode =
10285
+ oldSchema === null || oldSchema === void 0
10286
+ ? void 0
10287
+ : oldSchema.astNode) !== null && _oldSchema$astNode !== void 0
10288
+ ? _oldSchema$astNode
10289
+ : oldSchema === null || oldSchema === void 0
10290
+ ? void 0
10291
+ : oldSchema.getQueryType()) !== null && _ref2 !== void 0
10292
+ ? _ref2
10293
+ : oldSchema === null || oldSchema === void 0
10294
+ ? void 0
10295
+ : oldSchema.getMutationType()) !== null && _ref !== void 0
10296
+ ? _ref
10297
+ : oldSchema === null || oldSchema === void 0
10298
+ ? void 0
10299
+ : oldSchema.getSubscriptionType();
10300
+ let schemaDefinitionsCount = 0;
10301
+ return {
10302
+ SchemaDefinition(node) {
10303
+ if (alreadyDefined) {
10304
+ context.reportError(
10305
+ new GraphQLError(
10306
+ 'Cannot define a new schema within a schema extension.',
10307
+ node,
10308
+ ),
10309
+ );
10310
+ return;
10311
+ }
10312
+
10313
+ if (schemaDefinitionsCount > 0) {
10314
+ context.reportError(
10315
+ new GraphQLError('Must provide only one schema definition.', node),
10316
+ );
10317
+ }
10318
+
10319
+ ++schemaDefinitionsCount;
10320
+ },
10321
+ };
10322
+ }
10323
+
10324
+ /**
10325
+ * Unique operation types
10326
+ *
10327
+ * A GraphQL document is only valid if it has only one type per operation.
10328
+ */
10329
+ function UniqueOperationTypesRule(context) {
10330
+ const schema = context.getSchema();
10331
+ const definedOperationTypes = Object.create(null);
10332
+ const existingOperationTypes = schema
10333
+ ? {
10334
+ query: schema.getQueryType(),
10335
+ mutation: schema.getMutationType(),
10336
+ subscription: schema.getSubscriptionType(),
10337
+ }
10338
+ : {};
10339
+ return {
10340
+ SchemaDefinition: checkOperationTypes,
10341
+ SchemaExtension: checkOperationTypes,
10342
+ };
10343
+
10344
+ function checkOperationTypes(node) {
10345
+ var _node$operationTypes;
10346
+
10347
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
10348
+ const operationTypesNodes =
10349
+ (_node$operationTypes = node.operationTypes) !== null &&
10350
+ _node$operationTypes !== void 0
10351
+ ? _node$operationTypes
10352
+ : [];
10353
+
10354
+ for (const operationType of operationTypesNodes) {
10355
+ const operation = operationType.operation;
10356
+ const alreadyDefinedOperationType = definedOperationTypes[operation];
10357
+
10358
+ if (existingOperationTypes[operation]) {
10359
+ context.reportError(
10360
+ new GraphQLError(
10361
+ `Type for ${operation} already defined in the schema. It cannot be redefined.`,
10362
+ operationType,
10363
+ ),
10364
+ );
10365
+ } else if (alreadyDefinedOperationType) {
10366
+ context.reportError(
10367
+ new GraphQLError(
10368
+ `There can be only one ${operation} type in schema.`,
10369
+ [alreadyDefinedOperationType, operationType],
10370
+ ),
10371
+ );
10372
+ } else {
10373
+ definedOperationTypes[operation] = operationType;
10374
+ }
10375
+ }
10376
+
10377
+ return false;
10378
+ }
10379
+ }
10380
+
10381
+ /**
10382
+ * Unique type names
10383
+ *
10384
+ * A GraphQL document is only valid if all defined types have unique names.
10385
+ */
10386
+ function UniqueTypeNamesRule(context) {
10387
+ const knownTypeNames = Object.create(null);
10388
+ const schema = context.getSchema();
10389
+ return {
10390
+ ScalarTypeDefinition: checkTypeName,
10391
+ ObjectTypeDefinition: checkTypeName,
10392
+ InterfaceTypeDefinition: checkTypeName,
10393
+ UnionTypeDefinition: checkTypeName,
10394
+ EnumTypeDefinition: checkTypeName,
10395
+ InputObjectTypeDefinition: checkTypeName,
10396
+ };
10397
+
10398
+ function checkTypeName(node) {
10399
+ const typeName = node.name.value;
10400
+
10401
+ if (schema !== null && schema !== void 0 && schema.getType(typeName)) {
10402
+ context.reportError(
10403
+ new GraphQLError(
10404
+ `Type "${typeName}" already exists in the schema. It cannot also be defined in this type definition.`,
10405
+ node.name,
10406
+ ),
10407
+ );
10408
+ return;
10409
+ }
10410
+
10411
+ if (knownTypeNames[typeName]) {
10412
+ context.reportError(
10413
+ new GraphQLError(`There can be only one type named "${typeName}".`, [
10414
+ knownTypeNames[typeName],
10415
+ node.name,
10416
+ ]),
10417
+ );
10418
+ } else {
10419
+ knownTypeNames[typeName] = node.name;
10420
+ }
10421
+
10422
+ return false;
10423
+ }
10424
+ }
10425
+
10426
+ /**
10427
+ * Unique enum value names
10428
+ *
10429
+ * A GraphQL enum type is only valid if all its values are uniquely named.
10430
+ */
10431
+ function UniqueEnumValueNamesRule(context) {
10432
+ const schema = context.getSchema();
10433
+ const existingTypeMap = schema ? schema.getTypeMap() : Object.create(null);
10434
+ const knownValueNames = Object.create(null);
10435
+ return {
10436
+ EnumTypeDefinition: checkValueUniqueness,
10437
+ EnumTypeExtension: checkValueUniqueness,
10438
+ };
10439
+
10440
+ function checkValueUniqueness(node) {
10441
+ var _node$values;
10442
+
10443
+ const typeName = node.name.value;
10444
+
10445
+ if (!knownValueNames[typeName]) {
10446
+ knownValueNames[typeName] = Object.create(null);
10447
+ } // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
10448
+
10449
+ const valueNodes =
10450
+ (_node$values = node.values) !== null && _node$values !== void 0
10451
+ ? _node$values
10452
+ : [];
10453
+ const valueNames = knownValueNames[typeName];
10454
+
10455
+ for (const valueDef of valueNodes) {
10456
+ const valueName = valueDef.name.value;
10457
+ const existingType = existingTypeMap[typeName];
10458
+
10459
+ if (isEnumType(existingType) && existingType.getValue(valueName)) {
10460
+ context.reportError(
10461
+ new GraphQLError(
10462
+ `Enum value "${typeName}.${valueName}" already exists in the schema. It cannot also be defined in this type extension.`,
10463
+ valueDef.name,
10464
+ ),
10465
+ );
10466
+ } else if (valueNames[valueName]) {
10467
+ context.reportError(
10468
+ new GraphQLError(
10469
+ `Enum value "${typeName}.${valueName}" can only be defined once.`,
10470
+ [valueNames[valueName], valueDef.name],
10471
+ ),
10472
+ );
10473
+ } else {
10474
+ valueNames[valueName] = valueDef.name;
10475
+ }
10476
+ }
10477
+
10478
+ return false;
10479
+ }
10480
+ }
10481
+
10482
+ /**
10483
+ * Unique field definition names
10484
+ *
10485
+ * A GraphQL complex type is only valid if all its fields are uniquely named.
10486
+ */
10487
+ function UniqueFieldDefinitionNamesRule(context) {
10488
+ const schema = context.getSchema();
10489
+ const existingTypeMap = schema ? schema.getTypeMap() : Object.create(null);
10490
+ const knownFieldNames = Object.create(null);
10491
+ return {
10492
+ InputObjectTypeDefinition: checkFieldUniqueness,
10493
+ InputObjectTypeExtension: checkFieldUniqueness,
10494
+ InterfaceTypeDefinition: checkFieldUniqueness,
10495
+ InterfaceTypeExtension: checkFieldUniqueness,
10496
+ ObjectTypeDefinition: checkFieldUniqueness,
10497
+ ObjectTypeExtension: checkFieldUniqueness,
10498
+ };
10499
+
10500
+ function checkFieldUniqueness(node) {
10501
+ var _node$fields;
10502
+
10503
+ const typeName = node.name.value;
10504
+
10505
+ if (!knownFieldNames[typeName]) {
10506
+ knownFieldNames[typeName] = Object.create(null);
10507
+ } // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
10508
+
10509
+ const fieldNodes =
10510
+ (_node$fields = node.fields) !== null && _node$fields !== void 0
10511
+ ? _node$fields
10512
+ : [];
10513
+ const fieldNames = knownFieldNames[typeName];
10514
+
10515
+ for (const fieldDef of fieldNodes) {
10516
+ const fieldName = fieldDef.name.value;
10517
+
10518
+ if (hasField(existingTypeMap[typeName], fieldName)) {
10519
+ context.reportError(
10520
+ new GraphQLError(
10521
+ `Field "${typeName}.${fieldName}" already exists in the schema. It cannot also be defined in this type extension.`,
10522
+ fieldDef.name,
10523
+ ),
10524
+ );
10525
+ } else if (fieldNames[fieldName]) {
10526
+ context.reportError(
10527
+ new GraphQLError(
10528
+ `Field "${typeName}.${fieldName}" can only be defined once.`,
10529
+ [fieldNames[fieldName], fieldDef.name],
10530
+ ),
10531
+ );
10532
+ } else {
10533
+ fieldNames[fieldName] = fieldDef.name;
10534
+ }
10535
+ }
10536
+
10537
+ return false;
10538
+ }
10539
+ }
10540
+
10541
+ function hasField(type, fieldName) {
10542
+ if (isObjectType(type) || isInterfaceType(type) || isInputObjectType(type)) {
10543
+ return type.getFields()[fieldName] != null;
10544
+ }
10545
+
10546
+ return false;
10547
+ }
10548
+
10549
+ /**
10550
+ * Unique argument definition names
10551
+ *
10552
+ * A GraphQL Object or Interface type is only valid if all its fields have uniquely named arguments.
10553
+ * A GraphQL Directive is only valid if all its arguments are uniquely named.
10554
+ */
10555
+ function UniqueArgumentDefinitionNamesRule(context) {
10556
+ return {
10557
+ DirectiveDefinition(directiveNode) {
10558
+ var _directiveNode$argume;
10559
+
10560
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
10561
+ const argumentNodes =
10562
+ (_directiveNode$argume = directiveNode.arguments) !== null &&
10563
+ _directiveNode$argume !== void 0
10564
+ ? _directiveNode$argume
10565
+ : [];
10566
+ return checkArgUniqueness(`@${directiveNode.name.value}`, argumentNodes);
10567
+ },
10568
+
10569
+ InterfaceTypeDefinition: checkArgUniquenessPerField,
10570
+ InterfaceTypeExtension: checkArgUniquenessPerField,
10571
+ ObjectTypeDefinition: checkArgUniquenessPerField,
10572
+ ObjectTypeExtension: checkArgUniquenessPerField,
10573
+ };
10574
+
10575
+ function checkArgUniquenessPerField(typeNode) {
10576
+ var _typeNode$fields;
10577
+
10578
+ const typeName = typeNode.name.value; // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
10579
+
10580
+ const fieldNodes =
10581
+ (_typeNode$fields = typeNode.fields) !== null &&
10582
+ _typeNode$fields !== void 0
10583
+ ? _typeNode$fields
10584
+ : [];
10585
+
10586
+ for (const fieldDef of fieldNodes) {
10587
+ var _fieldDef$arguments;
10588
+
10589
+ const fieldName = fieldDef.name.value; // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
10590
+
10591
+ const argumentNodes =
10592
+ (_fieldDef$arguments = fieldDef.arguments) !== null &&
10593
+ _fieldDef$arguments !== void 0
10594
+ ? _fieldDef$arguments
10595
+ : [];
10596
+ checkArgUniqueness(`${typeName}.${fieldName}`, argumentNodes);
10597
+ }
10598
+
10599
+ return false;
10600
+ }
10601
+
10602
+ function checkArgUniqueness(parentName, argumentNodes) {
10603
+ const seenArgs = groupBy(argumentNodes, (arg) => arg.name.value);
10604
+
10605
+ for (const [argName, argNodes] of seenArgs) {
10606
+ if (argNodes.length > 1) {
10607
+ context.reportError(
10608
+ new GraphQLError(
10609
+ `Argument "${parentName}(${argName}:)" can only be defined once.`,
10610
+ argNodes.map((node) => node.name),
10611
+ ),
10612
+ );
10613
+ }
10614
+ }
10615
+
10616
+ return false;
10617
+ }
10618
+ }
10619
+
10620
+ /**
10621
+ * Unique directive names
10622
+ *
10623
+ * A GraphQL document is only valid if all defined directives have unique names.
10624
+ */
10625
+ function UniqueDirectiveNamesRule(context) {
10626
+ const knownDirectiveNames = Object.create(null);
10627
+ const schema = context.getSchema();
10628
+ return {
10629
+ DirectiveDefinition(node) {
10630
+ const directiveName = node.name.value;
10631
+
10632
+ if (
10633
+ schema !== null &&
10634
+ schema !== void 0 &&
10635
+ schema.getDirective(directiveName)
10636
+ ) {
10637
+ context.reportError(
10638
+ new GraphQLError(
10639
+ `Directive "@${directiveName}" already exists in the schema. It cannot be redefined.`,
10640
+ node.name,
10641
+ ),
10642
+ );
10643
+ return;
10644
+ }
10645
+
10646
+ if (knownDirectiveNames[directiveName]) {
10647
+ context.reportError(
10648
+ new GraphQLError(
10649
+ `There can be only one directive named "@${directiveName}".`,
10650
+ [knownDirectiveNames[directiveName], node.name],
10651
+ ),
10652
+ );
10653
+ } else {
10654
+ knownDirectiveNames[directiveName] = node.name;
10655
+ }
10656
+
10657
+ return false;
10658
+ },
10659
+ };
10660
+ }
10661
+
10662
+ /**
10663
+ * Possible type extension
10664
+ *
10665
+ * A type extension is only valid if the type is defined and has the same kind.
10666
+ */
10667
+ function PossibleTypeExtensionsRule(context) {
10668
+ const schema = context.getSchema();
10669
+ const definedTypes = Object.create(null);
10670
+
10671
+ for (const def of context.getDocument().definitions) {
10672
+ if (isTypeDefinitionNode(def)) {
10673
+ definedTypes[def.name.value] = def;
10674
+ }
10675
+ }
10676
+
10677
+ return {
10678
+ ScalarTypeExtension: checkExtension,
10679
+ ObjectTypeExtension: checkExtension,
10680
+ InterfaceTypeExtension: checkExtension,
10681
+ UnionTypeExtension: checkExtension,
10682
+ EnumTypeExtension: checkExtension,
10683
+ InputObjectTypeExtension: checkExtension,
10684
+ };
10685
+
10686
+ function checkExtension(node) {
10687
+ const typeName = node.name.value;
10688
+ const defNode = definedTypes[typeName];
10689
+ const existingType =
10690
+ schema === null || schema === void 0 ? void 0 : schema.getType(typeName);
10691
+ let expectedKind;
10692
+
10693
+ if (defNode) {
10694
+ expectedKind = defKindToExtKind[defNode.kind];
10695
+ } else if (existingType) {
10696
+ expectedKind = typeToExtKind(existingType);
10697
+ }
10698
+
10699
+ if (expectedKind) {
10700
+ if (expectedKind !== node.kind) {
10701
+ const kindStr = extensionKindToTypeName(node.kind);
10702
+ context.reportError(
10703
+ new GraphQLError(
10704
+ `Cannot extend non-${kindStr} type "${typeName}".`,
10705
+ defNode ? [defNode, node] : node,
10706
+ ),
10707
+ );
10708
+ }
10709
+ } else {
10710
+ const allTypeNames = Object.keys({
10711
+ ...definedTypes,
10712
+ ...(schema === null || schema === void 0
10713
+ ? void 0
10714
+ : schema.getTypeMap()),
10715
+ });
10716
+ const suggestedTypes = suggestionList(typeName, allTypeNames);
10717
+ context.reportError(
10718
+ new GraphQLError(
10719
+ `Cannot extend type "${typeName}" because it is not defined.` +
10720
+ didYouMean(suggestedTypes),
10721
+ node.name,
10722
+ ),
10723
+ );
10724
+ }
10725
+ }
10726
+ }
10727
+ const defKindToExtKind = {
10728
+ [Kind.SCALAR_TYPE_DEFINITION]: Kind.SCALAR_TYPE_EXTENSION,
10729
+ [Kind.OBJECT_TYPE_DEFINITION]: Kind.OBJECT_TYPE_EXTENSION,
10730
+ [Kind.INTERFACE_TYPE_DEFINITION]: Kind.INTERFACE_TYPE_EXTENSION,
10731
+ [Kind.UNION_TYPE_DEFINITION]: Kind.UNION_TYPE_EXTENSION,
10732
+ [Kind.ENUM_TYPE_DEFINITION]: Kind.ENUM_TYPE_EXTENSION,
10733
+ [Kind.INPUT_OBJECT_TYPE_DEFINITION]: Kind.INPUT_OBJECT_TYPE_EXTENSION,
10734
+ };
10735
+
10736
+ function typeToExtKind(type) {
10737
+ if (isScalarType(type)) {
10738
+ return Kind.SCALAR_TYPE_EXTENSION;
10739
+ }
10740
+
10741
+ if (isObjectType(type)) {
10742
+ return Kind.OBJECT_TYPE_EXTENSION;
10743
+ }
10744
+
10745
+ if (isInterfaceType(type)) {
10746
+ return Kind.INTERFACE_TYPE_EXTENSION;
10747
+ }
10748
+
10749
+ if (isUnionType(type)) {
10750
+ return Kind.UNION_TYPE_EXTENSION;
10751
+ }
10752
+
10753
+ if (isEnumType(type)) {
10754
+ return Kind.ENUM_TYPE_EXTENSION;
10755
+ } // istanbul ignore else (See: 'https://github.com/graphql/graphql-js/issues/2618')
10756
+
10757
+ if (isInputObjectType(type)) {
10758
+ return Kind.INPUT_OBJECT_TYPE_EXTENSION;
10759
+ } // istanbul ignore next (Not reachable. All possible types have been considered)
10760
+
10761
+ invariant(false, 'Unexpected type: ' + inspect(type));
10762
+ }
10763
+
10764
+ function extensionKindToTypeName(kind) {
10765
+ switch (kind) {
10766
+ case Kind.SCALAR_TYPE_EXTENSION:
10767
+ return 'scalar';
10768
+
10769
+ case Kind.OBJECT_TYPE_EXTENSION:
10770
+ return 'object';
10771
+
10772
+ case Kind.INTERFACE_TYPE_EXTENSION:
10773
+ return 'interface';
10774
+
10775
+ case Kind.UNION_TYPE_EXTENSION:
10776
+ return 'union';
10777
+
10778
+ case Kind.ENUM_TYPE_EXTENSION:
10779
+ return 'enum';
10780
+
10781
+ case Kind.INPUT_OBJECT_TYPE_EXTENSION:
10782
+ return 'input object';
10783
+ } // istanbul ignore next (Not reachable. All possible types have been considered)
10784
+
10785
+ invariant(false, 'Unexpected kind: ' + inspect(kind));
10786
+ }
10787
+
10788
+ // Spec Section: "Executable Definitions"
10789
+ /**
10790
+ * This set includes all validation rules defined by the GraphQL spec.
10791
+ *
10792
+ * The order of the rules in this list has been adjusted to lead to the
10793
+ * most clear output when encountering multiple validation errors.
10794
+ */
10795
+
10796
+ const specifiedRules = Object.freeze([
10797
+ ExecutableDefinitionsRule,
10798
+ UniqueOperationNamesRule,
10799
+ LoneAnonymousOperationRule,
10800
+ SingleFieldSubscriptionsRule,
10801
+ KnownTypeNamesRule,
10802
+ FragmentsOnCompositeTypesRule,
10803
+ VariablesAreInputTypesRule,
10804
+ ScalarLeafsRule,
10805
+ FieldsOnCorrectTypeRule,
10806
+ UniqueFragmentNamesRule,
10807
+ KnownFragmentNamesRule,
10808
+ NoUnusedFragmentsRule,
10809
+ PossibleFragmentSpreadsRule,
10810
+ NoFragmentCyclesRule,
10811
+ UniqueVariableNamesRule,
10812
+ NoUndefinedVariablesRule,
10813
+ NoUnusedVariablesRule,
10814
+ KnownDirectivesRule,
10815
+ UniqueDirectivesPerLocationRule,
10816
+ KnownArgumentNamesRule,
10817
+ UniqueArgumentNamesRule,
10818
+ ValuesOfCorrectTypeRule,
10819
+ ProvidedRequiredArgumentsRule,
10820
+ VariablesInAllowedPositionRule,
10821
+ OverlappingFieldsCanBeMergedRule,
10822
+ UniqueInputFieldNamesRule,
10823
+ ]);
10824
+ /**
10825
+ * @internal
10826
+ */
10827
+
10828
+ const specifiedSDLRules = Object.freeze([
10829
+ LoneSchemaDefinitionRule,
10830
+ UniqueOperationTypesRule,
10831
+ UniqueTypeNamesRule,
10832
+ UniqueEnumValueNamesRule,
10833
+ UniqueFieldDefinitionNamesRule,
10834
+ UniqueArgumentDefinitionNamesRule,
10835
+ UniqueDirectiveNamesRule,
10836
+ KnownTypeNamesRule,
10837
+ KnownDirectivesRule,
10838
+ UniqueDirectivesPerLocationRule,
10839
+ PossibleTypeExtensionsRule,
10840
+ KnownArgumentNamesOnDirectivesRule,
10841
+ UniqueArgumentNamesRule,
10842
+ UniqueInputFieldNamesRule,
10843
+ ProvidedRequiredArgumentsOnDirectivesRule,
10844
+ ]);
10845
+
10846
+ /**
10847
+ * An instance of this class is passed as the "this" context to all validators,
10848
+ * allowing access to commonly useful contextual information from within a
10849
+ * validation rule.
10850
+ */
10851
+ class ASTValidationContext {
10852
+ constructor(ast, onError) {
10853
+ this._ast = ast;
10854
+ this._fragments = undefined;
10855
+ this._fragmentSpreads = new Map();
10856
+ this._recursivelyReferencedFragments = new Map();
10857
+ this._onError = onError;
10858
+ }
10859
+
10860
+ get [Symbol.toStringTag]() {
10861
+ return 'ASTValidationContext';
10862
+ }
10863
+
10864
+ reportError(error) {
10865
+ this._onError(error);
10866
+ }
10867
+
10868
+ getDocument() {
10869
+ return this._ast;
10870
+ }
10871
+
10872
+ getFragment(name) {
10873
+ let fragments;
10874
+
10875
+ if (this._fragments) {
10876
+ fragments = this._fragments;
10877
+ } else {
10878
+ fragments = Object.create(null);
10879
+
10880
+ for (const defNode of this.getDocument().definitions) {
10881
+ if (defNode.kind === Kind.FRAGMENT_DEFINITION) {
10882
+ fragments[defNode.name.value] = defNode;
10883
+ }
10884
+ }
10885
+
10886
+ this._fragments = fragments;
10887
+ }
10888
+
10889
+ return fragments[name];
10890
+ }
10891
+
10892
+ getFragmentSpreads(node) {
10893
+ let spreads = this._fragmentSpreads.get(node);
10894
+
10895
+ if (!spreads) {
10896
+ spreads = [];
10897
+ const setsToVisit = [node];
10898
+ let set;
10899
+
10900
+ while ((set = setsToVisit.pop())) {
10901
+ for (const selection of set.selections) {
10902
+ if (selection.kind === Kind.FRAGMENT_SPREAD) {
10903
+ spreads.push(selection);
10904
+ } else if (selection.selectionSet) {
10905
+ setsToVisit.push(selection.selectionSet);
10906
+ }
10907
+ }
10908
+ }
10909
+
10910
+ this._fragmentSpreads.set(node, spreads);
10911
+ }
10912
+
10913
+ return spreads;
10914
+ }
10915
+
10916
+ getRecursivelyReferencedFragments(operation) {
10917
+ let fragments = this._recursivelyReferencedFragments.get(operation);
10918
+
10919
+ if (!fragments) {
10920
+ fragments = [];
10921
+ const collectedNames = Object.create(null);
10922
+ const nodesToVisit = [operation.selectionSet];
10923
+ let node;
10924
+
10925
+ while ((node = nodesToVisit.pop())) {
10926
+ for (const spread of this.getFragmentSpreads(node)) {
10927
+ const fragName = spread.name.value;
10928
+
10929
+ if (collectedNames[fragName] !== true) {
10930
+ collectedNames[fragName] = true;
10931
+ const fragment = this.getFragment(fragName);
10932
+
10933
+ if (fragment) {
10934
+ fragments.push(fragment);
10935
+ nodesToVisit.push(fragment.selectionSet);
10936
+ }
10937
+ }
10938
+ }
10939
+ }
10940
+
10941
+ this._recursivelyReferencedFragments.set(operation, fragments);
10942
+ }
10943
+
10944
+ return fragments;
10945
+ }
10946
+ }
10947
+ class SDLValidationContext extends ASTValidationContext {
10948
+ constructor(ast, schema, onError) {
10949
+ super(ast, onError);
10950
+ this._schema = schema;
10951
+ }
10952
+
10953
+ get [Symbol.toStringTag]() {
10954
+ return 'SDLValidationContext';
10955
+ }
10956
+
10957
+ getSchema() {
10958
+ return this._schema;
10959
+ }
10960
+ }
10961
+
10962
+ /**
10963
+ * @internal
10964
+ */
10965
+
10966
+ function validateSDL(
10967
+ documentAST,
10968
+ schemaToExtend,
10969
+ rules = specifiedSDLRules,
10970
+ ) {
10971
+ const errors = [];
10972
+ const context = new SDLValidationContext(
10973
+ documentAST,
10974
+ schemaToExtend,
10975
+ (error) => {
10976
+ errors.push(error);
10977
+ },
10978
+ );
10979
+ const visitors = rules.map((rule) => rule(context));
10980
+ visit(documentAST, visitInParallel(visitors));
10981
+ return errors;
10982
+ }
10983
+ /**
10984
+ * Utility function which asserts a SDL document is valid by throwing an error
10985
+ * if it is invalid.
10986
+ *
10987
+ * @internal
10988
+ */
10989
+
10990
+ function assertValidSDL(documentAST) {
10991
+ const errors = validateSDL(documentAST);
10992
+
10993
+ if (errors.length !== 0) {
10994
+ throw new Error(errors.map((error) => error.message).join('\n\n'));
10995
+ }
10996
+ }
10997
+
10998
+ /**
10999
+ * Build a GraphQLSchema for use by client tools.
11000
+ *
11001
+ * Given the result of a client running the introspection query, creates and
11002
+ * returns a GraphQLSchema instance which can be then used with all graphql-js
11003
+ * tools, but cannot be used to execute a query, as introspection does not
11004
+ * represent the "resolver", "parse" or "serialize" functions or any other
11005
+ * server-internal mechanisms.
11006
+ *
11007
+ * This function expects a complete introspection result. Don't forget to check
11008
+ * the "errors" field of a server response before calling this function.
11009
+ */
11010
+
11011
+ function buildClientSchema(introspection, options) {
11012
+ (isObjectLike(introspection) && isObjectLike(introspection.__schema)) ||
11013
+ devAssert(
11014
+ false,
11015
+ `Invalid or incomplete introspection result. Ensure that you are passing "data" property of introspection response and no "errors" was returned alongside: ${inspect(
11016
+ introspection,
11017
+ )}.`,
11018
+ ); // Get the schema from the introspection result.
11019
+
11020
+ const schemaIntrospection = introspection.__schema; // Iterate through all types, getting the type definition for each.
11021
+
11022
+ const typeMap = keyValMap(
11023
+ schemaIntrospection.types,
11024
+ (typeIntrospection) => typeIntrospection.name,
11025
+ (typeIntrospection) => buildType(typeIntrospection),
11026
+ ); // Include standard types only if they are used.
11027
+
11028
+ for (const stdType of [...specifiedScalarTypes, ...introspectionTypes]) {
11029
+ if (typeMap[stdType.name]) {
11030
+ typeMap[stdType.name] = stdType;
11031
+ }
11032
+ } // Get the root Query, Mutation, and Subscription types.
11033
+
11034
+ const queryType = schemaIntrospection.queryType
11035
+ ? getObjectType(schemaIntrospection.queryType)
11036
+ : null;
11037
+ const mutationType = schemaIntrospection.mutationType
11038
+ ? getObjectType(schemaIntrospection.mutationType)
11039
+ : null;
11040
+ const subscriptionType = schemaIntrospection.subscriptionType
11041
+ ? getObjectType(schemaIntrospection.subscriptionType)
11042
+ : null; // Get the directives supported by Introspection, assuming empty-set if
11043
+ // directives were not queried for.
11044
+
11045
+ const directives = schemaIntrospection.directives
11046
+ ? schemaIntrospection.directives.map(buildDirective)
11047
+ : []; // Then produce and return a Schema with these types.
11048
+
11049
+ return new GraphQLSchema({
11050
+ description: schemaIntrospection.description,
11051
+ query: queryType,
11052
+ mutation: mutationType,
11053
+ subscription: subscriptionType,
11054
+ types: Object.values(typeMap),
11055
+ directives,
11056
+ assumeValid:
11057
+ options === null || options === void 0 ? void 0 : options.assumeValid,
11058
+ }); // Given a type reference in introspection, return the GraphQLType instance.
11059
+ // preferring cached instances before building new instances.
11060
+
11061
+ function getType(typeRef) {
11062
+ if (typeRef.kind === TypeKind.LIST) {
11063
+ const itemRef = typeRef.ofType;
11064
+
11065
+ if (!itemRef) {
11066
+ throw new Error('Decorated type deeper than introspection query.');
11067
+ }
11068
+
11069
+ return new GraphQLList(getType(itemRef));
11070
+ }
11071
+
11072
+ if (typeRef.kind === TypeKind.NON_NULL) {
11073
+ const nullableRef = typeRef.ofType;
11074
+
11075
+ if (!nullableRef) {
11076
+ throw new Error('Decorated type deeper than introspection query.');
11077
+ }
11078
+
11079
+ const nullableType = getType(nullableRef);
11080
+ return new GraphQLNonNull(assertNullableType(nullableType));
11081
+ }
11082
+
11083
+ return getNamedType(typeRef);
11084
+ }
11085
+
11086
+ function getNamedType(typeRef) {
11087
+ const typeName = typeRef.name;
11088
+
11089
+ if (!typeName) {
11090
+ throw new Error(`Unknown type reference: ${inspect(typeRef)}.`);
11091
+ }
11092
+
11093
+ const type = typeMap[typeName];
11094
+
11095
+ if (!type) {
11096
+ throw new Error(
11097
+ `Invalid or incomplete schema, unknown type: ${typeName}. Ensure that a full introspection query is used in order to build a client schema.`,
11098
+ );
11099
+ }
11100
+
11101
+ return type;
7464
11102
  }
7465
11103
 
7466
11104
  function getObjectType(typeRef) {
@@ -7694,6 +11332,796 @@ function buildClientSchema(introspection, options) {
7694
11332
  }
7695
11333
  }
7696
11334
 
11335
+ /**
11336
+ * @internal
11337
+ */
11338
+
11339
+ function extendSchemaImpl(schemaConfig, documentAST, options) {
11340
+ var _schemaDef, _schemaDef$descriptio, _schemaDef2, _options$assumeValid;
11341
+
11342
+ // Collect the type definitions and extensions found in the document.
11343
+ const typeDefs = [];
11344
+ const typeExtensionsMap = Object.create(null); // New directives and types are separate because a directives and types can
11345
+ // have the same name. For example, a type named "skip".
11346
+
11347
+ const directiveDefs = [];
11348
+ let schemaDef; // Schema extensions are collected which may add additional operation types.
11349
+
11350
+ const schemaExtensions = [];
11351
+
11352
+ for (const def of documentAST.definitions) {
11353
+ if (def.kind === Kind.SCHEMA_DEFINITION) {
11354
+ schemaDef = def;
11355
+ } else if (def.kind === Kind.SCHEMA_EXTENSION) {
11356
+ schemaExtensions.push(def);
11357
+ } else if (isTypeDefinitionNode(def)) {
11358
+ typeDefs.push(def);
11359
+ } else if (isTypeExtensionNode(def)) {
11360
+ const extendedTypeName = def.name.value;
11361
+ const existingTypeExtensions = typeExtensionsMap[extendedTypeName];
11362
+ typeExtensionsMap[extendedTypeName] = existingTypeExtensions
11363
+ ? existingTypeExtensions.concat([def])
11364
+ : [def];
11365
+ } else if (def.kind === Kind.DIRECTIVE_DEFINITION) {
11366
+ directiveDefs.push(def);
11367
+ }
11368
+ } // If this document contains no new types, extensions, or directives then
11369
+ // return the same unmodified GraphQLSchema instance.
11370
+
11371
+ if (
11372
+ Object.keys(typeExtensionsMap).length === 0 &&
11373
+ typeDefs.length === 0 &&
11374
+ directiveDefs.length === 0 &&
11375
+ schemaExtensions.length === 0 &&
11376
+ schemaDef == null
11377
+ ) {
11378
+ return schemaConfig;
11379
+ }
11380
+
11381
+ const typeMap = Object.create(null);
11382
+
11383
+ for (const existingType of schemaConfig.types) {
11384
+ typeMap[existingType.name] = extendNamedType(existingType);
11385
+ }
11386
+
11387
+ for (const typeNode of typeDefs) {
11388
+ var _stdTypeMap$name;
11389
+
11390
+ const name = typeNode.name.value;
11391
+ typeMap[name] =
11392
+ (_stdTypeMap$name = stdTypeMap[name]) !== null &&
11393
+ _stdTypeMap$name !== void 0
11394
+ ? _stdTypeMap$name
11395
+ : buildType(typeNode);
11396
+ }
11397
+
11398
+ const operationTypes = {
11399
+ // Get the extended root operation types.
11400
+ query: schemaConfig.query && replaceNamedType(schemaConfig.query),
11401
+ mutation: schemaConfig.mutation && replaceNamedType(schemaConfig.mutation),
11402
+ subscription:
11403
+ schemaConfig.subscription && replaceNamedType(schemaConfig.subscription),
11404
+ // Then, incorporate schema definition and all schema extensions.
11405
+ ...(schemaDef && getOperationTypes([schemaDef])),
11406
+ ...getOperationTypes(schemaExtensions),
11407
+ }; // Then produce and return a Schema config with these types.
11408
+
11409
+ return {
11410
+ description:
11411
+ (_schemaDef = schemaDef) === null || _schemaDef === void 0
11412
+ ? void 0
11413
+ : (_schemaDef$descriptio = _schemaDef.description) === null ||
11414
+ _schemaDef$descriptio === void 0
11415
+ ? void 0
11416
+ : _schemaDef$descriptio.value,
11417
+ ...operationTypes,
11418
+ types: Object.values(typeMap),
11419
+ directives: [
11420
+ ...schemaConfig.directives.map(replaceDirective),
11421
+ ...directiveDefs.map(buildDirective),
11422
+ ],
11423
+ extensions: Object.create(null),
11424
+ astNode:
11425
+ (_schemaDef2 = schemaDef) !== null && _schemaDef2 !== void 0
11426
+ ? _schemaDef2
11427
+ : schemaConfig.astNode,
11428
+ extensionASTNodes: schemaConfig.extensionASTNodes.concat(schemaExtensions),
11429
+ assumeValid:
11430
+ (_options$assumeValid =
11431
+ options === null || options === void 0
11432
+ ? void 0
11433
+ : options.assumeValid) !== null && _options$assumeValid !== void 0
11434
+ ? _options$assumeValid
11435
+ : false,
11436
+ }; // Below are functions used for producing this schema that have closed over
11437
+ // this scope and have access to the schema, cache, and newly defined types.
11438
+
11439
+ function replaceType(type) {
11440
+ if (isListType(type)) {
11441
+ // @ts-expect-error
11442
+ return new GraphQLList(replaceType(type.ofType));
11443
+ }
11444
+
11445
+ if (isNonNullType(type)) {
11446
+ // @ts-expect-error
11447
+ return new GraphQLNonNull(replaceType(type.ofType));
11448
+ } // @ts-expect-error FIXME
11449
+
11450
+ return replaceNamedType(type);
11451
+ }
11452
+
11453
+ function replaceNamedType(type) {
11454
+ // Note: While this could make early assertions to get the correctly
11455
+ // typed values, that would throw immediately while type system
11456
+ // validation with validateSchema() will produce more actionable results.
11457
+ return typeMap[type.name];
11458
+ }
11459
+
11460
+ function replaceDirective(directive) {
11461
+ const config = directive.toConfig();
11462
+ return new GraphQLDirective({
11463
+ ...config,
11464
+ args: mapValue(config.args, extendArg),
11465
+ });
11466
+ }
11467
+
11468
+ function extendNamedType(type) {
11469
+ if (isIntrospectionType(type) || isSpecifiedScalarType(type)) {
11470
+ // Builtin types are not extended.
11471
+ return type;
11472
+ }
11473
+
11474
+ if (isScalarType(type)) {
11475
+ return extendScalarType(type);
11476
+ }
11477
+
11478
+ if (isObjectType(type)) {
11479
+ return extendObjectType(type);
11480
+ }
11481
+
11482
+ if (isInterfaceType(type)) {
11483
+ return extendInterfaceType(type);
11484
+ }
11485
+
11486
+ if (isUnionType(type)) {
11487
+ return extendUnionType(type);
11488
+ }
11489
+
11490
+ if (isEnumType(type)) {
11491
+ return extendEnumType(type);
11492
+ } // istanbul ignore else (See: 'https://github.com/graphql/graphql-js/issues/2618')
11493
+
11494
+ if (isInputObjectType(type)) {
11495
+ return extendInputObjectType(type);
11496
+ } // istanbul ignore next (Not reachable. All possible types have been considered)
11497
+
11498
+ invariant(false, 'Unexpected type: ' + inspect(type));
11499
+ }
11500
+
11501
+ function extendInputObjectType(type) {
11502
+ var _typeExtensionsMap$co;
11503
+
11504
+ const config = type.toConfig();
11505
+ const extensions =
11506
+ (_typeExtensionsMap$co = typeExtensionsMap[config.name]) !== null &&
11507
+ _typeExtensionsMap$co !== void 0
11508
+ ? _typeExtensionsMap$co
11509
+ : [];
11510
+ return new GraphQLInputObjectType({
11511
+ ...config,
11512
+ fields: () => ({
11513
+ ...mapValue(config.fields, (field) => ({
11514
+ ...field,
11515
+ type: replaceType(field.type),
11516
+ })),
11517
+ ...buildInputFieldMap(extensions),
11518
+ }),
11519
+ extensionASTNodes: config.extensionASTNodes.concat(extensions),
11520
+ });
11521
+ }
11522
+
11523
+ function extendEnumType(type) {
11524
+ var _typeExtensionsMap$ty;
11525
+
11526
+ const config = type.toConfig();
11527
+ const extensions =
11528
+ (_typeExtensionsMap$ty = typeExtensionsMap[type.name]) !== null &&
11529
+ _typeExtensionsMap$ty !== void 0
11530
+ ? _typeExtensionsMap$ty
11531
+ : [];
11532
+ return new GraphQLEnumType({
11533
+ ...config,
11534
+ values: { ...config.values, ...buildEnumValueMap(extensions) },
11535
+ extensionASTNodes: config.extensionASTNodes.concat(extensions),
11536
+ });
11537
+ }
11538
+
11539
+ function extendScalarType(type) {
11540
+ var _typeExtensionsMap$co2;
11541
+
11542
+ const config = type.toConfig();
11543
+ const extensions =
11544
+ (_typeExtensionsMap$co2 = typeExtensionsMap[config.name]) !== null &&
11545
+ _typeExtensionsMap$co2 !== void 0
11546
+ ? _typeExtensionsMap$co2
11547
+ : [];
11548
+ let specifiedByURL = config.specifiedByURL;
11549
+
11550
+ for (const extensionNode of extensions) {
11551
+ var _getSpecifiedByURL;
11552
+
11553
+ specifiedByURL =
11554
+ (_getSpecifiedByURL = getSpecifiedByURL(extensionNode)) !== null &&
11555
+ _getSpecifiedByURL !== void 0
11556
+ ? _getSpecifiedByURL
11557
+ : specifiedByURL;
11558
+ }
11559
+
11560
+ return new GraphQLScalarType({
11561
+ ...config,
11562
+ specifiedByURL,
11563
+ extensionASTNodes: config.extensionASTNodes.concat(extensions),
11564
+ });
11565
+ }
11566
+
11567
+ function extendObjectType(type) {
11568
+ var _typeExtensionsMap$co3;
11569
+
11570
+ const config = type.toConfig();
11571
+ const extensions =
11572
+ (_typeExtensionsMap$co3 = typeExtensionsMap[config.name]) !== null &&
11573
+ _typeExtensionsMap$co3 !== void 0
11574
+ ? _typeExtensionsMap$co3
11575
+ : [];
11576
+ return new GraphQLObjectType({
11577
+ ...config,
11578
+ interfaces: () => [
11579
+ ...type.getInterfaces().map(replaceNamedType),
11580
+ ...buildInterfaces(extensions),
11581
+ ],
11582
+ fields: () => ({
11583
+ ...mapValue(config.fields, extendField),
11584
+ ...buildFieldMap(extensions),
11585
+ }),
11586
+ extensionASTNodes: config.extensionASTNodes.concat(extensions),
11587
+ });
11588
+ }
11589
+
11590
+ function extendInterfaceType(type) {
11591
+ var _typeExtensionsMap$co4;
11592
+
11593
+ const config = type.toConfig();
11594
+ const extensions =
11595
+ (_typeExtensionsMap$co4 = typeExtensionsMap[config.name]) !== null &&
11596
+ _typeExtensionsMap$co4 !== void 0
11597
+ ? _typeExtensionsMap$co4
11598
+ : [];
11599
+ return new GraphQLInterfaceType({
11600
+ ...config,
11601
+ interfaces: () => [
11602
+ ...type.getInterfaces().map(replaceNamedType),
11603
+ ...buildInterfaces(extensions),
11604
+ ],
11605
+ fields: () => ({
11606
+ ...mapValue(config.fields, extendField),
11607
+ ...buildFieldMap(extensions),
11608
+ }),
11609
+ extensionASTNodes: config.extensionASTNodes.concat(extensions),
11610
+ });
11611
+ }
11612
+
11613
+ function extendUnionType(type) {
11614
+ var _typeExtensionsMap$co5;
11615
+
11616
+ const config = type.toConfig();
11617
+ const extensions =
11618
+ (_typeExtensionsMap$co5 = typeExtensionsMap[config.name]) !== null &&
11619
+ _typeExtensionsMap$co5 !== void 0
11620
+ ? _typeExtensionsMap$co5
11621
+ : [];
11622
+ return new GraphQLUnionType({
11623
+ ...config,
11624
+ types: () => [
11625
+ ...type.getTypes().map(replaceNamedType),
11626
+ ...buildUnionTypes(extensions),
11627
+ ],
11628
+ extensionASTNodes: config.extensionASTNodes.concat(extensions),
11629
+ });
11630
+ }
11631
+
11632
+ function extendField(field) {
11633
+ return {
11634
+ ...field,
11635
+ type: replaceType(field.type),
11636
+ args: field.args && mapValue(field.args, extendArg),
11637
+ };
11638
+ }
11639
+
11640
+ function extendArg(arg) {
11641
+ return { ...arg, type: replaceType(arg.type) };
11642
+ }
11643
+
11644
+ function getOperationTypes(nodes) {
11645
+ const opTypes = {};
11646
+
11647
+ for (const node of nodes) {
11648
+ var _node$operationTypes;
11649
+
11650
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
11651
+ const operationTypesNodes =
11652
+ (_node$operationTypes = node.operationTypes) !== null &&
11653
+ _node$operationTypes !== void 0
11654
+ ? _node$operationTypes
11655
+ : [];
11656
+
11657
+ for (const operationType of operationTypesNodes) {
11658
+ // Note: While this could make early assertions to get the correctly
11659
+ // typed values below, that would throw immediately while type system
11660
+ // validation with validateSchema() will produce more actionable results.
11661
+ // @ts-expect-error
11662
+ opTypes[operationType.operation] = getNamedType(operationType.type);
11663
+ }
11664
+ }
11665
+
11666
+ return opTypes;
11667
+ }
11668
+
11669
+ function getNamedType(node) {
11670
+ var _stdTypeMap$name2;
11671
+
11672
+ const name = node.name.value;
11673
+ const type =
11674
+ (_stdTypeMap$name2 = stdTypeMap[name]) !== null &&
11675
+ _stdTypeMap$name2 !== void 0
11676
+ ? _stdTypeMap$name2
11677
+ : typeMap[name];
11678
+
11679
+ if (type === undefined) {
11680
+ throw new Error(`Unknown type: "${name}".`);
11681
+ }
11682
+
11683
+ return type;
11684
+ }
11685
+
11686
+ function getWrappedType(node) {
11687
+ if (node.kind === Kind.LIST_TYPE) {
11688
+ return new GraphQLList(getWrappedType(node.type));
11689
+ }
11690
+
11691
+ if (node.kind === Kind.NON_NULL_TYPE) {
11692
+ return new GraphQLNonNull(getWrappedType(node.type));
11693
+ }
11694
+
11695
+ return getNamedType(node);
11696
+ }
11697
+
11698
+ function buildDirective(node) {
11699
+ var _node$description;
11700
+
11701
+ return new GraphQLDirective({
11702
+ name: node.name.value,
11703
+ description:
11704
+ (_node$description = node.description) === null ||
11705
+ _node$description === void 0
11706
+ ? void 0
11707
+ : _node$description.value,
11708
+ // @ts-expect-error
11709
+ locations: node.locations.map(({ value }) => value),
11710
+ isRepeatable: node.repeatable,
11711
+ args: buildArgumentMap(node.arguments),
11712
+ astNode: node,
11713
+ });
11714
+ }
11715
+
11716
+ function buildFieldMap(nodes) {
11717
+ const fieldConfigMap = Object.create(null);
11718
+
11719
+ for (const node of nodes) {
11720
+ var _node$fields;
11721
+
11722
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
11723
+ const nodeFields =
11724
+ (_node$fields = node.fields) !== null && _node$fields !== void 0
11725
+ ? _node$fields
11726
+ : [];
11727
+
11728
+ for (const field of nodeFields) {
11729
+ var _field$description;
11730
+
11731
+ fieldConfigMap[field.name.value] = {
11732
+ // Note: While this could make assertions to get the correctly typed
11733
+ // value, that would throw immediately while type system validation
11734
+ // with validateSchema() will produce more actionable results.
11735
+ type: getWrappedType(field.type),
11736
+ description:
11737
+ (_field$description = field.description) === null ||
11738
+ _field$description === void 0
11739
+ ? void 0
11740
+ : _field$description.value,
11741
+ args: buildArgumentMap(field.arguments),
11742
+ deprecationReason: getDeprecationReason(field),
11743
+ astNode: field,
11744
+ };
11745
+ }
11746
+ }
11747
+
11748
+ return fieldConfigMap;
11749
+ }
11750
+
11751
+ function buildArgumentMap(args) {
11752
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
11753
+ const argsNodes = args !== null && args !== void 0 ? args : [];
11754
+ const argConfigMap = Object.create(null);
11755
+
11756
+ for (const arg of argsNodes) {
11757
+ var _arg$description;
11758
+
11759
+ // Note: While this could make assertions to get the correctly typed
11760
+ // value, that would throw immediately while type system validation
11761
+ // with validateSchema() will produce more actionable results.
11762
+ const type = getWrappedType(arg.type);
11763
+ argConfigMap[arg.name.value] = {
11764
+ type,
11765
+ description:
11766
+ (_arg$description = arg.description) === null ||
11767
+ _arg$description === void 0
11768
+ ? void 0
11769
+ : _arg$description.value,
11770
+ defaultValue: valueFromAST(arg.defaultValue, type),
11771
+ deprecationReason: getDeprecationReason(arg),
11772
+ astNode: arg,
11773
+ };
11774
+ }
11775
+
11776
+ return argConfigMap;
11777
+ }
11778
+
11779
+ function buildInputFieldMap(nodes) {
11780
+ const inputFieldMap = Object.create(null);
11781
+
11782
+ for (const node of nodes) {
11783
+ var _node$fields2;
11784
+
11785
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
11786
+ const fieldsNodes =
11787
+ (_node$fields2 = node.fields) !== null && _node$fields2 !== void 0
11788
+ ? _node$fields2
11789
+ : [];
11790
+
11791
+ for (const field of fieldsNodes) {
11792
+ var _field$description2;
11793
+
11794
+ // Note: While this could make assertions to get the correctly typed
11795
+ // value, that would throw immediately while type system validation
11796
+ // with validateSchema() will produce more actionable results.
11797
+ const type = getWrappedType(field.type);
11798
+ inputFieldMap[field.name.value] = {
11799
+ type,
11800
+ description:
11801
+ (_field$description2 = field.description) === null ||
11802
+ _field$description2 === void 0
11803
+ ? void 0
11804
+ : _field$description2.value,
11805
+ defaultValue: valueFromAST(field.defaultValue, type),
11806
+ deprecationReason: getDeprecationReason(field),
11807
+ astNode: field,
11808
+ };
11809
+ }
11810
+ }
11811
+
11812
+ return inputFieldMap;
11813
+ }
11814
+
11815
+ function buildEnumValueMap(nodes) {
11816
+ const enumValueMap = Object.create(null);
11817
+
11818
+ for (const node of nodes) {
11819
+ var _node$values;
11820
+
11821
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
11822
+ const valuesNodes =
11823
+ (_node$values = node.values) !== null && _node$values !== void 0
11824
+ ? _node$values
11825
+ : [];
11826
+
11827
+ for (const value of valuesNodes) {
11828
+ var _value$description;
11829
+
11830
+ enumValueMap[value.name.value] = {
11831
+ description:
11832
+ (_value$description = value.description) === null ||
11833
+ _value$description === void 0
11834
+ ? void 0
11835
+ : _value$description.value,
11836
+ deprecationReason: getDeprecationReason(value),
11837
+ astNode: value,
11838
+ };
11839
+ }
11840
+ }
11841
+
11842
+ return enumValueMap;
11843
+ }
11844
+
11845
+ function buildInterfaces(nodes) {
11846
+ // Note: While this could make assertions to get the correctly typed
11847
+ // values below, that would throw immediately while type system
11848
+ // validation with validateSchema() will produce more actionable results.
11849
+ // @ts-expect-error
11850
+ return nodes.flatMap(
11851
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
11852
+ (node) => {
11853
+ var _node$interfaces$map, _node$interfaces;
11854
+
11855
+ return (_node$interfaces$map =
11856
+ (_node$interfaces = node.interfaces) === null ||
11857
+ _node$interfaces === void 0
11858
+ ? void 0
11859
+ : _node$interfaces.map(getNamedType)) !== null &&
11860
+ _node$interfaces$map !== void 0
11861
+ ? _node$interfaces$map
11862
+ : [];
11863
+ },
11864
+ );
11865
+ }
11866
+
11867
+ function buildUnionTypes(nodes) {
11868
+ // Note: While this could make assertions to get the correctly typed
11869
+ // values below, that would throw immediately while type system
11870
+ // validation with validateSchema() will produce more actionable results.
11871
+ // @ts-expect-error
11872
+ return nodes.flatMap(
11873
+ // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203')
11874
+ (node) => {
11875
+ var _node$types$map, _node$types;
11876
+
11877
+ return (_node$types$map =
11878
+ (_node$types = node.types) === null || _node$types === void 0
11879
+ ? void 0
11880
+ : _node$types.map(getNamedType)) !== null &&
11881
+ _node$types$map !== void 0
11882
+ ? _node$types$map
11883
+ : [];
11884
+ },
11885
+ );
11886
+ }
11887
+
11888
+ function buildType(astNode) {
11889
+ var _typeExtensionsMap$na;
11890
+
11891
+ const name = astNode.name.value;
11892
+ const extensionASTNodes =
11893
+ (_typeExtensionsMap$na = typeExtensionsMap[name]) !== null &&
11894
+ _typeExtensionsMap$na !== void 0
11895
+ ? _typeExtensionsMap$na
11896
+ : [];
11897
+
11898
+ switch (astNode.kind) {
11899
+ case Kind.OBJECT_TYPE_DEFINITION: {
11900
+ var _astNode$description;
11901
+
11902
+ const allNodes = [astNode, ...extensionASTNodes];
11903
+ return new GraphQLObjectType({
11904
+ name,
11905
+ description:
11906
+ (_astNode$description = astNode.description) === null ||
11907
+ _astNode$description === void 0
11908
+ ? void 0
11909
+ : _astNode$description.value,
11910
+ interfaces: () => buildInterfaces(allNodes),
11911
+ fields: () => buildFieldMap(allNodes),
11912
+ astNode,
11913
+ extensionASTNodes,
11914
+ });
11915
+ }
11916
+
11917
+ case Kind.INTERFACE_TYPE_DEFINITION: {
11918
+ var _astNode$description2;
11919
+
11920
+ const allNodes = [astNode, ...extensionASTNodes];
11921
+ return new GraphQLInterfaceType({
11922
+ name,
11923
+ description:
11924
+ (_astNode$description2 = astNode.description) === null ||
11925
+ _astNode$description2 === void 0
11926
+ ? void 0
11927
+ : _astNode$description2.value,
11928
+ interfaces: () => buildInterfaces(allNodes),
11929
+ fields: () => buildFieldMap(allNodes),
11930
+ astNode,
11931
+ extensionASTNodes,
11932
+ });
11933
+ }
11934
+
11935
+ case Kind.ENUM_TYPE_DEFINITION: {
11936
+ var _astNode$description3;
11937
+
11938
+ const allNodes = [astNode, ...extensionASTNodes];
11939
+ return new GraphQLEnumType({
11940
+ name,
11941
+ description:
11942
+ (_astNode$description3 = astNode.description) === null ||
11943
+ _astNode$description3 === void 0
11944
+ ? void 0
11945
+ : _astNode$description3.value,
11946
+ values: buildEnumValueMap(allNodes),
11947
+ astNode,
11948
+ extensionASTNodes,
11949
+ });
11950
+ }
11951
+
11952
+ case Kind.UNION_TYPE_DEFINITION: {
11953
+ var _astNode$description4;
11954
+
11955
+ const allNodes = [astNode, ...extensionASTNodes];
11956
+ return new GraphQLUnionType({
11957
+ name,
11958
+ description:
11959
+ (_astNode$description4 = astNode.description) === null ||
11960
+ _astNode$description4 === void 0
11961
+ ? void 0
11962
+ : _astNode$description4.value,
11963
+ types: () => buildUnionTypes(allNodes),
11964
+ astNode,
11965
+ extensionASTNodes,
11966
+ });
11967
+ }
11968
+
11969
+ case Kind.SCALAR_TYPE_DEFINITION: {
11970
+ var _astNode$description5;
11971
+
11972
+ return new GraphQLScalarType({
11973
+ name,
11974
+ description:
11975
+ (_astNode$description5 = astNode.description) === null ||
11976
+ _astNode$description5 === void 0
11977
+ ? void 0
11978
+ : _astNode$description5.value,
11979
+ specifiedByURL: getSpecifiedByURL(astNode),
11980
+ astNode,
11981
+ extensionASTNodes,
11982
+ });
11983
+ }
11984
+
11985
+ case Kind.INPUT_OBJECT_TYPE_DEFINITION: {
11986
+ var _astNode$description6;
11987
+
11988
+ const allNodes = [astNode, ...extensionASTNodes];
11989
+ return new GraphQLInputObjectType({
11990
+ name,
11991
+ description:
11992
+ (_astNode$description6 = astNode.description) === null ||
11993
+ _astNode$description6 === void 0
11994
+ ? void 0
11995
+ : _astNode$description6.value,
11996
+ fields: () => buildInputFieldMap(allNodes),
11997
+ astNode,
11998
+ extensionASTNodes,
11999
+ });
12000
+ }
12001
+ } // istanbul ignore next (Not reachable. All possible type definition nodes have been considered)
12002
+
12003
+
12004
+ invariant(false, 'Unexpected type definition node: ' + inspect(astNode));
12005
+ }
12006
+ }
12007
+ const stdTypeMap = keyMap(
12008
+ [...specifiedScalarTypes, ...introspectionTypes],
12009
+ (type) => type.name,
12010
+ );
12011
+ /**
12012
+ * Given a field or enum value node, returns the string value for the
12013
+ * deprecation reason.
12014
+ */
12015
+
12016
+ function getDeprecationReason(node) {
12017
+ const deprecated = getDirectiveValues(GraphQLDeprecatedDirective, node); // @ts-expect-error validated by `getDirectiveValues`
12018
+
12019
+ return deprecated === null || deprecated === void 0
12020
+ ? void 0
12021
+ : deprecated.reason;
12022
+ }
12023
+ /**
12024
+ * Given a scalar node, returns the string value for the specifiedByURL.
12025
+ */
12026
+
12027
+ function getSpecifiedByURL(node) {
12028
+ const specifiedBy = getDirectiveValues(GraphQLSpecifiedByDirective, node); // @ts-expect-error validated by `getDirectiveValues`
12029
+
12030
+ return specifiedBy === null || specifiedBy === void 0
12031
+ ? void 0
12032
+ : specifiedBy.url;
12033
+ }
12034
+
12035
+ /**
12036
+ * This takes the ast of a schema document produced by the parse function in
12037
+ * src/language/parser.js.
12038
+ *
12039
+ * If no schema definition is provided, then it will look for types named Query,
12040
+ * Mutation and Subscription.
12041
+ *
12042
+ * Given that AST it constructs a GraphQLSchema. The resulting schema
12043
+ * has no resolve methods, so execution will use default resolvers.
12044
+ */
12045
+ function buildASTSchema(documentAST, options) {
12046
+ (documentAST != null && documentAST.kind === Kind.DOCUMENT) ||
12047
+ devAssert(false, 'Must provide valid Document AST.');
12048
+
12049
+ if (
12050
+ (options === null || options === void 0 ? void 0 : options.assumeValid) !==
12051
+ true &&
12052
+ (options === null || options === void 0
12053
+ ? void 0
12054
+ : options.assumeValidSDL) !== true
12055
+ ) {
12056
+ assertValidSDL(documentAST);
12057
+ }
12058
+
12059
+ const emptySchemaConfig = {
12060
+ description: undefined,
12061
+ types: [],
12062
+ directives: [],
12063
+ extensions: Object.create(null),
12064
+ extensionASTNodes: [],
12065
+ assumeValid: false,
12066
+ };
12067
+ const config = extendSchemaImpl(emptySchemaConfig, documentAST, options);
12068
+
12069
+ if (config.astNode == null) {
12070
+ for (const type of config.types) {
12071
+ switch (type.name) {
12072
+ // Note: While this could make early assertions to get the correctly
12073
+ // typed values below, that would throw immediately while type system
12074
+ // validation with validateSchema() will produce more actionable results.
12075
+ case 'Query':
12076
+ // @ts-expect-error validated in `validateSchema`
12077
+ config.query = type;
12078
+ break;
12079
+
12080
+ case 'Mutation':
12081
+ // @ts-expect-error validated in `validateSchema`
12082
+ config.mutation = type;
12083
+ break;
12084
+
12085
+ case 'Subscription':
12086
+ // @ts-expect-error validated in `validateSchema`
12087
+ config.subscription = type;
12088
+ break;
12089
+ }
12090
+ }
12091
+ }
12092
+
12093
+ const directives = [
12094
+ ...config.directives, // If specified directives were not explicitly declared, add them.
12095
+ ...specifiedDirectives.filter((stdDirective) =>
12096
+ config.directives.every(
12097
+ (directive) => directive.name !== stdDirective.name,
12098
+ ),
12099
+ ),
12100
+ ];
12101
+ return new GraphQLSchema({ ...config, directives });
12102
+ }
12103
+ /**
12104
+ * A helper function to build a GraphQLSchema directly from a source
12105
+ * document.
12106
+ */
12107
+
12108
+ function buildSchema(source, options) {
12109
+ const document = parse(source, {
12110
+ noLocation:
12111
+ options === null || options === void 0 ? void 0 : options.noLocation,
12112
+ allowLegacyFragmentVariables:
12113
+ options === null || options === void 0
12114
+ ? void 0
12115
+ : options.allowLegacyFragmentVariables,
12116
+ });
12117
+ return buildASTSchema(document, {
12118
+ assumeValidSDL:
12119
+ options === null || options === void 0 ? void 0 : options.assumeValidSDL,
12120
+ assumeValid:
12121
+ options === null || options === void 0 ? void 0 : options.assumeValid,
12122
+ });
12123
+ }
12124
+
7697
12125
  function printSchema(schema) {
7698
12126
  return printFilteredSchema(
7699
12127
  schema,
@@ -8086,8 +12514,8 @@ function run() {
8086
12514
  let oldSchema;
8087
12515
  let newSchema;
8088
12516
  let sources;
8089
- if (path.extname(schemaPath.toLowerCase()) === '.json') {
8090
- oldSchema = buildClientSchema(JSON.parse(oldFile));
12517
+ if (path.extname(schemaPath.toLowerCase()) === ".json") {
12518
+ oldSchema = endpoint ? buildSchema(oldFile) : buildClientSchema(JSON.parse(oldFile));
8091
12519
  newSchema = buildClientSchema(JSON.parse(newFile));
8092
12520
  sources = {
8093
12521
  old: new Source(printSchema(oldSchema), endpoint || `${schemaRef}:${schemaPath}`),
@@ -8160,6 +12588,8 @@ function fileLoader({ octokit, owner, repo, }) {
8160
12588
  repository(name: $repo, owner: $owner) {
8161
12589
  object(expression: $expression) {
8162
12590
  ... on Blob {
12591
+ isTruncated
12592
+ oid
8163
12593
  text
8164
12594
  }
8165
12595
  }
@@ -8167,7 +12597,7 @@ function fileLoader({ octokit, owner, repo, }) {
8167
12597
  }
8168
12598
  `;
8169
12599
  return function loadFile(file) {
8170
- var _a, _b;
12600
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
8171
12601
  return tslib.__awaiter(this, void 0, void 0, function* () {
8172
12602
  if (file.workspace) {
8173
12603
  return fs.readFileSync(path.resolve(file.workspace, file.path), {
@@ -8181,8 +12611,23 @@ function fileLoader({ octokit, owner, repo, }) {
8181
12611
  });
8182
12612
  core.info(`Query ${file.ref}:${file.path} from ${owner}/${repo}`);
8183
12613
  try {
8184
- if ((_b = (_a = result === null || result === void 0 ? void 0 : result.repository) === null || _a === void 0 ? void 0 : _a.object) === null || _b === void 0 ? void 0 : _b.text) {
8185
- return result.repository.object.text;
12614
+ if (((_b = (_a = result === null || result === void 0 ? void 0 : result.repository) === null || _a === void 0 ? void 0 : _a.object) === null || _b === void 0 ? void 0 : _b.oid) && ((_d = (_c = result === null || result === void 0 ? void 0 : result.repository) === null || _c === void 0 ? void 0 : _c.object) === null || _d === void 0 ? void 0 : _d.isTruncated)) {
12615
+ const oid = (_f = (_e = result === null || result === void 0 ? void 0 : result.repository) === null || _e === void 0 ? void 0 : _e.object) === null || _f === void 0 ? void 0 : _f.oid;
12616
+ const getBlobResponse = yield octokit.git.getBlob({
12617
+ owner,
12618
+ repo,
12619
+ file_sha: oid,
12620
+ });
12621
+ if ((_g = getBlobResponse === null || getBlobResponse === void 0 ? void 0 : getBlobResponse.data) === null || _g === void 0 ? void 0 : _g.content) {
12622
+ return Buffer.from((_h = getBlobResponse === null || getBlobResponse === void 0 ? void 0 : getBlobResponse.data) === null || _h === void 0 ? void 0 : _h.content, 'base64').toString('utf-8');
12623
+ }
12624
+ throw new Error('getBlobResponse.data.content is null');
12625
+ }
12626
+ if ((_k = (_j = result === null || result === void 0 ? void 0 : result.repository) === null || _j === void 0 ? void 0 : _j.object) === null || _k === void 0 ? void 0 : _k.text) {
12627
+ if (((_m = (_l = result === null || result === void 0 ? void 0 : result.repository) === null || _l === void 0 ? void 0 : _l.object) === null || _m === void 0 ? void 0 : _m.isTruncated) === false) {
12628
+ return result.repository.object.text;
12629
+ }
12630
+ throw new Error('result.repository.object.text is truncated and oid is null');
8186
12631
  }
8187
12632
  throw new Error('result.repository.object.text is null');
8188
12633
  }