graphql 15.7.2 → 15.9.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.
@@ -285,19 +285,30 @@ function executeFields(exeContext, parentType, sourceValue, path, fields) {
285
285
  var results = Object.create(null);
286
286
  var containsPromise = false;
287
287
 
288
- for (var _i4 = 0, _Object$keys2 = Object.keys(fields); _i4 < _Object$keys2.length; _i4++) {
289
- var responseName = _Object$keys2[_i4];
290
- var fieldNodes = fields[responseName];
291
- var fieldPath = (0, _Path.addPath)(path, responseName, parentType.name);
292
- var result = resolveField(exeContext, parentType, sourceValue, fieldNodes, fieldPath);
288
+ try {
289
+ for (var _i4 = 0, _Object$keys2 = Object.keys(fields); _i4 < _Object$keys2.length; _i4++) {
290
+ var responseName = _Object$keys2[_i4];
291
+ var fieldNodes = fields[responseName];
292
+ var fieldPath = (0, _Path.addPath)(path, responseName, parentType.name);
293
+ var result = resolveField(exeContext, parentType, sourceValue, fieldNodes, fieldPath);
293
294
 
294
- if (result !== undefined) {
295
- results[responseName] = result;
295
+ if (result !== undefined) {
296
+ results[responseName] = result;
296
297
 
297
- if ((0, _isPromise.default)(result)) {
298
- containsPromise = true;
298
+ if ((0, _isPromise.default)(result)) {
299
+ containsPromise = true;
300
+ }
299
301
  }
300
302
  }
303
+ } catch (error) {
304
+ if (containsPromise) {
305
+ // Ensure that any promises returned by other fields are handled, as they may also reject.
306
+ return (0, _promiseForObject.default)(results).finally(function () {
307
+ throw error;
308
+ });
309
+ }
310
+
311
+ throw error;
301
312
  } // If there are no promises, we can just return the object
302
313
 
303
314
 
@@ -457,23 +457,33 @@ function executeFields(
457
457
  const results = Object.create(null);
458
458
  let containsPromise = false;
459
459
 
460
- for (const responseName of Object.keys(fields)) {
461
- const fieldNodes = fields[responseName];
462
- const fieldPath = addPath(path, responseName, parentType.name);
463
- const result = resolveField(
464
- exeContext,
465
- parentType,
466
- sourceValue,
467
- fieldNodes,
468
- fieldPath,
469
- );
460
+ try {
461
+ for (const responseName of Object.keys(fields)) {
462
+ const fieldNodes = fields[responseName];
463
+ const fieldPath = addPath(path, responseName, parentType.name);
464
+ const result = resolveField(
465
+ exeContext,
466
+ parentType,
467
+ sourceValue,
468
+ fieldNodes,
469
+ fieldPath,
470
+ );
470
471
 
471
- if (result !== undefined) {
472
- results[responseName] = result;
473
- if (isPromise(result)) {
474
- containsPromise = true;
472
+ if (result !== undefined) {
473
+ results[responseName] = result;
474
+ if (isPromise(result)) {
475
+ containsPromise = true;
476
+ }
475
477
  }
476
478
  }
479
+ } catch (error) {
480
+ if (containsPromise) {
481
+ // Ensure that any promises returned by other fields are handled, as they may also reject.
482
+ return promiseForObject(results).finally(() => {
483
+ throw error;
484
+ });
485
+ }
486
+ throw error;
477
487
  }
478
488
 
479
489
  // If there are no promises, we can just return the object
@@ -273,19 +273,30 @@ function executeFields(exeContext, parentType, sourceValue, path, fields) {
273
273
  var results = Object.create(null);
274
274
  var containsPromise = false;
275
275
 
276
- for (var _i4 = 0, _Object$keys2 = Object.keys(fields); _i4 < _Object$keys2.length; _i4++) {
277
- var responseName = _Object$keys2[_i4];
278
- var fieldNodes = fields[responseName];
279
- var fieldPath = addPath(path, responseName, parentType.name);
280
- var result = resolveField(exeContext, parentType, sourceValue, fieldNodes, fieldPath);
276
+ try {
277
+ for (var _i4 = 0, _Object$keys2 = Object.keys(fields); _i4 < _Object$keys2.length; _i4++) {
278
+ var responseName = _Object$keys2[_i4];
279
+ var fieldNodes = fields[responseName];
280
+ var fieldPath = addPath(path, responseName, parentType.name);
281
+ var result = resolveField(exeContext, parentType, sourceValue, fieldNodes, fieldPath);
281
282
 
282
- if (result !== undefined) {
283
- results[responseName] = result;
283
+ if (result !== undefined) {
284
+ results[responseName] = result;
284
285
 
285
- if (isPromise(result)) {
286
- containsPromise = true;
286
+ if (isPromise(result)) {
287
+ containsPromise = true;
288
+ }
287
289
  }
288
290
  }
291
+ } catch (error) {
292
+ if (containsPromise) {
293
+ // Ensure that any promises returned by other fields are handled, as they may also reject.
294
+ return promiseForObject(results).finally(function () {
295
+ throw error;
296
+ });
297
+ }
298
+
299
+ throw error;
289
300
  } // If there are no promises, we can just return the object
290
301
 
291
302
 
package/index.d.ts CHANGED
@@ -138,6 +138,8 @@ export {
138
138
  GraphQLNullableType,
139
139
  GraphQLNamedType,
140
140
  Thunk,
141
+ GraphQLNamedInputType,
142
+ GraphQLNamedOutputType,
141
143
  GraphQLSchemaConfig,
142
144
  GraphQLSchemaExtensions,
143
145
  GraphQLDirectiveConfig,
@@ -315,6 +317,7 @@ export {
315
317
  ValidationContext,
316
318
  // All validation rules in the GraphQL Specification.
317
319
  specifiedRules,
320
+ recommendedRules,
318
321
  // Individual validation rules.
319
322
  ExecutableDefinitionsRule,
320
323
  FieldsOnCorrectTypeRule,
package/index.js CHANGED
@@ -747,6 +747,12 @@ Object.defineProperty(exports, "specifiedRules", {
747
747
  return _index5.specifiedRules;
748
748
  }
749
749
  });
750
+ Object.defineProperty(exports, "recommendedRules", {
751
+ enumerable: true,
752
+ get: function get() {
753
+ return _index5.recommendedRules;
754
+ }
755
+ });
750
756
  Object.defineProperty(exports, "ExecutableDefinitionsRule", {
751
757
  enumerable: true,
752
758
  get: function get() {
@@ -903,6 +909,12 @@ Object.defineProperty(exports, "VariablesInAllowedPositionRule", {
903
909
  return _index5.VariablesInAllowedPositionRule;
904
910
  }
905
911
  });
912
+ Object.defineProperty(exports, "MaxIntrospectionDepthRule", {
913
+ enumerable: true,
914
+ get: function get() {
915
+ return _index5.MaxIntrospectionDepthRule;
916
+ }
917
+ });
906
918
  Object.defineProperty(exports, "LoneSchemaDefinitionRule", {
907
919
  enumerable: true,
908
920
  get: function get() {
package/index.js.flow CHANGED
@@ -138,6 +138,8 @@ export type {
138
138
  GraphQLNullableType,
139
139
  GraphQLNamedType,
140
140
  Thunk,
141
+ GraphQLNamedInputType,
142
+ GraphQLNamedOutputType,
141
143
  GraphQLSchemaConfig,
142
144
  GraphQLDirectiveConfig,
143
145
  GraphQLArgument,
@@ -302,6 +304,7 @@ export {
302
304
  ValidationContext,
303
305
  // All validation rules in the GraphQL Specification.
304
306
  specifiedRules,
307
+ recommendedRules,
305
308
  // Individual validation rules.
306
309
  ExecutableDefinitionsRule,
307
310
  FieldsOnCorrectTypeRule,
@@ -329,6 +332,7 @@ export {
329
332
  ValuesOfCorrectTypeRule,
330
333
  VariablesAreInputTypesRule,
331
334
  VariablesInAllowedPositionRule,
335
+ MaxIntrospectionDepthRule,
332
336
  // SDL-specific validation rules
333
337
  LoneSchemaDefinitionRule,
334
338
  UniqueOperationTypesRule,
package/index.mjs CHANGED
@@ -51,8 +51,8 @@ export { execute, executeSync, defaultFieldResolver, defaultTypeResolver, respon
51
51
  export { subscribe, createSourceEventStream } from "./subscription/index.mjs";
52
52
  // Validate GraphQL documents.
53
53
  export { validate, ValidationContext // All validation rules in the GraphQL Specification.
54
- , specifiedRules // Individual validation rules.
55
- , ExecutableDefinitionsRule, FieldsOnCorrectTypeRule, FragmentsOnCompositeTypesRule, KnownArgumentNamesRule, KnownDirectivesRule, KnownFragmentNamesRule, KnownTypeNamesRule, LoneAnonymousOperationRule, NoFragmentCyclesRule, NoUndefinedVariablesRule, NoUnusedFragmentsRule, NoUnusedVariablesRule, OverlappingFieldsCanBeMergedRule, PossibleFragmentSpreadsRule, ProvidedRequiredArgumentsRule, ScalarLeafsRule, SingleFieldSubscriptionsRule, UniqueArgumentNamesRule, UniqueDirectivesPerLocationRule, UniqueFragmentNamesRule, UniqueInputFieldNamesRule, UniqueOperationNamesRule, UniqueVariableNamesRule, ValuesOfCorrectTypeRule, VariablesAreInputTypesRule, VariablesInAllowedPositionRule // SDL-specific validation rules
54
+ , specifiedRules, recommendedRules // Individual validation rules.
55
+ , ExecutableDefinitionsRule, FieldsOnCorrectTypeRule, FragmentsOnCompositeTypesRule, KnownArgumentNamesRule, KnownDirectivesRule, KnownFragmentNamesRule, KnownTypeNamesRule, LoneAnonymousOperationRule, NoFragmentCyclesRule, NoUndefinedVariablesRule, NoUnusedFragmentsRule, NoUnusedVariablesRule, OverlappingFieldsCanBeMergedRule, PossibleFragmentSpreadsRule, ProvidedRequiredArgumentsRule, ScalarLeafsRule, SingleFieldSubscriptionsRule, UniqueArgumentNamesRule, UniqueDirectivesPerLocationRule, UniqueFragmentNamesRule, UniqueInputFieldNamesRule, UniqueOperationNamesRule, UniqueVariableNamesRule, ValuesOfCorrectTypeRule, VariablesAreInputTypesRule, VariablesInAllowedPositionRule, MaxIntrospectionDepthRule // SDL-specific validation rules
56
56
  , LoneSchemaDefinitionRule, UniqueOperationTypesRule, UniqueTypeNamesRule, UniqueEnumValueNamesRule, UniqueFieldDefinitionNamesRule, UniqueDirectiveNamesRule, PossibleTypeExtensionsRule // Custom validation rules
57
57
  , NoDeprecatedCustomRule, NoSchemaIntrospectionCustomRule } from "./validation/index.mjs";
58
58
  // Create, format, and print GraphQL errors.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphql",
3
- "version": "15.7.2",
3
+ "version": "15.9.0",
4
4
  "description": "A Query Language and Runtime which can target any service.",
5
5
  "license": "MIT",
6
6
  "main": "index",
@@ -21,5 +21,8 @@
21
21
  ],
22
22
  "engines": {
23
23
  "node": ">= 10.x"
24
+ },
25
+ "publishConfig": {
26
+ "tag": "15.x.x"
24
27
  }
25
28
  }
@@ -254,19 +254,27 @@ export function getNullableType<T extends GraphQLNullableType>(
254
254
  /**
255
255
  * These named types do not include modifiers like List or NonNull.
256
256
  */
257
- export type GraphQLNamedType =
257
+ export type GraphQLNamedType = GraphQLNamedInputType | GraphQLNamedOutputType;
258
+
259
+ export type GraphQLNamedInputType =
260
+ | GraphQLScalarType
261
+ | GraphQLEnumType
262
+ | GraphQLInputObjectType;
263
+
264
+ export type GraphQLNamedOutputType =
258
265
  | GraphQLScalarType
259
266
  | GraphQLObjectType
260
267
  | GraphQLInterfaceType
261
268
  | GraphQLUnionType
262
- | GraphQLEnumType
263
- | GraphQLInputObjectType;
269
+ | GraphQLEnumType;
264
270
 
265
271
  export function isNamedType(type: any): type is GraphQLNamedType;
266
272
 
267
273
  export function assertNamedType(type: any): GraphQLNamedType;
268
274
 
269
275
  export function getNamedType(type: undefined): undefined;
276
+ export function getNamedType(type: GraphQLInputType): GraphQLNamedInputType;
277
+ export function getNamedType(type: GraphQLOutputType): GraphQLNamedOutputType;
270
278
  export function getNamedType(type: GraphQLType): GraphQLNamedType;
271
279
 
272
280
  /**
@@ -494,13 +494,19 @@ export function getNullableType(type) {
494
494
  /**
495
495
  * These named types do not include modifiers like List or NonNull.
496
496
  */
497
- export type GraphQLNamedType =
497
+ export type GraphQLNamedType = GraphQLNamedInputType | GraphQLNamedOutputType;
498
+
499
+ export type GraphQLNamedInputType =
500
+ | GraphQLScalarType
501
+ | GraphQLEnumType
502
+ | GraphQLInputObjectType;
503
+
504
+ export type GraphQLNamedOutputType =
498
505
  | GraphQLScalarType
499
506
  | GraphQLObjectType
500
507
  | GraphQLInterfaceType
501
508
  | GraphQLUnionType
502
- | GraphQLEnumType
503
- | GraphQLInputObjectType;
509
+ | GraphQLEnumType;
504
510
 
505
511
  export function isNamedType(type: mixed): boolean %checks {
506
512
  return (
@@ -522,6 +528,8 @@ export function assertNamedType(type: mixed): GraphQLNamedType {
522
528
 
523
529
  /* eslint-disable no-redeclare */
524
530
  declare function getNamedType(type: void | null): void;
531
+ declare function getNamedType(type: GraphQLInputType): GraphQLNamedInputType;
532
+ declare function getNamedType(type: GraphQLOutputType): GraphQLNamedOutputType;
525
533
  declare function getNamedType(type: GraphQLType): GraphQLNamedType;
526
534
  export function getNamedType(type) {
527
535
  /* eslint-enable no-redeclare */
package/type/index.d.ts CHANGED
@@ -74,6 +74,8 @@ export {
74
74
  GraphQLNullableType,
75
75
  GraphQLNamedType,
76
76
  Thunk,
77
+ GraphQLNamedInputType,
78
+ GraphQLNamedOutputType,
77
79
  GraphQLArgument,
78
80
  GraphQLArgumentConfig,
79
81
  GraphQLArgumentExtensions,
@@ -130,6 +130,8 @@ export type {
130
130
  GraphQLNullableType,
131
131
  GraphQLNamedType,
132
132
  Thunk,
133
+ GraphQLNamedInputType,
134
+ GraphQLNamedOutputType,
133
135
  GraphQLArgument,
134
136
  GraphQLArgumentConfig,
135
137
  GraphQLEnumTypeConfig,
@@ -2,7 +2,7 @@ export { validate } from './validate';
2
2
 
3
3
  export { ValidationContext, ValidationRule } from './ValidationContext';
4
4
 
5
- export { specifiedRules } from './specifiedRules';
5
+ export { specifiedRules, recommendedRules } from './specifiedRules';
6
6
 
7
7
  // Spec Section: "Executable Definitions"
8
8
  export { ExecutableDefinitionsRule } from './rules/ExecutableDefinitionsRule';
@@ -21,6 +21,12 @@ Object.defineProperty(exports, "specifiedRules", {
21
21
  return _specifiedRules.specifiedRules;
22
22
  }
23
23
  });
24
+ Object.defineProperty(exports, "recommendedRules", {
25
+ enumerable: true,
26
+ get: function get() {
27
+ return _specifiedRules.recommendedRules;
28
+ }
29
+ });
24
30
  Object.defineProperty(exports, "ExecutableDefinitionsRule", {
25
31
  enumerable: true,
26
32
  get: function get() {
@@ -177,6 +183,12 @@ Object.defineProperty(exports, "VariablesInAllowedPositionRule", {
177
183
  return _VariablesInAllowedPositionRule.VariablesInAllowedPositionRule;
178
184
  }
179
185
  });
186
+ Object.defineProperty(exports, "MaxIntrospectionDepthRule", {
187
+ enumerable: true,
188
+ get: function get() {
189
+ return _MaxIntrospectionDepthRule.MaxIntrospectionDepthRule;
190
+ }
191
+ });
180
192
  Object.defineProperty(exports, "LoneSchemaDefinitionRule", {
181
193
  enumerable: true,
182
194
  get: function get() {
@@ -290,6 +302,8 @@ var _VariablesAreInputTypesRule = require("./rules/VariablesAreInputTypesRule.js
290
302
 
291
303
  var _VariablesInAllowedPositionRule = require("./rules/VariablesInAllowedPositionRule.js");
292
304
 
305
+ var _MaxIntrospectionDepthRule = require("./rules/MaxIntrospectionDepthRule.js");
306
+
293
307
  var _LoneSchemaDefinitionRule = require("./rules/LoneSchemaDefinitionRule.js");
294
308
 
295
309
  var _UniqueOperationTypesRule = require("./rules/UniqueOperationTypesRule.js");
@@ -5,7 +5,7 @@ export { ValidationContext } from './ValidationContext';
5
5
  export type { ValidationRule } from './ValidationContext';
6
6
 
7
7
  // All validation rules in the GraphQL Specification.
8
- export { specifiedRules } from './specifiedRules';
8
+ export { specifiedRules, recommendedRules } from './specifiedRules';
9
9
 
10
10
  // Spec Section: "Executable Definitions"
11
11
  export { ExecutableDefinitionsRule } from './rules/ExecutableDefinitionsRule';
@@ -85,6 +85,8 @@ export { VariablesAreInputTypesRule } from './rules/VariablesAreInputTypesRule';
85
85
  // Spec Section: "All Variable Usages Are Allowed"
86
86
  export { VariablesInAllowedPositionRule } from './rules/VariablesInAllowedPositionRule';
87
87
 
88
+ export { MaxIntrospectionDepthRule } from './rules/MaxIntrospectionDepthRule';
89
+
88
90
  // SDL-specific validation rules
89
91
  export { LoneSchemaDefinitionRule } from './rules/LoneSchemaDefinitionRule';
90
92
  export { UniqueOperationTypesRule } from './rules/UniqueOperationTypesRule';
@@ -1,7 +1,7 @@
1
1
  export { validate } from "./validate.mjs";
2
2
  export { ValidationContext } from "./ValidationContext.mjs";
3
3
  // All validation rules in the GraphQL Specification.
4
- export { specifiedRules } from "./specifiedRules.mjs"; // Spec Section: "Executable Definitions"
4
+ export { specifiedRules, recommendedRules } from "./specifiedRules.mjs"; // Spec Section: "Executable Definitions"
5
5
 
6
6
  export { ExecutableDefinitionsRule } from "./rules/ExecutableDefinitionsRule.mjs"; // Spec Section: "Field Selections on Objects, Interfaces, and Unions Types"
7
7
 
@@ -53,7 +53,8 @@ export { ValuesOfCorrectTypeRule } from "./rules/ValuesOfCorrectTypeRule.mjs"; /
53
53
 
54
54
  export { VariablesAreInputTypesRule } from "./rules/VariablesAreInputTypesRule.mjs"; // Spec Section: "All Variable Usages Are Allowed"
55
55
 
56
- export { VariablesInAllowedPositionRule } from "./rules/VariablesInAllowedPositionRule.mjs"; // SDL-specific validation rules
56
+ export { VariablesInAllowedPositionRule } from "./rules/VariablesInAllowedPositionRule.mjs";
57
+ export { MaxIntrospectionDepthRule } from "./rules/MaxIntrospectionDepthRule.mjs"; // SDL-specific validation rules
57
58
 
58
59
  export { LoneSchemaDefinitionRule } from "./rules/LoneSchemaDefinitionRule.mjs";
59
60
  export { UniqueOperationTypesRule } from "./rules/UniqueOperationTypesRule.mjs";
@@ -0,0 +1,6 @@
1
+ import { ASTVisitor } from '../../language/visitor';
2
+ import { SDLValidationContext } from '../ValidationContext';
3
+
4
+ export function MaxIntrospectionDepthRule(
5
+ context: SDLValidationContext,
6
+ ): ASTVisitor;
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.MaxIntrospectionDepthRule = MaxIntrospectionDepthRule;
7
+
8
+ var _GraphQLError = require("../../error/GraphQLError.js");
9
+
10
+ var _kinds = require("../../language/kinds.js");
11
+
12
+ var MAX_LISTS_DEPTH = 3;
13
+
14
+ function MaxIntrospectionDepthRule(context) {
15
+ /**
16
+ * Counts the depth of list fields in "__Type" recursively and
17
+ * returns `true` if the limit has been reached.
18
+ */
19
+ function checkDepth(node) {
20
+ var visitedFragments = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Object.create(null);
21
+ var depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
22
+
23
+ if (node.kind === _kinds.Kind.FRAGMENT_SPREAD) {
24
+ var _fragmentName = node.name.value;
25
+
26
+ if (visitedFragments[_fragmentName] === true) {
27
+ // Fragment cycles are handled by `NoFragmentCyclesRule`.
28
+ return false;
29
+ }
30
+
31
+ var fragment = context.getFragment(_fragmentName);
32
+
33
+ if (!fragment) {
34
+ // Missing fragments checks are handled by `KnownFragmentNamesRule`.
35
+ return false;
36
+ } // Rather than following an immutable programming pattern which has
37
+ // significant memory and garbage collection overhead, we've opted to
38
+ // take a mutable approach for efficiency's sake. Importantly visiting a
39
+ // fragment twice is fine, so long as you don't do one visit inside the
40
+ // other.
41
+
42
+
43
+ try {
44
+ visitedFragments[_fragmentName] = true;
45
+ return checkDepth(fragment, visitedFragments, depth);
46
+ } finally {
47
+ visitedFragments[_fragmentName] = null;
48
+ }
49
+ }
50
+
51
+ if (node.kind === _kinds.Kind.FIELD && ( // check all introspection lists
52
+ node.name.value === 'fields' || node.name.value === 'interfaces' || node.name.value === 'possibleTypes' || node.name.value === 'inputFields')) {
53
+ // $FlowFixMe[reassign-const] why are argument parameters treated as const in flow?
54
+ depth++; // eslint-disable-line no-param-reassign
55
+
56
+ if (depth >= MAX_LISTS_DEPTH) {
57
+ return true;
58
+ }
59
+ } // handles fields and inline fragments
60
+
61
+
62
+ if ('selectionSet' in node && node.selectionSet) {
63
+ for (var _i2 = 0, _node$selectionSet$se2 = node.selectionSet.selections; _i2 < _node$selectionSet$se2.length; _i2++) {
64
+ var child = _node$selectionSet$se2[_i2];
65
+
66
+ if (checkDepth(child, visitedFragments, depth)) {
67
+ return true;
68
+ }
69
+ }
70
+ }
71
+
72
+ return false;
73
+ }
74
+
75
+ return {
76
+ Field: function Field(node) {
77
+ if (node.name.value === '__schema' || node.name.value === '__type') {
78
+ if (checkDepth(node)) {
79
+ context.reportError(new _GraphQLError.GraphQLError('Maximum introspection depth exceeded', [node]));
80
+ return false;
81
+ }
82
+ }
83
+ }
84
+ };
85
+ }
@@ -0,0 +1,91 @@
1
+ // @flow strict
2
+ import { GraphQLError } from '../../error/GraphQLError';
3
+
4
+ import type { ASTNode } from '../../language/ast';
5
+ import { Kind } from '../../language/kinds';
6
+ import type { ASTVisitor } from '../../language/visitor';
7
+
8
+ import type { ASTValidationContext } from '../ValidationContext';
9
+
10
+ const MAX_LISTS_DEPTH = 3;
11
+
12
+ export function MaxIntrospectionDepthRule(
13
+ context: ASTValidationContext,
14
+ ): ASTVisitor {
15
+ /**
16
+ * Counts the depth of list fields in "__Type" recursively and
17
+ * returns `true` if the limit has been reached.
18
+ */
19
+ function checkDepth(
20
+ node: ASTNode,
21
+ visitedFragments: {
22
+ [fragmentName: string]: true | null,
23
+ __proto__: null,
24
+ } = Object.create(null),
25
+ depth: number = 0,
26
+ ): boolean {
27
+ if (node.kind === Kind.FRAGMENT_SPREAD) {
28
+ const fragmentName = node.name.value;
29
+ if (visitedFragments[fragmentName] === true) {
30
+ // Fragment cycles are handled by `NoFragmentCyclesRule`.
31
+ return false;
32
+ }
33
+ const fragment = context.getFragment(fragmentName);
34
+ if (!fragment) {
35
+ // Missing fragments checks are handled by `KnownFragmentNamesRule`.
36
+ return false;
37
+ }
38
+
39
+ // Rather than following an immutable programming pattern which has
40
+ // significant memory and garbage collection overhead, we've opted to
41
+ // take a mutable approach for efficiency's sake. Importantly visiting a
42
+ // fragment twice is fine, so long as you don't do one visit inside the
43
+ // other.
44
+ try {
45
+ visitedFragments[fragmentName] = true;
46
+ return checkDepth(fragment, visitedFragments, depth);
47
+ } finally {
48
+ visitedFragments[fragmentName] = null;
49
+ }
50
+ }
51
+
52
+ if (
53
+ node.kind === Kind.FIELD &&
54
+ // check all introspection lists
55
+ (node.name.value === 'fields' ||
56
+ node.name.value === 'interfaces' ||
57
+ node.name.value === 'possibleTypes' ||
58
+ node.name.value === 'inputFields')
59
+ ) {
60
+ // $FlowFixMe[reassign-const] why are argument parameters treated as const in flow?
61
+ depth++; // eslint-disable-line no-param-reassign
62
+ if (depth >= MAX_LISTS_DEPTH) {
63
+ return true;
64
+ }
65
+ }
66
+
67
+ // handles fields and inline fragments
68
+ if ('selectionSet' in node && node.selectionSet) {
69
+ for (const child of node.selectionSet.selections) {
70
+ if (checkDepth(child, visitedFragments, depth)) {
71
+ return true;
72
+ }
73
+ }
74
+ }
75
+
76
+ return false;
77
+ }
78
+
79
+ return {
80
+ Field(node) {
81
+ if (node.name.value === '__schema' || node.name.value === '__type') {
82
+ if (checkDepth(node)) {
83
+ context.reportError(
84
+ new GraphQLError('Maximum introspection depth exceeded', [node]),
85
+ );
86
+ return false;
87
+ }
88
+ }
89
+ },
90
+ };
91
+ }
@@ -0,0 +1,75 @@
1
+ import { GraphQLError } from "../../error/GraphQLError.mjs";
2
+ import { Kind } from "../../language/kinds.mjs";
3
+ var MAX_LISTS_DEPTH = 3;
4
+ export function MaxIntrospectionDepthRule(context) {
5
+ /**
6
+ * Counts the depth of list fields in "__Type" recursively and
7
+ * returns `true` if the limit has been reached.
8
+ */
9
+ function checkDepth(node) {
10
+ var visitedFragments = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Object.create(null);
11
+ var depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
12
+
13
+ if (node.kind === Kind.FRAGMENT_SPREAD) {
14
+ var _fragmentName = node.name.value;
15
+
16
+ if (visitedFragments[_fragmentName] === true) {
17
+ // Fragment cycles are handled by `NoFragmentCyclesRule`.
18
+ return false;
19
+ }
20
+
21
+ var fragment = context.getFragment(_fragmentName);
22
+
23
+ if (!fragment) {
24
+ // Missing fragments checks are handled by `KnownFragmentNamesRule`.
25
+ return false;
26
+ } // Rather than following an immutable programming pattern which has
27
+ // significant memory and garbage collection overhead, we've opted to
28
+ // take a mutable approach for efficiency's sake. Importantly visiting a
29
+ // fragment twice is fine, so long as you don't do one visit inside the
30
+ // other.
31
+
32
+
33
+ try {
34
+ visitedFragments[_fragmentName] = true;
35
+ return checkDepth(fragment, visitedFragments, depth);
36
+ } finally {
37
+ visitedFragments[_fragmentName] = null;
38
+ }
39
+ }
40
+
41
+ if (node.kind === Kind.FIELD && ( // check all introspection lists
42
+ node.name.value === 'fields' || node.name.value === 'interfaces' || node.name.value === 'possibleTypes' || node.name.value === 'inputFields')) {
43
+ // $FlowFixMe[reassign-const] why are argument parameters treated as const in flow?
44
+ depth++; // eslint-disable-line no-param-reassign
45
+
46
+ if (depth >= MAX_LISTS_DEPTH) {
47
+ return true;
48
+ }
49
+ } // handles fields and inline fragments
50
+
51
+
52
+ if ('selectionSet' in node && node.selectionSet) {
53
+ for (var _i2 = 0, _node$selectionSet$se2 = node.selectionSet.selections; _i2 < _node$selectionSet$se2.length; _i2++) {
54
+ var child = _node$selectionSet$se2[_i2];
55
+
56
+ if (checkDepth(child, visitedFragments, depth)) {
57
+ return true;
58
+ }
59
+ }
60
+ }
61
+
62
+ return false;
63
+ }
64
+
65
+ return {
66
+ Field: function Field(node) {
67
+ if (node.name.value === '__schema' || node.name.value === '__type') {
68
+ if (checkDepth(node)) {
69
+ context.reportError(new GraphQLError('Maximum introspection depth exceeded', [node]));
70
+ return false;
71
+ }
72
+ }
73
+ }
74
+ };
75
+ }
@@ -180,6 +180,13 @@ function collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFiel
180
180
  // and any fragment names found in the given fragment.
181
181
 
182
182
  for (var i = 0; i < fragmentNames2.length; i++) {
183
+ var referencedFragmentName = fragmentNames2[i]; // Memoize so two fragments are not compared for conflicts more than once.
184
+
185
+ if (comparedFragmentPairs.has(referencedFragmentName, fragmentName, areMutuallyExclusive)) {
186
+ continue;
187
+ }
188
+
189
+ comparedFragmentPairs.add(referencedFragmentName, fragmentName, areMutuallyExclusive);
183
190
  collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap, fragmentNames2[i]);
184
191
  }
185
192
  } // Collect all conflicts found between two fragments, including via spreading in
@@ -265,6 +265,24 @@ function collectConflictsBetweenFieldsAndFragment(
265
265
  // (E) Then collect any conflicts between the provided collection of fields
266
266
  // and any fragment names found in the given fragment.
267
267
  for (let i = 0; i < fragmentNames2.length; i++) {
268
+ const referencedFragmentName = fragmentNames2[i];
269
+
270
+ // Memoize so two fragments are not compared for conflicts more than once.
271
+ if (
272
+ comparedFragmentPairs.has(
273
+ referencedFragmentName,
274
+ fragmentName,
275
+ areMutuallyExclusive,
276
+ )
277
+ ) {
278
+ continue;
279
+ }
280
+ comparedFragmentPairs.add(
281
+ referencedFragmentName,
282
+ fragmentName,
283
+ areMutuallyExclusive,
284
+ );
285
+
268
286
  collectConflictsBetweenFieldsAndFragment(
269
287
  context,
270
288
  conflicts,
@@ -164,6 +164,13 @@ function collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFiel
164
164
  // and any fragment names found in the given fragment.
165
165
 
166
166
  for (var i = 0; i < fragmentNames2.length; i++) {
167
+ var referencedFragmentName = fragmentNames2[i]; // Memoize so two fragments are not compared for conflicts more than once.
168
+
169
+ if (comparedFragmentPairs.has(referencedFragmentName, fragmentName, areMutuallyExclusive)) {
170
+ continue;
171
+ }
172
+
173
+ comparedFragmentPairs.add(referencedFragmentName, fragmentName, areMutuallyExclusive);
167
174
  collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap, fragmentNames2[i]);
168
175
  }
169
176
  } // Collect all conflicts found between two fragments, including via spreading in
@@ -1,5 +1,11 @@
1
1
  import { ValidationRule, SDLValidationRule } from './ValidationContext';
2
2
 
3
+ /**
4
+ * Technically these aren't part of the spec but they are strongly encouraged
5
+ * validation rules.
6
+ */
7
+ export const recommendedRules: ReadonlyArray<ValidationRule>;
8
+
3
9
  /**
4
10
  * This set includes all validation rules defined by the GraphQL spec.
5
11
  *
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.specifiedSDLRules = exports.specifiedRules = void 0;
6
+ exports.specifiedSDLRules = exports.specifiedRules = exports.recommendedRules = void 0;
7
7
 
8
8
  var _ExecutableDefinitionsRule = require("./rules/ExecutableDefinitionsRule.js");
9
9
 
@@ -57,6 +57,8 @@ var _OverlappingFieldsCanBeMergedRule = require("./rules/OverlappingFieldsCanBeM
57
57
 
58
58
  var _UniqueInputFieldNamesRule = require("./rules/UniqueInputFieldNamesRule.js");
59
59
 
60
+ var _MaxIntrospectionDepthRule = require("./rules/MaxIntrospectionDepthRule.js");
61
+
60
62
  var _LoneSchemaDefinitionRule = require("./rules/LoneSchemaDefinitionRule.js");
61
63
 
62
64
  var _UniqueOperationTypesRule = require("./rules/UniqueOperationTypesRule.js");
@@ -97,15 +99,23 @@ var _PossibleTypeExtensionsRule = require("./rules/PossibleTypeExtensionsRule.js
97
99
  // Spec Section: "All Variable Usages Are Allowed"
98
100
  // Spec Section: "Field Selection Merging"
99
101
  // Spec Section: "Input Object Field Uniqueness"
102
+ // TODO: Spec Section
100
103
  // SDL-specific validation rules
101
104
 
105
+ /**
106
+ * Technically these aren't part of the spec but they are strongly encouraged
107
+ * validation rules.
108
+ */
109
+ var recommendedRules = Object.freeze([_MaxIntrospectionDepthRule.MaxIntrospectionDepthRule]);
102
110
  /**
103
111
  * This set includes all validation rules defined by the GraphQL spec.
104
112
  *
105
113
  * The order of the rules in this list has been adjusted to lead to the
106
114
  * most clear output when encountering multiple validation errors.
107
115
  */
108
- var specifiedRules = Object.freeze([_ExecutableDefinitionsRule.ExecutableDefinitionsRule, _UniqueOperationNamesRule.UniqueOperationNamesRule, _LoneAnonymousOperationRule.LoneAnonymousOperationRule, _SingleFieldSubscriptionsRule.SingleFieldSubscriptionsRule, _KnownTypeNamesRule.KnownTypeNamesRule, _FragmentsOnCompositeTypesRule.FragmentsOnCompositeTypesRule, _VariablesAreInputTypesRule.VariablesAreInputTypesRule, _ScalarLeafsRule.ScalarLeafsRule, _FieldsOnCorrectTypeRule.FieldsOnCorrectTypeRule, _UniqueFragmentNamesRule.UniqueFragmentNamesRule, _KnownFragmentNamesRule.KnownFragmentNamesRule, _NoUnusedFragmentsRule.NoUnusedFragmentsRule, _PossibleFragmentSpreadsRule.PossibleFragmentSpreadsRule, _NoFragmentCyclesRule.NoFragmentCyclesRule, _UniqueVariableNamesRule.UniqueVariableNamesRule, _NoUndefinedVariablesRule.NoUndefinedVariablesRule, _NoUnusedVariablesRule.NoUnusedVariablesRule, _KnownDirectivesRule.KnownDirectivesRule, _UniqueDirectivesPerLocationRule.UniqueDirectivesPerLocationRule, _KnownArgumentNamesRule.KnownArgumentNamesRule, _UniqueArgumentNamesRule.UniqueArgumentNamesRule, _ValuesOfCorrectTypeRule.ValuesOfCorrectTypeRule, _ProvidedRequiredArgumentsRule.ProvidedRequiredArgumentsRule, _VariablesInAllowedPositionRule.VariablesInAllowedPositionRule, _OverlappingFieldsCanBeMergedRule.OverlappingFieldsCanBeMergedRule, _UniqueInputFieldNamesRule.UniqueInputFieldNamesRule]);
116
+
117
+ exports.recommendedRules = recommendedRules;
118
+ var specifiedRules = Object.freeze([_ExecutableDefinitionsRule.ExecutableDefinitionsRule, _UniqueOperationNamesRule.UniqueOperationNamesRule, _LoneAnonymousOperationRule.LoneAnonymousOperationRule, _SingleFieldSubscriptionsRule.SingleFieldSubscriptionsRule, _KnownTypeNamesRule.KnownTypeNamesRule, _FragmentsOnCompositeTypesRule.FragmentsOnCompositeTypesRule, _VariablesAreInputTypesRule.VariablesAreInputTypesRule, _ScalarLeafsRule.ScalarLeafsRule, _FieldsOnCorrectTypeRule.FieldsOnCorrectTypeRule, _UniqueFragmentNamesRule.UniqueFragmentNamesRule, _KnownFragmentNamesRule.KnownFragmentNamesRule, _NoUnusedFragmentsRule.NoUnusedFragmentsRule, _PossibleFragmentSpreadsRule.PossibleFragmentSpreadsRule, _NoFragmentCyclesRule.NoFragmentCyclesRule, _UniqueVariableNamesRule.UniqueVariableNamesRule, _NoUndefinedVariablesRule.NoUndefinedVariablesRule, _NoUnusedVariablesRule.NoUnusedVariablesRule, _KnownDirectivesRule.KnownDirectivesRule, _UniqueDirectivesPerLocationRule.UniqueDirectivesPerLocationRule, _KnownArgumentNamesRule.KnownArgumentNamesRule, _UniqueArgumentNamesRule.UniqueArgumentNamesRule, _ValuesOfCorrectTypeRule.ValuesOfCorrectTypeRule, _ProvidedRequiredArgumentsRule.ProvidedRequiredArgumentsRule, _VariablesInAllowedPositionRule.VariablesInAllowedPositionRule, _OverlappingFieldsCanBeMergedRule.OverlappingFieldsCanBeMergedRule, _UniqueInputFieldNamesRule.UniqueInputFieldNamesRule].concat(recommendedRules));
109
119
  /**
110
120
  * @internal
111
121
  */
@@ -83,6 +83,9 @@ import { OverlappingFieldsCanBeMergedRule } from './rules/OverlappingFieldsCanBe
83
83
  // Spec Section: "Input Object Field Uniqueness"
84
84
  import { UniqueInputFieldNamesRule } from './rules/UniqueInputFieldNamesRule';
85
85
 
86
+ // TODO: Spec Section
87
+ import { MaxIntrospectionDepthRule } from './rules/MaxIntrospectionDepthRule';
88
+
86
89
  // SDL-specific validation rules
87
90
  import { LoneSchemaDefinitionRule } from './rules/LoneSchemaDefinitionRule';
88
91
  import { UniqueOperationTypesRule } from './rules/UniqueOperationTypesRule';
@@ -92,6 +95,12 @@ import { UniqueFieldDefinitionNamesRule } from './rules/UniqueFieldDefinitionNam
92
95
  import { UniqueDirectiveNamesRule } from './rules/UniqueDirectiveNamesRule';
93
96
  import { PossibleTypeExtensionsRule } from './rules/PossibleTypeExtensionsRule';
94
97
 
98
+ /**
99
+ * Technically these aren't part of the spec but they are strongly encouraged
100
+ * validation rules.
101
+ */
102
+ export const recommendedRules = Object.freeze([MaxIntrospectionDepthRule]);
103
+
95
104
  /**
96
105
  * This set includes all validation rules defined by the GraphQL spec.
97
106
  *
@@ -125,6 +134,7 @@ export const specifiedRules = Object.freeze([
125
134
  VariablesInAllowedPositionRule,
126
135
  OverlappingFieldsCanBeMergedRule,
127
136
  UniqueInputFieldNamesRule,
137
+ ...recommendedRules,
128
138
  ]);
129
139
 
130
140
  /**
@@ -49,7 +49,9 @@ import { VariablesInAllowedPositionRule } from "./rules/VariablesInAllowedPositi
49
49
 
50
50
  import { OverlappingFieldsCanBeMergedRule } from "./rules/OverlappingFieldsCanBeMergedRule.mjs"; // Spec Section: "Input Object Field Uniqueness"
51
51
 
52
- import { UniqueInputFieldNamesRule } from "./rules/UniqueInputFieldNamesRule.mjs"; // SDL-specific validation rules
52
+ import { UniqueInputFieldNamesRule } from "./rules/UniqueInputFieldNamesRule.mjs"; // TODO: Spec Section
53
+
54
+ import { MaxIntrospectionDepthRule } from "./rules/MaxIntrospectionDepthRule.mjs"; // SDL-specific validation rules
53
55
 
54
56
  import { LoneSchemaDefinitionRule } from "./rules/LoneSchemaDefinitionRule.mjs";
55
57
  import { UniqueOperationTypesRule } from "./rules/UniqueOperationTypesRule.mjs";
@@ -58,6 +60,12 @@ import { UniqueEnumValueNamesRule } from "./rules/UniqueEnumValueNamesRule.mjs";
58
60
  import { UniqueFieldDefinitionNamesRule } from "./rules/UniqueFieldDefinitionNamesRule.mjs";
59
61
  import { UniqueDirectiveNamesRule } from "./rules/UniqueDirectiveNamesRule.mjs";
60
62
  import { PossibleTypeExtensionsRule } from "./rules/PossibleTypeExtensionsRule.mjs";
63
+ /**
64
+ * Technically these aren't part of the spec but they are strongly encouraged
65
+ * validation rules.
66
+ */
67
+
68
+ export var recommendedRules = Object.freeze([MaxIntrospectionDepthRule]);
61
69
  /**
62
70
  * This set includes all validation rules defined by the GraphQL spec.
63
71
  *
@@ -65,7 +73,7 @@ import { PossibleTypeExtensionsRule } from "./rules/PossibleTypeExtensionsRule.m
65
73
  * most clear output when encountering multiple validation errors.
66
74
  */
67
75
 
68
- export var specifiedRules = Object.freeze([ExecutableDefinitionsRule, UniqueOperationNamesRule, LoneAnonymousOperationRule, SingleFieldSubscriptionsRule, KnownTypeNamesRule, FragmentsOnCompositeTypesRule, VariablesAreInputTypesRule, ScalarLeafsRule, FieldsOnCorrectTypeRule, UniqueFragmentNamesRule, KnownFragmentNamesRule, NoUnusedFragmentsRule, PossibleFragmentSpreadsRule, NoFragmentCyclesRule, UniqueVariableNamesRule, NoUndefinedVariablesRule, NoUnusedVariablesRule, KnownDirectivesRule, UniqueDirectivesPerLocationRule, KnownArgumentNamesRule, UniqueArgumentNamesRule, ValuesOfCorrectTypeRule, ProvidedRequiredArgumentsRule, VariablesInAllowedPositionRule, OverlappingFieldsCanBeMergedRule, UniqueInputFieldNamesRule]);
76
+ export var specifiedRules = Object.freeze([ExecutableDefinitionsRule, UniqueOperationNamesRule, LoneAnonymousOperationRule, SingleFieldSubscriptionsRule, KnownTypeNamesRule, FragmentsOnCompositeTypesRule, VariablesAreInputTypesRule, ScalarLeafsRule, FieldsOnCorrectTypeRule, UniqueFragmentNamesRule, KnownFragmentNamesRule, NoUnusedFragmentsRule, PossibleFragmentSpreadsRule, NoFragmentCyclesRule, UniqueVariableNamesRule, NoUndefinedVariablesRule, NoUnusedVariablesRule, KnownDirectivesRule, UniqueDirectivesPerLocationRule, KnownArgumentNamesRule, UniqueArgumentNamesRule, ValuesOfCorrectTypeRule, ProvidedRequiredArgumentsRule, VariablesInAllowedPositionRule, OverlappingFieldsCanBeMergedRule, UniqueInputFieldNamesRule].concat(recommendedRules));
69
77
  /**
70
78
  * @internal
71
79
  */
package/version.js CHANGED
@@ -13,7 +13,7 @@ exports.versionInfo = exports.version = void 0;
13
13
  /**
14
14
  * A string containing the version of the GraphQL.js library
15
15
  */
16
- var version = '15.7.2';
16
+ var version = '15.9.0';
17
17
  /**
18
18
  * An object containing the components of the GraphQL.js version string
19
19
  */
@@ -21,8 +21,8 @@ var version = '15.7.2';
21
21
  exports.version = version;
22
22
  var versionInfo = Object.freeze({
23
23
  major: 15,
24
- minor: 7,
25
- patch: 2,
24
+ minor: 9,
25
+ patch: 0,
26
26
  preReleaseTag: null
27
27
  });
28
28
  exports.versionInfo = versionInfo;
package/version.js.flow CHANGED
@@ -7,14 +7,14 @@
7
7
  /**
8
8
  * A string containing the version of the GraphQL.js library
9
9
  */
10
- export const version = '15.7.2';
10
+ export const version = '15.9.0';
11
11
 
12
12
  /**
13
13
  * An object containing the components of the GraphQL.js version string
14
14
  */
15
15
  export const versionInfo = Object.freeze({
16
16
  major: 15,
17
- minor: 7,
18
- patch: 2,
17
+ minor: 9,
18
+ patch: 0,
19
19
  preReleaseTag: null,
20
20
  });
package/version.mjs CHANGED
@@ -6,14 +6,14 @@
6
6
  /**
7
7
  * A string containing the version of the GraphQL.js library
8
8
  */
9
- export var version = '15.7.2';
9
+ export var version = '15.9.0';
10
10
  /**
11
11
  * An object containing the components of the GraphQL.js version string
12
12
  */
13
13
 
14
14
  export var versionInfo = Object.freeze({
15
15
  major: 15,
16
- minor: 7,
17
- patch: 2,
16
+ minor: 9,
17
+ patch: 0,
18
18
  preReleaseTag: null
19
19
  });