graphql 16.9.0 → 16.10.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.
- package/README.md +2 -0
- package/error/GraphQLError.d.ts +13 -3
- package/error/index.d.ts +1 -0
- package/index.d.ts +1 -0
- package/language/ast.d.ts +1 -0
- package/language/parser.d.ts +1 -0
- package/language/parser.js +12 -3
- package/language/parser.mjs +12 -3
- package/package.json +1 -1
- package/type/validate.js +8 -2
- package/type/validate.mjs +8 -2
- package/utilities/getIntrospectionQuery.js +3 -3
- package/utilities/getIntrospectionQuery.mjs +3 -3
- package/validation/rules/OverlappingFieldsCanBeMergedRule.js +83 -35
- package/validation/rules/OverlappingFieldsCanBeMergedRule.mjs +83 -35
- package/validation/rules/ScalarLeafsRule.js +11 -0
- package/validation/rules/ScalarLeafsRule.mjs +11 -0
- package/version.js +2 -2
- package/version.mjs +2 -2
package/README.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
[](https://graphql.org/conf/2024/?utm_source=github&utm_medium=graphql_js&utm_campaign=readme)
|
|
2
|
+
|
|
1
3
|
# GraphQL.js
|
|
2
4
|
|
|
3
5
|
The JavaScript reference implementation for GraphQL, a query language for APIs created by Facebook.
|
package/error/GraphQLError.d.ts
CHANGED
|
@@ -14,6 +14,18 @@ import type { Source } from '../language/source';
|
|
|
14
14
|
export interface GraphQLErrorExtensions {
|
|
15
15
|
[attributeName: string]: unknown;
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Custom formatted extensions
|
|
19
|
+
*
|
|
20
|
+
* @remarks
|
|
21
|
+
* Use a unique identifier name for your extension, for example the name of
|
|
22
|
+
* your library or project. Do not use a shortened identifier as this increases
|
|
23
|
+
* the risk of conflicts. We recommend you add at most one extension field,
|
|
24
|
+
* an object which can contain all the values you need.
|
|
25
|
+
*/
|
|
26
|
+
export interface GraphQLFormattedErrorExtensions {
|
|
27
|
+
[attributeName: string]: unknown;
|
|
28
|
+
}
|
|
17
29
|
export interface GraphQLErrorOptions {
|
|
18
30
|
nodes?: ReadonlyArray<ASTNode> | ASTNode | null;
|
|
19
31
|
source?: Maybe<Source>;
|
|
@@ -122,9 +134,7 @@ export interface GraphQLFormattedError {
|
|
|
122
134
|
* Reserved for implementors to extend the protocol however they see fit,
|
|
123
135
|
* and hence there are no additional restrictions on its contents.
|
|
124
136
|
*/
|
|
125
|
-
readonly extensions?:
|
|
126
|
-
[key: string]: unknown;
|
|
127
|
-
};
|
|
137
|
+
readonly extensions?: GraphQLFormattedErrorExtensions;
|
|
128
138
|
}
|
|
129
139
|
/**
|
|
130
140
|
* Prints a GraphQLError to a string, representing useful location information
|
package/error/index.d.ts
CHANGED
package/index.d.ts
CHANGED
package/language/ast.d.ts
CHANGED
|
@@ -162,6 +162,7 @@ export interface DocumentNode {
|
|
|
162
162
|
readonly kind: Kind.DOCUMENT;
|
|
163
163
|
readonly loc?: Location;
|
|
164
164
|
readonly definitions: ReadonlyArray<DefinitionNode>;
|
|
165
|
+
readonly tokenCount?: number | undefined;
|
|
165
166
|
}
|
|
166
167
|
export declare type DefinitionNode =
|
|
167
168
|
| ExecutableDefinitionNode
|
package/language/parser.d.ts
CHANGED
|
@@ -149,6 +149,7 @@ export declare class Parser {
|
|
|
149
149
|
protected _lexer: Lexer;
|
|
150
150
|
protected _tokenCounter: number;
|
|
151
151
|
constructor(source: string | Source, options?: ParseOptions);
|
|
152
|
+
get tokenCount(): number;
|
|
152
153
|
/**
|
|
153
154
|
* Converts a name lex token into a name parse node.
|
|
154
155
|
*/
|
package/language/parser.js
CHANGED
|
@@ -29,7 +29,12 @@ var _tokenKind = require('./tokenKind.js');
|
|
|
29
29
|
*/
|
|
30
30
|
function parse(source, options) {
|
|
31
31
|
const parser = new Parser(source, options);
|
|
32
|
-
|
|
32
|
+
const document = parser.parseDocument();
|
|
33
|
+
Object.defineProperty(document, 'tokenCount', {
|
|
34
|
+
enumerable: false,
|
|
35
|
+
value: parser.tokenCount,
|
|
36
|
+
});
|
|
37
|
+
return document;
|
|
33
38
|
}
|
|
34
39
|
/**
|
|
35
40
|
* Given a string containing a GraphQL value (ex. `[42]`), parse the AST for
|
|
@@ -100,6 +105,10 @@ class Parser {
|
|
|
100
105
|
this._options = options;
|
|
101
106
|
this._tokenCounter = 0;
|
|
102
107
|
}
|
|
108
|
+
|
|
109
|
+
get tokenCount() {
|
|
110
|
+
return this._tokenCounter;
|
|
111
|
+
}
|
|
103
112
|
/**
|
|
104
113
|
* Converts a name lex token into a name parse node.
|
|
105
114
|
*/
|
|
@@ -1535,10 +1544,10 @@ class Parser {
|
|
|
1535
1544
|
|
|
1536
1545
|
const token = this._lexer.advance();
|
|
1537
1546
|
|
|
1538
|
-
if (
|
|
1547
|
+
if (token.kind !== _tokenKind.TokenKind.EOF) {
|
|
1539
1548
|
++this._tokenCounter;
|
|
1540
1549
|
|
|
1541
|
-
if (this._tokenCounter > maxTokens) {
|
|
1550
|
+
if (maxTokens !== undefined && this._tokenCounter > maxTokens) {
|
|
1542
1551
|
throw (0, _syntaxError.syntaxError)(
|
|
1543
1552
|
this._lexer.source,
|
|
1544
1553
|
token.start,
|
package/language/parser.mjs
CHANGED
|
@@ -15,7 +15,12 @@ import { TokenKind } from './tokenKind.mjs';
|
|
|
15
15
|
*/
|
|
16
16
|
export function parse(source, options) {
|
|
17
17
|
const parser = new Parser(source, options);
|
|
18
|
-
|
|
18
|
+
const document = parser.parseDocument();
|
|
19
|
+
Object.defineProperty(document, 'tokenCount', {
|
|
20
|
+
enumerable: false,
|
|
21
|
+
value: parser.tokenCount,
|
|
22
|
+
});
|
|
23
|
+
return document;
|
|
19
24
|
}
|
|
20
25
|
/**
|
|
21
26
|
* Given a string containing a GraphQL value (ex. `[42]`), parse the AST for
|
|
@@ -84,6 +89,10 @@ export class Parser {
|
|
|
84
89
|
this._options = options;
|
|
85
90
|
this._tokenCounter = 0;
|
|
86
91
|
}
|
|
92
|
+
|
|
93
|
+
get tokenCount() {
|
|
94
|
+
return this._tokenCounter;
|
|
95
|
+
}
|
|
87
96
|
/**
|
|
88
97
|
* Converts a name lex token into a name parse node.
|
|
89
98
|
*/
|
|
@@ -1494,10 +1503,10 @@ export class Parser {
|
|
|
1494
1503
|
|
|
1495
1504
|
const token = this._lexer.advance();
|
|
1496
1505
|
|
|
1497
|
-
if (
|
|
1506
|
+
if (token.kind !== TokenKind.EOF) {
|
|
1498
1507
|
++this._tokenCounter;
|
|
1499
1508
|
|
|
1500
|
-
if (this._tokenCounter > maxTokens) {
|
|
1509
|
+
if (maxTokens !== undefined && this._tokenCounter > maxTokens) {
|
|
1501
1510
|
throw syntaxError(
|
|
1502
1511
|
this._lexer.source,
|
|
1503
1512
|
token.start,
|
package/package.json
CHANGED
package/type/validate.js
CHANGED
|
@@ -175,8 +175,14 @@ function validateDirectives(context) {
|
|
|
175
175
|
continue;
|
|
176
176
|
} // Ensure they are named correctly.
|
|
177
177
|
|
|
178
|
-
validateName(context, directive);
|
|
179
|
-
|
|
178
|
+
validateName(context, directive);
|
|
179
|
+
|
|
180
|
+
if (directive.locations.length === 0) {
|
|
181
|
+
context.reportError(
|
|
182
|
+
`Directive @${directive.name} must include 1 or more locations.`,
|
|
183
|
+
directive.astNode,
|
|
184
|
+
);
|
|
185
|
+
} // Ensure the arguments are valid.
|
|
180
186
|
|
|
181
187
|
for (const arg of directive.args) {
|
|
182
188
|
// Ensure they are named correctly.
|
package/type/validate.mjs
CHANGED
|
@@ -173,8 +173,14 @@ function validateDirectives(context) {
|
|
|
173
173
|
continue;
|
|
174
174
|
} // Ensure they are named correctly.
|
|
175
175
|
|
|
176
|
-
validateName(context, directive);
|
|
177
|
-
|
|
176
|
+
validateName(context, directive);
|
|
177
|
+
|
|
178
|
+
if (directive.locations.length === 0) {
|
|
179
|
+
context.reportError(
|
|
180
|
+
`Directive @${directive.name} must include 1 or more locations.`,
|
|
181
|
+
directive.astNode,
|
|
182
|
+
);
|
|
183
|
+
} // Ensure the arguments are valid.
|
|
178
184
|
|
|
179
185
|
for (const arg of directive.args) {
|
|
180
186
|
// Ensure they are named correctly.
|
|
@@ -39,9 +39,9 @@ function getIntrospectionQuery(options) {
|
|
|
39
39
|
query IntrospectionQuery {
|
|
40
40
|
__schema {
|
|
41
41
|
${schemaDescription}
|
|
42
|
-
queryType { name }
|
|
43
|
-
mutationType { name }
|
|
44
|
-
subscriptionType { name }
|
|
42
|
+
queryType { name kind }
|
|
43
|
+
mutationType { name kind }
|
|
44
|
+
subscriptionType { name kind }
|
|
45
45
|
types {
|
|
46
46
|
...FullType
|
|
47
47
|
}
|
|
@@ -32,9 +32,9 @@ export function getIntrospectionQuery(options) {
|
|
|
32
32
|
query IntrospectionQuery {
|
|
33
33
|
__schema {
|
|
34
34
|
${schemaDescription}
|
|
35
|
-
queryType { name }
|
|
36
|
-
mutationType { name }
|
|
37
|
-
subscriptionType { name }
|
|
35
|
+
queryType { name kind }
|
|
36
|
+
mutationType { name kind }
|
|
37
|
+
subscriptionType { name kind }
|
|
38
38
|
types {
|
|
39
39
|
...FullType
|
|
40
40
|
}
|
|
@@ -43,9 +43,10 @@ function reasonMessage(reason) {
|
|
|
43
43
|
*/
|
|
44
44
|
|
|
45
45
|
function OverlappingFieldsCanBeMergedRule(context) {
|
|
46
|
-
// A memoization for when two fragments are compared
|
|
47
|
-
// conflicts.
|
|
48
|
-
// dramatically improve the performance of this validator.
|
|
46
|
+
// A memoization for when fields and a fragment or two fragments are compared
|
|
47
|
+
// "between" each other for conflicts. Comparisons made be made many times,
|
|
48
|
+
// so memoizing this can dramatically improve the performance of this validator.
|
|
49
|
+
const comparedFieldsAndFragmentPairs = new OrderedPairSet();
|
|
49
50
|
const comparedFragmentPairs = new PairSet(); // A cache for the "field map" and list of fragment names found in any given
|
|
50
51
|
// selection set. Selection sets may be asked for this information multiple
|
|
51
52
|
// times, so this improves the performance of this validator.
|
|
@@ -56,6 +57,7 @@ function OverlappingFieldsCanBeMergedRule(context) {
|
|
|
56
57
|
const conflicts = findConflictsWithinSelectionSet(
|
|
57
58
|
context,
|
|
58
59
|
cachedFieldsAndFragmentNames,
|
|
60
|
+
comparedFieldsAndFragmentPairs,
|
|
59
61
|
comparedFragmentPairs,
|
|
60
62
|
context.getParentType(),
|
|
61
63
|
selectionSet,
|
|
@@ -136,6 +138,7 @@ function OverlappingFieldsCanBeMergedRule(context) {
|
|
|
136
138
|
function findConflictsWithinSelectionSet(
|
|
137
139
|
context,
|
|
138
140
|
cachedFieldsAndFragmentNames,
|
|
141
|
+
comparedFieldsAndFragmentPairs,
|
|
139
142
|
comparedFragmentPairs,
|
|
140
143
|
parentType,
|
|
141
144
|
selectionSet,
|
|
@@ -153,6 +156,7 @@ function findConflictsWithinSelectionSet(
|
|
|
153
156
|
context,
|
|
154
157
|
conflicts,
|
|
155
158
|
cachedFieldsAndFragmentNames,
|
|
159
|
+
comparedFieldsAndFragmentPairs,
|
|
156
160
|
comparedFragmentPairs,
|
|
157
161
|
fieldMap,
|
|
158
162
|
);
|
|
@@ -165,6 +169,7 @@ function findConflictsWithinSelectionSet(
|
|
|
165
169
|
context,
|
|
166
170
|
conflicts,
|
|
167
171
|
cachedFieldsAndFragmentNames,
|
|
172
|
+
comparedFieldsAndFragmentPairs,
|
|
168
173
|
comparedFragmentPairs,
|
|
169
174
|
false,
|
|
170
175
|
fieldMap,
|
|
@@ -179,6 +184,7 @@ function findConflictsWithinSelectionSet(
|
|
|
179
184
|
context,
|
|
180
185
|
conflicts,
|
|
181
186
|
cachedFieldsAndFragmentNames,
|
|
187
|
+
comparedFieldsAndFragmentPairs,
|
|
182
188
|
comparedFragmentPairs,
|
|
183
189
|
false,
|
|
184
190
|
fragmentNames[i],
|
|
@@ -196,11 +202,29 @@ function collectConflictsBetweenFieldsAndFragment(
|
|
|
196
202
|
context,
|
|
197
203
|
conflicts,
|
|
198
204
|
cachedFieldsAndFragmentNames,
|
|
205
|
+
comparedFieldsAndFragmentPairs,
|
|
199
206
|
comparedFragmentPairs,
|
|
200
207
|
areMutuallyExclusive,
|
|
201
208
|
fieldMap,
|
|
202
209
|
fragmentName,
|
|
203
210
|
) {
|
|
211
|
+
// Memoize so the fields and fragments are not compared for conflicts more
|
|
212
|
+
// than once.
|
|
213
|
+
if (
|
|
214
|
+
comparedFieldsAndFragmentPairs.has(
|
|
215
|
+
fieldMap,
|
|
216
|
+
fragmentName,
|
|
217
|
+
areMutuallyExclusive,
|
|
218
|
+
)
|
|
219
|
+
) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
comparedFieldsAndFragmentPairs.add(
|
|
224
|
+
fieldMap,
|
|
225
|
+
fragmentName,
|
|
226
|
+
areMutuallyExclusive,
|
|
227
|
+
);
|
|
204
228
|
const fragment = context.getFragment(fragmentName);
|
|
205
229
|
|
|
206
230
|
if (!fragment) {
|
|
@@ -223,6 +247,7 @@ function collectConflictsBetweenFieldsAndFragment(
|
|
|
223
247
|
context,
|
|
224
248
|
conflicts,
|
|
225
249
|
cachedFieldsAndFragmentNames,
|
|
250
|
+
comparedFieldsAndFragmentPairs,
|
|
226
251
|
comparedFragmentPairs,
|
|
227
252
|
areMutuallyExclusive,
|
|
228
253
|
fieldMap,
|
|
@@ -231,26 +256,11 @@ function collectConflictsBetweenFieldsAndFragment(
|
|
|
231
256
|
// and any fragment names found in the given fragment.
|
|
232
257
|
|
|
233
258
|
for (const referencedFragmentName of referencedFragmentNames) {
|
|
234
|
-
// Memoize so two fragments are not compared for conflicts more than once.
|
|
235
|
-
if (
|
|
236
|
-
comparedFragmentPairs.has(
|
|
237
|
-
referencedFragmentName,
|
|
238
|
-
fragmentName,
|
|
239
|
-
areMutuallyExclusive,
|
|
240
|
-
)
|
|
241
|
-
) {
|
|
242
|
-
continue;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
comparedFragmentPairs.add(
|
|
246
|
-
referencedFragmentName,
|
|
247
|
-
fragmentName,
|
|
248
|
-
areMutuallyExclusive,
|
|
249
|
-
);
|
|
250
259
|
collectConflictsBetweenFieldsAndFragment(
|
|
251
260
|
context,
|
|
252
261
|
conflicts,
|
|
253
262
|
cachedFieldsAndFragmentNames,
|
|
263
|
+
comparedFieldsAndFragmentPairs,
|
|
254
264
|
comparedFragmentPairs,
|
|
255
265
|
areMutuallyExclusive,
|
|
256
266
|
fieldMap,
|
|
@@ -264,6 +274,7 @@ function collectConflictsBetweenFragments(
|
|
|
264
274
|
context,
|
|
265
275
|
conflicts,
|
|
266
276
|
cachedFieldsAndFragmentNames,
|
|
277
|
+
comparedFieldsAndFragmentPairs,
|
|
267
278
|
comparedFragmentPairs,
|
|
268
279
|
areMutuallyExclusive,
|
|
269
280
|
fragmentName1,
|
|
@@ -310,6 +321,7 @@ function collectConflictsBetweenFragments(
|
|
|
310
321
|
context,
|
|
311
322
|
conflicts,
|
|
312
323
|
cachedFieldsAndFragmentNames,
|
|
324
|
+
comparedFieldsAndFragmentPairs,
|
|
313
325
|
comparedFragmentPairs,
|
|
314
326
|
areMutuallyExclusive,
|
|
315
327
|
fieldMap1,
|
|
@@ -322,6 +334,7 @@ function collectConflictsBetweenFragments(
|
|
|
322
334
|
context,
|
|
323
335
|
conflicts,
|
|
324
336
|
cachedFieldsAndFragmentNames,
|
|
337
|
+
comparedFieldsAndFragmentPairs,
|
|
325
338
|
comparedFragmentPairs,
|
|
326
339
|
areMutuallyExclusive,
|
|
327
340
|
fragmentName1,
|
|
@@ -335,6 +348,7 @@ function collectConflictsBetweenFragments(
|
|
|
335
348
|
context,
|
|
336
349
|
conflicts,
|
|
337
350
|
cachedFieldsAndFragmentNames,
|
|
351
|
+
comparedFieldsAndFragmentPairs,
|
|
338
352
|
comparedFragmentPairs,
|
|
339
353
|
areMutuallyExclusive,
|
|
340
354
|
referencedFragmentName1,
|
|
@@ -348,6 +362,7 @@ function collectConflictsBetweenFragments(
|
|
|
348
362
|
function findConflictsBetweenSubSelectionSets(
|
|
349
363
|
context,
|
|
350
364
|
cachedFieldsAndFragmentNames,
|
|
365
|
+
comparedFieldsAndFragmentPairs,
|
|
351
366
|
comparedFragmentPairs,
|
|
352
367
|
areMutuallyExclusive,
|
|
353
368
|
parentType1,
|
|
@@ -373,6 +388,7 @@ function findConflictsBetweenSubSelectionSets(
|
|
|
373
388
|
context,
|
|
374
389
|
conflicts,
|
|
375
390
|
cachedFieldsAndFragmentNames,
|
|
391
|
+
comparedFieldsAndFragmentPairs,
|
|
376
392
|
comparedFragmentPairs,
|
|
377
393
|
areMutuallyExclusive,
|
|
378
394
|
fieldMap1,
|
|
@@ -385,6 +401,7 @@ function findConflictsBetweenSubSelectionSets(
|
|
|
385
401
|
context,
|
|
386
402
|
conflicts,
|
|
387
403
|
cachedFieldsAndFragmentNames,
|
|
404
|
+
comparedFieldsAndFragmentPairs,
|
|
388
405
|
comparedFragmentPairs,
|
|
389
406
|
areMutuallyExclusive,
|
|
390
407
|
fieldMap1,
|
|
@@ -398,6 +415,7 @@ function findConflictsBetweenSubSelectionSets(
|
|
|
398
415
|
context,
|
|
399
416
|
conflicts,
|
|
400
417
|
cachedFieldsAndFragmentNames,
|
|
418
|
+
comparedFieldsAndFragmentPairs,
|
|
401
419
|
comparedFragmentPairs,
|
|
402
420
|
areMutuallyExclusive,
|
|
403
421
|
fieldMap2,
|
|
@@ -413,6 +431,7 @@ function findConflictsBetweenSubSelectionSets(
|
|
|
413
431
|
context,
|
|
414
432
|
conflicts,
|
|
415
433
|
cachedFieldsAndFragmentNames,
|
|
434
|
+
comparedFieldsAndFragmentPairs,
|
|
416
435
|
comparedFragmentPairs,
|
|
417
436
|
areMutuallyExclusive,
|
|
418
437
|
fragmentName1,
|
|
@@ -428,6 +447,7 @@ function collectConflictsWithin(
|
|
|
428
447
|
context,
|
|
429
448
|
conflicts,
|
|
430
449
|
cachedFieldsAndFragmentNames,
|
|
450
|
+
comparedFieldsAndFragmentPairs,
|
|
431
451
|
comparedFragmentPairs,
|
|
432
452
|
fieldMap,
|
|
433
453
|
) {
|
|
@@ -445,6 +465,7 @@ function collectConflictsWithin(
|
|
|
445
465
|
const conflict = findConflict(
|
|
446
466
|
context,
|
|
447
467
|
cachedFieldsAndFragmentNames,
|
|
468
|
+
comparedFieldsAndFragmentPairs,
|
|
448
469
|
comparedFragmentPairs,
|
|
449
470
|
false, // within one collection is never mutually exclusive
|
|
450
471
|
responseName,
|
|
@@ -469,6 +490,7 @@ function collectConflictsBetween(
|
|
|
469
490
|
context,
|
|
470
491
|
conflicts,
|
|
471
492
|
cachedFieldsAndFragmentNames,
|
|
493
|
+
comparedFieldsAndFragmentPairs,
|
|
472
494
|
comparedFragmentPairs,
|
|
473
495
|
parentFieldsAreMutuallyExclusive,
|
|
474
496
|
fieldMap1,
|
|
@@ -488,6 +510,7 @@ function collectConflictsBetween(
|
|
|
488
510
|
const conflict = findConflict(
|
|
489
511
|
context,
|
|
490
512
|
cachedFieldsAndFragmentNames,
|
|
513
|
+
comparedFieldsAndFragmentPairs,
|
|
491
514
|
comparedFragmentPairs,
|
|
492
515
|
parentFieldsAreMutuallyExclusive,
|
|
493
516
|
responseName,
|
|
@@ -508,6 +531,7 @@ function collectConflictsBetween(
|
|
|
508
531
|
function findConflict(
|
|
509
532
|
context,
|
|
510
533
|
cachedFieldsAndFragmentNames,
|
|
534
|
+
comparedFieldsAndFragmentPairs,
|
|
511
535
|
comparedFragmentPairs,
|
|
512
536
|
parentFieldsAreMutuallyExclusive,
|
|
513
537
|
responseName,
|
|
@@ -577,6 +601,7 @@ function findConflict(
|
|
|
577
601
|
const conflicts = findConflictsBetweenSubSelectionSets(
|
|
578
602
|
context,
|
|
579
603
|
cachedFieldsAndFragmentNames,
|
|
604
|
+
comparedFieldsAndFragmentPairs,
|
|
580
605
|
comparedFragmentPairs,
|
|
581
606
|
areMutuallyExclusive,
|
|
582
607
|
(0, _definition.getNamedType)(type1),
|
|
@@ -779,42 +804,65 @@ function subfieldConflicts(conflicts, responseName, node1, node2) {
|
|
|
779
804
|
}
|
|
780
805
|
}
|
|
781
806
|
/**
|
|
782
|
-
* A way to keep track of pairs of things
|
|
807
|
+
* A way to keep track of pairs of things where the ordering of the pair
|
|
808
|
+
* matters.
|
|
809
|
+
*
|
|
810
|
+
* Provides a third argument for has/set to allow flagging the pair as
|
|
811
|
+
* weakly or strongly present within the collection.
|
|
783
812
|
*/
|
|
784
813
|
|
|
785
|
-
class
|
|
814
|
+
class OrderedPairSet {
|
|
786
815
|
constructor() {
|
|
787
816
|
this._data = new Map();
|
|
788
817
|
}
|
|
789
818
|
|
|
790
|
-
has(a, b,
|
|
819
|
+
has(a, b, weaklyPresent) {
|
|
791
820
|
var _this$_data$get;
|
|
792
821
|
|
|
793
|
-
const [key1, key2] = a < b ? [a, b] : [b, a];
|
|
794
822
|
const result =
|
|
795
|
-
(_this$_data$get = this._data.get(
|
|
823
|
+
(_this$_data$get = this._data.get(a)) === null ||
|
|
796
824
|
_this$_data$get === void 0
|
|
797
825
|
? void 0
|
|
798
|
-
: _this$_data$get.get(
|
|
826
|
+
: _this$_data$get.get(b);
|
|
799
827
|
|
|
800
828
|
if (result === undefined) {
|
|
801
829
|
return false;
|
|
802
|
-
}
|
|
803
|
-
// we want to know if this PairSet "has" these two with no exclusivity,
|
|
804
|
-
// we have to ensure it was added as such.
|
|
830
|
+
}
|
|
805
831
|
|
|
806
|
-
return
|
|
832
|
+
return weaklyPresent ? true : weaklyPresent === result;
|
|
807
833
|
}
|
|
808
834
|
|
|
809
|
-
add(a, b,
|
|
810
|
-
const
|
|
811
|
-
|
|
812
|
-
const map = this._data.get(key1);
|
|
835
|
+
add(a, b, weaklyPresent) {
|
|
836
|
+
const map = this._data.get(a);
|
|
813
837
|
|
|
814
838
|
if (map === undefined) {
|
|
815
|
-
this._data.set(
|
|
839
|
+
this._data.set(a, new Map([[b, weaklyPresent]]));
|
|
840
|
+
} else {
|
|
841
|
+
map.set(b, weaklyPresent);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* A way to keep track of pairs of similar things when the ordering of the pair
|
|
847
|
+
* does not matter.
|
|
848
|
+
*/
|
|
849
|
+
|
|
850
|
+
class PairSet {
|
|
851
|
+
constructor() {
|
|
852
|
+
this._orderedPairSet = new OrderedPairSet();
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
has(a, b, weaklyPresent) {
|
|
856
|
+
return a < b
|
|
857
|
+
? this._orderedPairSet.has(a, b, weaklyPresent)
|
|
858
|
+
: this._orderedPairSet.has(b, a, weaklyPresent);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
add(a, b, weaklyPresent) {
|
|
862
|
+
if (a < b) {
|
|
863
|
+
this._orderedPairSet.add(a, b, weaklyPresent);
|
|
816
864
|
} else {
|
|
817
|
-
|
|
865
|
+
this._orderedPairSet.add(b, a, weaklyPresent);
|
|
818
866
|
}
|
|
819
867
|
}
|
|
820
868
|
}
|
|
@@ -37,9 +37,10 @@ function reasonMessage(reason) {
|
|
|
37
37
|
*/
|
|
38
38
|
|
|
39
39
|
export function OverlappingFieldsCanBeMergedRule(context) {
|
|
40
|
-
// A memoization for when two fragments are compared
|
|
41
|
-
// conflicts.
|
|
42
|
-
// dramatically improve the performance of this validator.
|
|
40
|
+
// A memoization for when fields and a fragment or two fragments are compared
|
|
41
|
+
// "between" each other for conflicts. Comparisons made be made many times,
|
|
42
|
+
// so memoizing this can dramatically improve the performance of this validator.
|
|
43
|
+
const comparedFieldsAndFragmentPairs = new OrderedPairSet();
|
|
43
44
|
const comparedFragmentPairs = new PairSet(); // A cache for the "field map" and list of fragment names found in any given
|
|
44
45
|
// selection set. Selection sets may be asked for this information multiple
|
|
45
46
|
// times, so this improves the performance of this validator.
|
|
@@ -50,6 +51,7 @@ export function OverlappingFieldsCanBeMergedRule(context) {
|
|
|
50
51
|
const conflicts = findConflictsWithinSelectionSet(
|
|
51
52
|
context,
|
|
52
53
|
cachedFieldsAndFragmentNames,
|
|
54
|
+
comparedFieldsAndFragmentPairs,
|
|
53
55
|
comparedFragmentPairs,
|
|
54
56
|
context.getParentType(),
|
|
55
57
|
selectionSet,
|
|
@@ -130,6 +132,7 @@ export function OverlappingFieldsCanBeMergedRule(context) {
|
|
|
130
132
|
function findConflictsWithinSelectionSet(
|
|
131
133
|
context,
|
|
132
134
|
cachedFieldsAndFragmentNames,
|
|
135
|
+
comparedFieldsAndFragmentPairs,
|
|
133
136
|
comparedFragmentPairs,
|
|
134
137
|
parentType,
|
|
135
138
|
selectionSet,
|
|
@@ -147,6 +150,7 @@ function findConflictsWithinSelectionSet(
|
|
|
147
150
|
context,
|
|
148
151
|
conflicts,
|
|
149
152
|
cachedFieldsAndFragmentNames,
|
|
153
|
+
comparedFieldsAndFragmentPairs,
|
|
150
154
|
comparedFragmentPairs,
|
|
151
155
|
fieldMap,
|
|
152
156
|
);
|
|
@@ -159,6 +163,7 @@ function findConflictsWithinSelectionSet(
|
|
|
159
163
|
context,
|
|
160
164
|
conflicts,
|
|
161
165
|
cachedFieldsAndFragmentNames,
|
|
166
|
+
comparedFieldsAndFragmentPairs,
|
|
162
167
|
comparedFragmentPairs,
|
|
163
168
|
false,
|
|
164
169
|
fieldMap,
|
|
@@ -173,6 +178,7 @@ function findConflictsWithinSelectionSet(
|
|
|
173
178
|
context,
|
|
174
179
|
conflicts,
|
|
175
180
|
cachedFieldsAndFragmentNames,
|
|
181
|
+
comparedFieldsAndFragmentPairs,
|
|
176
182
|
comparedFragmentPairs,
|
|
177
183
|
false,
|
|
178
184
|
fragmentNames[i],
|
|
@@ -190,11 +196,29 @@ function collectConflictsBetweenFieldsAndFragment(
|
|
|
190
196
|
context,
|
|
191
197
|
conflicts,
|
|
192
198
|
cachedFieldsAndFragmentNames,
|
|
199
|
+
comparedFieldsAndFragmentPairs,
|
|
193
200
|
comparedFragmentPairs,
|
|
194
201
|
areMutuallyExclusive,
|
|
195
202
|
fieldMap,
|
|
196
203
|
fragmentName,
|
|
197
204
|
) {
|
|
205
|
+
// Memoize so the fields and fragments are not compared for conflicts more
|
|
206
|
+
// than once.
|
|
207
|
+
if (
|
|
208
|
+
comparedFieldsAndFragmentPairs.has(
|
|
209
|
+
fieldMap,
|
|
210
|
+
fragmentName,
|
|
211
|
+
areMutuallyExclusive,
|
|
212
|
+
)
|
|
213
|
+
) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
comparedFieldsAndFragmentPairs.add(
|
|
218
|
+
fieldMap,
|
|
219
|
+
fragmentName,
|
|
220
|
+
areMutuallyExclusive,
|
|
221
|
+
);
|
|
198
222
|
const fragment = context.getFragment(fragmentName);
|
|
199
223
|
|
|
200
224
|
if (!fragment) {
|
|
@@ -217,6 +241,7 @@ function collectConflictsBetweenFieldsAndFragment(
|
|
|
217
241
|
context,
|
|
218
242
|
conflicts,
|
|
219
243
|
cachedFieldsAndFragmentNames,
|
|
244
|
+
comparedFieldsAndFragmentPairs,
|
|
220
245
|
comparedFragmentPairs,
|
|
221
246
|
areMutuallyExclusive,
|
|
222
247
|
fieldMap,
|
|
@@ -225,26 +250,11 @@ function collectConflictsBetweenFieldsAndFragment(
|
|
|
225
250
|
// and any fragment names found in the given fragment.
|
|
226
251
|
|
|
227
252
|
for (const referencedFragmentName of referencedFragmentNames) {
|
|
228
|
-
// Memoize so two fragments are not compared for conflicts more than once.
|
|
229
|
-
if (
|
|
230
|
-
comparedFragmentPairs.has(
|
|
231
|
-
referencedFragmentName,
|
|
232
|
-
fragmentName,
|
|
233
|
-
areMutuallyExclusive,
|
|
234
|
-
)
|
|
235
|
-
) {
|
|
236
|
-
continue;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
comparedFragmentPairs.add(
|
|
240
|
-
referencedFragmentName,
|
|
241
|
-
fragmentName,
|
|
242
|
-
areMutuallyExclusive,
|
|
243
|
-
);
|
|
244
253
|
collectConflictsBetweenFieldsAndFragment(
|
|
245
254
|
context,
|
|
246
255
|
conflicts,
|
|
247
256
|
cachedFieldsAndFragmentNames,
|
|
257
|
+
comparedFieldsAndFragmentPairs,
|
|
248
258
|
comparedFragmentPairs,
|
|
249
259
|
areMutuallyExclusive,
|
|
250
260
|
fieldMap,
|
|
@@ -258,6 +268,7 @@ function collectConflictsBetweenFragments(
|
|
|
258
268
|
context,
|
|
259
269
|
conflicts,
|
|
260
270
|
cachedFieldsAndFragmentNames,
|
|
271
|
+
comparedFieldsAndFragmentPairs,
|
|
261
272
|
comparedFragmentPairs,
|
|
262
273
|
areMutuallyExclusive,
|
|
263
274
|
fragmentName1,
|
|
@@ -304,6 +315,7 @@ function collectConflictsBetweenFragments(
|
|
|
304
315
|
context,
|
|
305
316
|
conflicts,
|
|
306
317
|
cachedFieldsAndFragmentNames,
|
|
318
|
+
comparedFieldsAndFragmentPairs,
|
|
307
319
|
comparedFragmentPairs,
|
|
308
320
|
areMutuallyExclusive,
|
|
309
321
|
fieldMap1,
|
|
@@ -316,6 +328,7 @@ function collectConflictsBetweenFragments(
|
|
|
316
328
|
context,
|
|
317
329
|
conflicts,
|
|
318
330
|
cachedFieldsAndFragmentNames,
|
|
331
|
+
comparedFieldsAndFragmentPairs,
|
|
319
332
|
comparedFragmentPairs,
|
|
320
333
|
areMutuallyExclusive,
|
|
321
334
|
fragmentName1,
|
|
@@ -329,6 +342,7 @@ function collectConflictsBetweenFragments(
|
|
|
329
342
|
context,
|
|
330
343
|
conflicts,
|
|
331
344
|
cachedFieldsAndFragmentNames,
|
|
345
|
+
comparedFieldsAndFragmentPairs,
|
|
332
346
|
comparedFragmentPairs,
|
|
333
347
|
areMutuallyExclusive,
|
|
334
348
|
referencedFragmentName1,
|
|
@@ -342,6 +356,7 @@ function collectConflictsBetweenFragments(
|
|
|
342
356
|
function findConflictsBetweenSubSelectionSets(
|
|
343
357
|
context,
|
|
344
358
|
cachedFieldsAndFragmentNames,
|
|
359
|
+
comparedFieldsAndFragmentPairs,
|
|
345
360
|
comparedFragmentPairs,
|
|
346
361
|
areMutuallyExclusive,
|
|
347
362
|
parentType1,
|
|
@@ -367,6 +382,7 @@ function findConflictsBetweenSubSelectionSets(
|
|
|
367
382
|
context,
|
|
368
383
|
conflicts,
|
|
369
384
|
cachedFieldsAndFragmentNames,
|
|
385
|
+
comparedFieldsAndFragmentPairs,
|
|
370
386
|
comparedFragmentPairs,
|
|
371
387
|
areMutuallyExclusive,
|
|
372
388
|
fieldMap1,
|
|
@@ -379,6 +395,7 @@ function findConflictsBetweenSubSelectionSets(
|
|
|
379
395
|
context,
|
|
380
396
|
conflicts,
|
|
381
397
|
cachedFieldsAndFragmentNames,
|
|
398
|
+
comparedFieldsAndFragmentPairs,
|
|
382
399
|
comparedFragmentPairs,
|
|
383
400
|
areMutuallyExclusive,
|
|
384
401
|
fieldMap1,
|
|
@@ -392,6 +409,7 @@ function findConflictsBetweenSubSelectionSets(
|
|
|
392
409
|
context,
|
|
393
410
|
conflicts,
|
|
394
411
|
cachedFieldsAndFragmentNames,
|
|
412
|
+
comparedFieldsAndFragmentPairs,
|
|
395
413
|
comparedFragmentPairs,
|
|
396
414
|
areMutuallyExclusive,
|
|
397
415
|
fieldMap2,
|
|
@@ -407,6 +425,7 @@ function findConflictsBetweenSubSelectionSets(
|
|
|
407
425
|
context,
|
|
408
426
|
conflicts,
|
|
409
427
|
cachedFieldsAndFragmentNames,
|
|
428
|
+
comparedFieldsAndFragmentPairs,
|
|
410
429
|
comparedFragmentPairs,
|
|
411
430
|
areMutuallyExclusive,
|
|
412
431
|
fragmentName1,
|
|
@@ -422,6 +441,7 @@ function collectConflictsWithin(
|
|
|
422
441
|
context,
|
|
423
442
|
conflicts,
|
|
424
443
|
cachedFieldsAndFragmentNames,
|
|
444
|
+
comparedFieldsAndFragmentPairs,
|
|
425
445
|
comparedFragmentPairs,
|
|
426
446
|
fieldMap,
|
|
427
447
|
) {
|
|
@@ -439,6 +459,7 @@ function collectConflictsWithin(
|
|
|
439
459
|
const conflict = findConflict(
|
|
440
460
|
context,
|
|
441
461
|
cachedFieldsAndFragmentNames,
|
|
462
|
+
comparedFieldsAndFragmentPairs,
|
|
442
463
|
comparedFragmentPairs,
|
|
443
464
|
false, // within one collection is never mutually exclusive
|
|
444
465
|
responseName,
|
|
@@ -463,6 +484,7 @@ function collectConflictsBetween(
|
|
|
463
484
|
context,
|
|
464
485
|
conflicts,
|
|
465
486
|
cachedFieldsAndFragmentNames,
|
|
487
|
+
comparedFieldsAndFragmentPairs,
|
|
466
488
|
comparedFragmentPairs,
|
|
467
489
|
parentFieldsAreMutuallyExclusive,
|
|
468
490
|
fieldMap1,
|
|
@@ -482,6 +504,7 @@ function collectConflictsBetween(
|
|
|
482
504
|
const conflict = findConflict(
|
|
483
505
|
context,
|
|
484
506
|
cachedFieldsAndFragmentNames,
|
|
507
|
+
comparedFieldsAndFragmentPairs,
|
|
485
508
|
comparedFragmentPairs,
|
|
486
509
|
parentFieldsAreMutuallyExclusive,
|
|
487
510
|
responseName,
|
|
@@ -502,6 +525,7 @@ function collectConflictsBetween(
|
|
|
502
525
|
function findConflict(
|
|
503
526
|
context,
|
|
504
527
|
cachedFieldsAndFragmentNames,
|
|
528
|
+
comparedFieldsAndFragmentPairs,
|
|
505
529
|
comparedFragmentPairs,
|
|
506
530
|
parentFieldsAreMutuallyExclusive,
|
|
507
531
|
responseName,
|
|
@@ -571,6 +595,7 @@ function findConflict(
|
|
|
571
595
|
const conflicts = findConflictsBetweenSubSelectionSets(
|
|
572
596
|
context,
|
|
573
597
|
cachedFieldsAndFragmentNames,
|
|
598
|
+
comparedFieldsAndFragmentPairs,
|
|
574
599
|
comparedFragmentPairs,
|
|
575
600
|
areMutuallyExclusive,
|
|
576
601
|
getNamedType(type1),
|
|
@@ -764,42 +789,65 @@ function subfieldConflicts(conflicts, responseName, node1, node2) {
|
|
|
764
789
|
}
|
|
765
790
|
}
|
|
766
791
|
/**
|
|
767
|
-
* A way to keep track of pairs of things
|
|
792
|
+
* A way to keep track of pairs of things where the ordering of the pair
|
|
793
|
+
* matters.
|
|
794
|
+
*
|
|
795
|
+
* Provides a third argument for has/set to allow flagging the pair as
|
|
796
|
+
* weakly or strongly present within the collection.
|
|
768
797
|
*/
|
|
769
798
|
|
|
770
|
-
class
|
|
799
|
+
class OrderedPairSet {
|
|
771
800
|
constructor() {
|
|
772
801
|
this._data = new Map();
|
|
773
802
|
}
|
|
774
803
|
|
|
775
|
-
has(a, b,
|
|
804
|
+
has(a, b, weaklyPresent) {
|
|
776
805
|
var _this$_data$get;
|
|
777
806
|
|
|
778
|
-
const [key1, key2] = a < b ? [a, b] : [b, a];
|
|
779
807
|
const result =
|
|
780
|
-
(_this$_data$get = this._data.get(
|
|
808
|
+
(_this$_data$get = this._data.get(a)) === null ||
|
|
781
809
|
_this$_data$get === void 0
|
|
782
810
|
? void 0
|
|
783
|
-
: _this$_data$get.get(
|
|
811
|
+
: _this$_data$get.get(b);
|
|
784
812
|
|
|
785
813
|
if (result === undefined) {
|
|
786
814
|
return false;
|
|
787
|
-
}
|
|
788
|
-
// we want to know if this PairSet "has" these two with no exclusivity,
|
|
789
|
-
// we have to ensure it was added as such.
|
|
815
|
+
}
|
|
790
816
|
|
|
791
|
-
return
|
|
817
|
+
return weaklyPresent ? true : weaklyPresent === result;
|
|
792
818
|
}
|
|
793
819
|
|
|
794
|
-
add(a, b,
|
|
795
|
-
const
|
|
796
|
-
|
|
797
|
-
const map = this._data.get(key1);
|
|
820
|
+
add(a, b, weaklyPresent) {
|
|
821
|
+
const map = this._data.get(a);
|
|
798
822
|
|
|
799
823
|
if (map === undefined) {
|
|
800
|
-
this._data.set(
|
|
824
|
+
this._data.set(a, new Map([[b, weaklyPresent]]));
|
|
825
|
+
} else {
|
|
826
|
+
map.set(b, weaklyPresent);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* A way to keep track of pairs of similar things when the ordering of the pair
|
|
832
|
+
* does not matter.
|
|
833
|
+
*/
|
|
834
|
+
|
|
835
|
+
class PairSet {
|
|
836
|
+
constructor() {
|
|
837
|
+
this._orderedPairSet = new OrderedPairSet();
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
has(a, b, weaklyPresent) {
|
|
841
|
+
return a < b
|
|
842
|
+
? this._orderedPairSet.has(a, b, weaklyPresent)
|
|
843
|
+
: this._orderedPairSet.has(b, a, weaklyPresent);
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
add(a, b, weaklyPresent) {
|
|
847
|
+
if (a < b) {
|
|
848
|
+
this._orderedPairSet.add(a, b, weaklyPresent);
|
|
801
849
|
} else {
|
|
802
|
-
|
|
850
|
+
this._orderedPairSet.add(b, a, weaklyPresent);
|
|
803
851
|
}
|
|
804
852
|
}
|
|
805
853
|
}
|
|
@@ -48,6 +48,17 @@ function ScalarLeafsRule(context) {
|
|
|
48
48
|
},
|
|
49
49
|
),
|
|
50
50
|
);
|
|
51
|
+
} else if (selectionSet.selections.length === 0) {
|
|
52
|
+
const fieldName = node.name.value;
|
|
53
|
+
const typeStr = (0, _inspect.inspect)(type);
|
|
54
|
+
context.reportError(
|
|
55
|
+
new _GraphQLError.GraphQLError(
|
|
56
|
+
`Field "${fieldName}" of type "${typeStr}" must have at least one field selected.`,
|
|
57
|
+
{
|
|
58
|
+
nodes: node,
|
|
59
|
+
},
|
|
60
|
+
),
|
|
61
|
+
);
|
|
51
62
|
}
|
|
52
63
|
}
|
|
53
64
|
},
|
|
@@ -39,6 +39,17 @@ export function ScalarLeafsRule(context) {
|
|
|
39
39
|
},
|
|
40
40
|
),
|
|
41
41
|
);
|
|
42
|
+
} else if (selectionSet.selections.length === 0) {
|
|
43
|
+
const fieldName = node.name.value;
|
|
44
|
+
const typeStr = inspect(type);
|
|
45
|
+
context.reportError(
|
|
46
|
+
new GraphQLError(
|
|
47
|
+
`Field "${fieldName}" of type "${typeStr}" must have at least one field selected.`,
|
|
48
|
+
{
|
|
49
|
+
nodes: node,
|
|
50
|
+
},
|
|
51
|
+
),
|
|
52
|
+
);
|
|
42
53
|
}
|
|
43
54
|
}
|
|
44
55
|
},
|
package/version.js
CHANGED
|
@@ -10,7 +10,7 @@ exports.versionInfo = exports.version = void 0;
|
|
|
10
10
|
/**
|
|
11
11
|
* A string containing the version of the GraphQL.js library
|
|
12
12
|
*/
|
|
13
|
-
const version = '16.
|
|
13
|
+
const version = '16.10.0';
|
|
14
14
|
/**
|
|
15
15
|
* An object containing the components of the GraphQL.js version string
|
|
16
16
|
*/
|
|
@@ -18,7 +18,7 @@ const version = '16.9.0';
|
|
|
18
18
|
exports.version = version;
|
|
19
19
|
const versionInfo = Object.freeze({
|
|
20
20
|
major: 16,
|
|
21
|
-
minor:
|
|
21
|
+
minor: 10,
|
|
22
22
|
patch: 0,
|
|
23
23
|
preReleaseTag: null,
|
|
24
24
|
});
|
package/version.mjs
CHANGED
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* A string containing the version of the GraphQL.js library
|
|
6
6
|
*/
|
|
7
|
-
export const version = '16.
|
|
7
|
+
export const version = '16.10.0';
|
|
8
8
|
/**
|
|
9
9
|
* An object containing the components of the GraphQL.js version string
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
export const versionInfo = Object.freeze({
|
|
13
13
|
major: 16,
|
|
14
|
-
minor:
|
|
14
|
+
minor: 10,
|
|
15
15
|
patch: 0,
|
|
16
16
|
preReleaseTag: null,
|
|
17
17
|
});
|