graphql 16.11.0 → 16.12.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 +49 -6
- package/execution/execute.js +9 -0
- package/execution/execute.mjs +9 -0
- package/index.d.ts +11 -0
- package/index.js +24 -0
- package/index.mjs +6 -2
- package/language/ast.d.ts +45 -1
- package/language/ast.js +14 -1
- package/language/ast.mjs +14 -1
- package/language/index.d.ts +14 -1
- package/language/index.js +12 -0
- package/language/index.mjs +8 -1
- package/language/kinds.d.ts +6 -0
- package/language/kinds.js +5 -0
- package/language/kinds.mjs +5 -0
- package/language/lexer.d.ts +52 -1
- package/language/lexer.js +10 -0
- package/language/lexer.mjs +17 -4
- package/language/parser.d.ts +30 -3
- package/language/parser.js +129 -13
- package/language/parser.mjs +123 -11
- package/language/predicates.d.ts +4 -0
- package/language/predicates.js +11 -0
- package/language/predicates.mjs +9 -0
- package/language/printer.js +42 -13
- package/language/printer.mjs +42 -13
- package/language/schemaCoordinateLexer.d.ts +43 -0
- package/language/schemaCoordinateLexer.js +171 -0
- package/language/schemaCoordinateLexer.mjs +122 -0
- package/language/tokenKind.d.ts +1 -0
- package/language/tokenKind.js +1 -0
- package/language/tokenKind.mjs +1 -0
- package/package.json +1 -1
- package/utilities/index.d.ts +5 -0
- package/utilities/index.js +14 -0
- package/utilities/index.mjs +5 -0
- package/utilities/resolveSchemaCoordinate.d.ts +80 -0
- package/utilities/resolveSchemaCoordinate.js +260 -0
- package/utilities/resolveSchemaCoordinate.mjs +243 -0
- package/validation/rules/ValuesOfCorrectTypeRule.js +2 -36
- package/validation/rules/ValuesOfCorrectTypeRule.mjs +2 -35
- package/version.js +2 -2
- package/version.mjs +2 -2
package/language/lexer.mjs
CHANGED
|
@@ -3,6 +3,13 @@ import { Token } from './ast.mjs';
|
|
|
3
3
|
import { dedentBlockStringLines } from './blockString.mjs';
|
|
4
4
|
import { isDigit, isNameContinue, isNameStart } from './characterClasses.mjs';
|
|
5
5
|
import { TokenKind } from './tokenKind.mjs';
|
|
6
|
+
/**
|
|
7
|
+
* A Lexer interface which provides common properties and methods required for
|
|
8
|
+
* lexing GraphQL source.
|
|
9
|
+
*
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
|
|
6
13
|
/**
|
|
7
14
|
* Given a Source object, creates a Lexer for that source.
|
|
8
15
|
* A Lexer is a stateful stream generator in that every time
|
|
@@ -11,7 +18,6 @@ import { TokenKind } from './tokenKind.mjs';
|
|
|
11
18
|
* EOF, after which the lexer will repeatedly return the same EOF token
|
|
12
19
|
* whenever called.
|
|
13
20
|
*/
|
|
14
|
-
|
|
15
21
|
export class Lexer {
|
|
16
22
|
/**
|
|
17
23
|
* The previously focused non-ignored token.
|
|
@@ -87,6 +93,7 @@ export function isPunctuatorTokenKind(kind) {
|
|
|
87
93
|
kind === TokenKind.AMP ||
|
|
88
94
|
kind === TokenKind.PAREN_L ||
|
|
89
95
|
kind === TokenKind.PAREN_R ||
|
|
96
|
+
kind === TokenKind.DOT ||
|
|
90
97
|
kind === TokenKind.SPREAD ||
|
|
91
98
|
kind === TokenKind.COLON ||
|
|
92
99
|
kind === TokenKind.EQUALS ||
|
|
@@ -141,9 +148,11 @@ function isTrailingSurrogate(code) {
|
|
|
141
148
|
*
|
|
142
149
|
* Printable ASCII is printed quoted, while other points are printed in Unicode
|
|
143
150
|
* code point form (ie. U+1234).
|
|
151
|
+
*
|
|
152
|
+
* @internal
|
|
144
153
|
*/
|
|
145
154
|
|
|
146
|
-
function printCodePointAt(lexer, location) {
|
|
155
|
+
export function printCodePointAt(lexer, location) {
|
|
147
156
|
const code = lexer.source.body.codePointAt(location);
|
|
148
157
|
|
|
149
158
|
if (code === undefined) {
|
|
@@ -158,9 +167,11 @@ function printCodePointAt(lexer, location) {
|
|
|
158
167
|
}
|
|
159
168
|
/**
|
|
160
169
|
* Create a token with line and column location information.
|
|
170
|
+
*
|
|
171
|
+
* @internal
|
|
161
172
|
*/
|
|
162
173
|
|
|
163
|
-
function createToken(lexer, kind, start, end, value) {
|
|
174
|
+
export function createToken(lexer, kind, start, end, value) {
|
|
164
175
|
const line = lexer.line;
|
|
165
176
|
const col = 1 + start - lexer.lineStart;
|
|
166
177
|
return new Token(kind, start, end, line, col, value);
|
|
@@ -875,9 +886,11 @@ function readBlockString(lexer, start) {
|
|
|
875
886
|
* Name ::
|
|
876
887
|
* - NameStart NameContinue* [lookahead != NameContinue]
|
|
877
888
|
* ```
|
|
889
|
+
*
|
|
890
|
+
* @internal
|
|
878
891
|
*/
|
|
879
892
|
|
|
880
|
-
function readName(lexer, start) {
|
|
893
|
+
export function readName(lexer, start) {
|
|
881
894
|
const body = lexer.source.body;
|
|
882
895
|
const bodyLength = body.length;
|
|
883
896
|
let position = start + 1;
|
package/language/parser.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ import type {
|
|
|
36
36
|
OperationTypeDefinitionNode,
|
|
37
37
|
ScalarTypeDefinitionNode,
|
|
38
38
|
ScalarTypeExtensionNode,
|
|
39
|
+
SchemaCoordinateNode,
|
|
39
40
|
SchemaDefinitionNode,
|
|
40
41
|
SchemaExtensionNode,
|
|
41
42
|
SelectionNode,
|
|
@@ -51,7 +52,7 @@ import type {
|
|
|
51
52
|
VariableNode,
|
|
52
53
|
} from './ast';
|
|
53
54
|
import { Location, OperationTypeNode } from './ast';
|
|
54
|
-
import {
|
|
55
|
+
import type { LexerInterface } from './lexer';
|
|
55
56
|
import { Source } from './source';
|
|
56
57
|
import { TokenKind } from './tokenKind';
|
|
57
58
|
/**
|
|
@@ -88,6 +89,11 @@ export interface ParseOptions {
|
|
|
88
89
|
* ```
|
|
89
90
|
*/
|
|
90
91
|
allowLegacyFragmentVariables?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* You may override the Lexer class used to lex the source; this is used by
|
|
94
|
+
* schema coordinates to introduce a lexer with a restricted syntax.
|
|
95
|
+
*/
|
|
96
|
+
lexer?: LexerInterface | undefined;
|
|
91
97
|
}
|
|
92
98
|
/**
|
|
93
99
|
* Given a GraphQL source, parses it into a Document.
|
|
@@ -133,6 +139,18 @@ export declare function parseType(
|
|
|
133
139
|
source: string | Source,
|
|
134
140
|
options?: ParseOptions | undefined,
|
|
135
141
|
): TypeNode;
|
|
142
|
+
/**
|
|
143
|
+
* Given a string containing a GraphQL Schema Coordinate (ex. `Type.field`),
|
|
144
|
+
* parse the AST for that schema coordinate.
|
|
145
|
+
* Throws GraphQLError if a syntax error is encountered.
|
|
146
|
+
*
|
|
147
|
+
* Consider providing the results to the utility function:
|
|
148
|
+
* resolveASTSchemaCoordinate(). Or calling resolveSchemaCoordinate() directly
|
|
149
|
+
* with an unparsed source.
|
|
150
|
+
*/
|
|
151
|
+
export declare function parseSchemaCoordinate(
|
|
152
|
+
source: string | Source,
|
|
153
|
+
): SchemaCoordinateNode;
|
|
136
154
|
/**
|
|
137
155
|
* This class is exported only to assist people in implementing their own parsers
|
|
138
156
|
* without duplicating too much code and should be used only as last resort for cases
|
|
@@ -145,8 +163,8 @@ export declare function parseType(
|
|
|
145
163
|
* @internal
|
|
146
164
|
*/
|
|
147
165
|
export declare class Parser {
|
|
148
|
-
protected _options: ParseOptions
|
|
149
|
-
protected _lexer:
|
|
166
|
+
protected _options: Omit<ParseOptions, 'lexer'>;
|
|
167
|
+
protected _lexer: LexerInterface;
|
|
150
168
|
protected _tokenCounter: number;
|
|
151
169
|
constructor(source: string | Source, options?: ParseOptions);
|
|
152
170
|
get tokenCount(): number;
|
|
@@ -490,6 +508,15 @@ export declare class Parser {
|
|
|
490
508
|
*/
|
|
491
509
|
parseDirectiveLocations(): Array<NameNode>;
|
|
492
510
|
parseDirectiveLocation(): NameNode;
|
|
511
|
+
/**
|
|
512
|
+
* SchemaCoordinate :
|
|
513
|
+
* - Name
|
|
514
|
+
* - Name . Name
|
|
515
|
+
* - Name . Name ( Name : )
|
|
516
|
+
* - \@ Name
|
|
517
|
+
* - \@ Name ( Name : )
|
|
518
|
+
*/
|
|
519
|
+
parseSchemaCoordinate(): SchemaCoordinateNode;
|
|
493
520
|
/**
|
|
494
521
|
* Returns a node that, if configured to do so, sets a "loc" field as a
|
|
495
522
|
* location object, used to identify the place in the source that created a
|
package/language/parser.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, '__esModule', {
|
|
|
6
6
|
exports.Parser = void 0;
|
|
7
7
|
exports.parse = parse;
|
|
8
8
|
exports.parseConstValue = parseConstValue;
|
|
9
|
+
exports.parseSchemaCoordinate = parseSchemaCoordinate;
|
|
9
10
|
exports.parseType = parseType;
|
|
10
11
|
exports.parseValue = parseValue;
|
|
11
12
|
|
|
@@ -19,6 +20,8 @@ var _kinds = require('./kinds.js');
|
|
|
19
20
|
|
|
20
21
|
var _lexer = require('./lexer.js');
|
|
21
22
|
|
|
23
|
+
var _schemaCoordinateLexer = require('./schemaCoordinateLexer.js');
|
|
24
|
+
|
|
22
25
|
var _source = require('./source.js');
|
|
23
26
|
|
|
24
27
|
var _tokenKind = require('./tokenKind.js');
|
|
@@ -84,6 +87,29 @@ function parseType(source, options) {
|
|
|
84
87
|
parser.expectToken(_tokenKind.TokenKind.EOF);
|
|
85
88
|
return type;
|
|
86
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Given a string containing a GraphQL Schema Coordinate (ex. `Type.field`),
|
|
92
|
+
* parse the AST for that schema coordinate.
|
|
93
|
+
* Throws GraphQLError if a syntax error is encountered.
|
|
94
|
+
*
|
|
95
|
+
* Consider providing the results to the utility function:
|
|
96
|
+
* resolveASTSchemaCoordinate(). Or calling resolveSchemaCoordinate() directly
|
|
97
|
+
* with an unparsed source.
|
|
98
|
+
*/
|
|
99
|
+
|
|
100
|
+
function parseSchemaCoordinate(source) {
|
|
101
|
+
const sourceObj = (0, _source.isSource)(source)
|
|
102
|
+
? source
|
|
103
|
+
: new _source.Source(source);
|
|
104
|
+
const lexer = new _schemaCoordinateLexer.SchemaCoordinateLexer(sourceObj);
|
|
105
|
+
const parser = new Parser(source, {
|
|
106
|
+
lexer,
|
|
107
|
+
});
|
|
108
|
+
parser.expectToken(_tokenKind.TokenKind.SOF);
|
|
109
|
+
const coordinate = parser.parseSchemaCoordinate();
|
|
110
|
+
parser.expectToken(_tokenKind.TokenKind.EOF);
|
|
111
|
+
return coordinate;
|
|
112
|
+
}
|
|
87
113
|
/**
|
|
88
114
|
* This class is exported only to assist people in implementing their own parsers
|
|
89
115
|
* without duplicating too much code and should be used only as last resort for cases
|
|
@@ -98,11 +124,18 @@ function parseType(source, options) {
|
|
|
98
124
|
|
|
99
125
|
class Parser {
|
|
100
126
|
constructor(source, options = {}) {
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
127
|
+
const { lexer, ..._options } = options;
|
|
128
|
+
|
|
129
|
+
if (lexer) {
|
|
130
|
+
this._lexer = lexer;
|
|
131
|
+
} else {
|
|
132
|
+
const sourceObj = (0, _source.isSource)(source)
|
|
133
|
+
? source
|
|
134
|
+
: new _source.Source(source);
|
|
135
|
+
this._lexer = new _lexer.Lexer(sourceObj);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
this._options = _options;
|
|
106
139
|
this._tokenCounter = 0;
|
|
107
140
|
}
|
|
108
141
|
|
|
@@ -169,6 +202,14 @@ class Parser {
|
|
|
169
202
|
? this._lexer.lookahead()
|
|
170
203
|
: this._lexer.token;
|
|
171
204
|
|
|
205
|
+
if (hasDescription && keywordToken.kind === _tokenKind.TokenKind.BRACE_L) {
|
|
206
|
+
throw (0, _syntaxError.syntaxError)(
|
|
207
|
+
this._lexer.source,
|
|
208
|
+
this._lexer.token.start,
|
|
209
|
+
'Unexpected description, descriptions are not supported on shorthand queries.',
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
172
213
|
if (keywordToken.kind === _tokenKind.TokenKind.NAME) {
|
|
173
214
|
switch (keywordToken.value) {
|
|
174
215
|
case 'schema':
|
|
@@ -196,14 +237,6 @@ class Parser {
|
|
|
196
237
|
return this.parseDirectiveDefinition();
|
|
197
238
|
}
|
|
198
239
|
|
|
199
|
-
if (hasDescription) {
|
|
200
|
-
throw (0, _syntaxError.syntaxError)(
|
|
201
|
-
this._lexer.source,
|
|
202
|
-
this._lexer.token.start,
|
|
203
|
-
'Unexpected description, descriptions are supported only on type definitions.',
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
240
|
switch (keywordToken.value) {
|
|
208
241
|
case 'query':
|
|
209
242
|
case 'mutation':
|
|
@@ -212,7 +245,17 @@ class Parser {
|
|
|
212
245
|
|
|
213
246
|
case 'fragment':
|
|
214
247
|
return this.parseFragmentDefinition();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (hasDescription) {
|
|
251
|
+
throw (0, _syntaxError.syntaxError)(
|
|
252
|
+
this._lexer.source,
|
|
253
|
+
this._lexer.token.start,
|
|
254
|
+
'Unexpected description, only GraphQL definitions support descriptions.',
|
|
255
|
+
);
|
|
256
|
+
}
|
|
215
257
|
|
|
258
|
+
switch (keywordToken.value) {
|
|
216
259
|
case 'extend':
|
|
217
260
|
return this.parseTypeSystemExtension();
|
|
218
261
|
}
|
|
@@ -234,6 +277,7 @@ class Parser {
|
|
|
234
277
|
return this.node(start, {
|
|
235
278
|
kind: _kinds.Kind.OPERATION_DEFINITION,
|
|
236
279
|
operation: _ast.OperationTypeNode.QUERY,
|
|
280
|
+
description: undefined,
|
|
237
281
|
name: undefined,
|
|
238
282
|
variableDefinitions: [],
|
|
239
283
|
directives: [],
|
|
@@ -241,6 +285,7 @@ class Parser {
|
|
|
241
285
|
});
|
|
242
286
|
}
|
|
243
287
|
|
|
288
|
+
const description = this.parseDescription();
|
|
244
289
|
const operation = this.parseOperationType();
|
|
245
290
|
let name;
|
|
246
291
|
|
|
@@ -251,6 +296,7 @@ class Parser {
|
|
|
251
296
|
return this.node(start, {
|
|
252
297
|
kind: _kinds.Kind.OPERATION_DEFINITION,
|
|
253
298
|
operation,
|
|
299
|
+
description,
|
|
254
300
|
name,
|
|
255
301
|
variableDefinitions: this.parseVariableDefinitions(),
|
|
256
302
|
directives: this.parseDirectives(false),
|
|
@@ -295,6 +341,7 @@ class Parser {
|
|
|
295
341
|
parseVariableDefinition() {
|
|
296
342
|
return this.node(this._lexer.token, {
|
|
297
343
|
kind: _kinds.Kind.VARIABLE_DEFINITION,
|
|
344
|
+
description: this.parseDescription(),
|
|
298
345
|
variable: this.parseVariable(),
|
|
299
346
|
type:
|
|
300
347
|
(this.expectToken(_tokenKind.TokenKind.COLON),
|
|
@@ -443,6 +490,7 @@ class Parser {
|
|
|
443
490
|
|
|
444
491
|
parseFragmentDefinition() {
|
|
445
492
|
const start = this._lexer.token;
|
|
493
|
+
const description = this.parseDescription();
|
|
446
494
|
this.expectKeyword('fragment'); // Legacy support for defining variables within fragments changes
|
|
447
495
|
// the grammar of FragmentDefinition:
|
|
448
496
|
// - fragment FragmentName VariableDefinitions? on TypeCondition Directives? SelectionSet
|
|
@@ -450,6 +498,7 @@ class Parser {
|
|
|
450
498
|
if (this._options.allowLegacyFragmentVariables === true) {
|
|
451
499
|
return this.node(start, {
|
|
452
500
|
kind: _kinds.Kind.FRAGMENT_DEFINITION,
|
|
501
|
+
description,
|
|
453
502
|
name: this.parseFragmentName(),
|
|
454
503
|
variableDefinitions: this.parseVariableDefinitions(),
|
|
455
504
|
typeCondition: (this.expectKeyword('on'), this.parseNamedType()),
|
|
@@ -460,6 +509,7 @@ class Parser {
|
|
|
460
509
|
|
|
461
510
|
return this.node(start, {
|
|
462
511
|
kind: _kinds.Kind.FRAGMENT_DEFINITION,
|
|
512
|
+
description,
|
|
463
513
|
name: this.parseFragmentName(),
|
|
464
514
|
typeCondition: (this.expectKeyword('on'), this.parseNamedType()),
|
|
465
515
|
directives: this.parseDirectives(false),
|
|
@@ -1364,6 +1414,72 @@ class Parser {
|
|
|
1364
1414
|
}
|
|
1365
1415
|
|
|
1366
1416
|
throw this.unexpected(start);
|
|
1417
|
+
} // Schema Coordinates
|
|
1418
|
+
|
|
1419
|
+
/**
|
|
1420
|
+
* SchemaCoordinate :
|
|
1421
|
+
* - Name
|
|
1422
|
+
* - Name . Name
|
|
1423
|
+
* - Name . Name ( Name : )
|
|
1424
|
+
* - \@ Name
|
|
1425
|
+
* - \@ Name ( Name : )
|
|
1426
|
+
*/
|
|
1427
|
+
|
|
1428
|
+
parseSchemaCoordinate() {
|
|
1429
|
+
const start = this._lexer.token;
|
|
1430
|
+
const ofDirective = this.expectOptionalToken(_tokenKind.TokenKind.AT);
|
|
1431
|
+
const name = this.parseName();
|
|
1432
|
+
let memberName;
|
|
1433
|
+
|
|
1434
|
+
if (!ofDirective && this.expectOptionalToken(_tokenKind.TokenKind.DOT)) {
|
|
1435
|
+
memberName = this.parseName();
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
let argumentName;
|
|
1439
|
+
|
|
1440
|
+
if (
|
|
1441
|
+
(ofDirective || memberName) &&
|
|
1442
|
+
this.expectOptionalToken(_tokenKind.TokenKind.PAREN_L)
|
|
1443
|
+
) {
|
|
1444
|
+
argumentName = this.parseName();
|
|
1445
|
+
this.expectToken(_tokenKind.TokenKind.COLON);
|
|
1446
|
+
this.expectToken(_tokenKind.TokenKind.PAREN_R);
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
if (ofDirective) {
|
|
1450
|
+
if (argumentName) {
|
|
1451
|
+
return this.node(start, {
|
|
1452
|
+
kind: _kinds.Kind.DIRECTIVE_ARGUMENT_COORDINATE,
|
|
1453
|
+
name,
|
|
1454
|
+
argumentName,
|
|
1455
|
+
});
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
return this.node(start, {
|
|
1459
|
+
kind: _kinds.Kind.DIRECTIVE_COORDINATE,
|
|
1460
|
+
name,
|
|
1461
|
+
});
|
|
1462
|
+
} else if (memberName) {
|
|
1463
|
+
if (argumentName) {
|
|
1464
|
+
return this.node(start, {
|
|
1465
|
+
kind: _kinds.Kind.ARGUMENT_COORDINATE,
|
|
1466
|
+
name,
|
|
1467
|
+
fieldName: memberName,
|
|
1468
|
+
argumentName,
|
|
1469
|
+
});
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
return this.node(start, {
|
|
1473
|
+
kind: _kinds.Kind.MEMBER_COORDINATE,
|
|
1474
|
+
name,
|
|
1475
|
+
memberName,
|
|
1476
|
+
});
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
return this.node(start, {
|
|
1480
|
+
kind: _kinds.Kind.TYPE_COORDINATE,
|
|
1481
|
+
name,
|
|
1482
|
+
});
|
|
1367
1483
|
} // Core parsing utility functions
|
|
1368
1484
|
|
|
1369
1485
|
/**
|
package/language/parser.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import { Location, OperationTypeNode } from './ast.mjs';
|
|
|
3
3
|
import { DirectiveLocation } from './directiveLocation.mjs';
|
|
4
4
|
import { Kind } from './kinds.mjs';
|
|
5
5
|
import { isPunctuatorTokenKind, Lexer } from './lexer.mjs';
|
|
6
|
+
import { SchemaCoordinateLexer } from './schemaCoordinateLexer.mjs';
|
|
6
7
|
import { isSource, Source } from './source.mjs';
|
|
7
8
|
import { TokenKind } from './tokenKind.mjs';
|
|
8
9
|
/**
|
|
@@ -70,6 +71,27 @@ export function parseType(source, options) {
|
|
|
70
71
|
parser.expectToken(TokenKind.EOF);
|
|
71
72
|
return type;
|
|
72
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Given a string containing a GraphQL Schema Coordinate (ex. `Type.field`),
|
|
76
|
+
* parse the AST for that schema coordinate.
|
|
77
|
+
* Throws GraphQLError if a syntax error is encountered.
|
|
78
|
+
*
|
|
79
|
+
* Consider providing the results to the utility function:
|
|
80
|
+
* resolveASTSchemaCoordinate(). Or calling resolveSchemaCoordinate() directly
|
|
81
|
+
* with an unparsed source.
|
|
82
|
+
*/
|
|
83
|
+
|
|
84
|
+
export function parseSchemaCoordinate(source) {
|
|
85
|
+
const sourceObj = isSource(source) ? source : new Source(source);
|
|
86
|
+
const lexer = new SchemaCoordinateLexer(sourceObj);
|
|
87
|
+
const parser = new Parser(source, {
|
|
88
|
+
lexer,
|
|
89
|
+
});
|
|
90
|
+
parser.expectToken(TokenKind.SOF);
|
|
91
|
+
const coordinate = parser.parseSchemaCoordinate();
|
|
92
|
+
parser.expectToken(TokenKind.EOF);
|
|
93
|
+
return coordinate;
|
|
94
|
+
}
|
|
73
95
|
/**
|
|
74
96
|
* This class is exported only to assist people in implementing their own parsers
|
|
75
97
|
* without duplicating too much code and should be used only as last resort for cases
|
|
@@ -84,9 +106,16 @@ export function parseType(source, options) {
|
|
|
84
106
|
|
|
85
107
|
export class Parser {
|
|
86
108
|
constructor(source, options = {}) {
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
109
|
+
const { lexer, ..._options } = options;
|
|
110
|
+
|
|
111
|
+
if (lexer) {
|
|
112
|
+
this._lexer = lexer;
|
|
113
|
+
} else {
|
|
114
|
+
const sourceObj = isSource(source) ? source : new Source(source);
|
|
115
|
+
this._lexer = new Lexer(sourceObj);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
this._options = _options;
|
|
90
119
|
this._tokenCounter = 0;
|
|
91
120
|
}
|
|
92
121
|
|
|
@@ -153,6 +182,14 @@ export class Parser {
|
|
|
153
182
|
? this._lexer.lookahead()
|
|
154
183
|
: this._lexer.token;
|
|
155
184
|
|
|
185
|
+
if (hasDescription && keywordToken.kind === TokenKind.BRACE_L) {
|
|
186
|
+
throw syntaxError(
|
|
187
|
+
this._lexer.source,
|
|
188
|
+
this._lexer.token.start,
|
|
189
|
+
'Unexpected description, descriptions are not supported on shorthand queries.',
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
156
193
|
if (keywordToken.kind === TokenKind.NAME) {
|
|
157
194
|
switch (keywordToken.value) {
|
|
158
195
|
case 'schema':
|
|
@@ -180,14 +217,6 @@ export class Parser {
|
|
|
180
217
|
return this.parseDirectiveDefinition();
|
|
181
218
|
}
|
|
182
219
|
|
|
183
|
-
if (hasDescription) {
|
|
184
|
-
throw syntaxError(
|
|
185
|
-
this._lexer.source,
|
|
186
|
-
this._lexer.token.start,
|
|
187
|
-
'Unexpected description, descriptions are supported only on type definitions.',
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
220
|
switch (keywordToken.value) {
|
|
192
221
|
case 'query':
|
|
193
222
|
case 'mutation':
|
|
@@ -196,7 +225,17 @@ export class Parser {
|
|
|
196
225
|
|
|
197
226
|
case 'fragment':
|
|
198
227
|
return this.parseFragmentDefinition();
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (hasDescription) {
|
|
231
|
+
throw syntaxError(
|
|
232
|
+
this._lexer.source,
|
|
233
|
+
this._lexer.token.start,
|
|
234
|
+
'Unexpected description, only GraphQL definitions support descriptions.',
|
|
235
|
+
);
|
|
236
|
+
}
|
|
199
237
|
|
|
238
|
+
switch (keywordToken.value) {
|
|
200
239
|
case 'extend':
|
|
201
240
|
return this.parseTypeSystemExtension();
|
|
202
241
|
}
|
|
@@ -218,6 +257,7 @@ export class Parser {
|
|
|
218
257
|
return this.node(start, {
|
|
219
258
|
kind: Kind.OPERATION_DEFINITION,
|
|
220
259
|
operation: OperationTypeNode.QUERY,
|
|
260
|
+
description: undefined,
|
|
221
261
|
name: undefined,
|
|
222
262
|
variableDefinitions: [],
|
|
223
263
|
directives: [],
|
|
@@ -225,6 +265,7 @@ export class Parser {
|
|
|
225
265
|
});
|
|
226
266
|
}
|
|
227
267
|
|
|
268
|
+
const description = this.parseDescription();
|
|
228
269
|
const operation = this.parseOperationType();
|
|
229
270
|
let name;
|
|
230
271
|
|
|
@@ -235,6 +276,7 @@ export class Parser {
|
|
|
235
276
|
return this.node(start, {
|
|
236
277
|
kind: Kind.OPERATION_DEFINITION,
|
|
237
278
|
operation,
|
|
279
|
+
description,
|
|
238
280
|
name,
|
|
239
281
|
variableDefinitions: this.parseVariableDefinitions(),
|
|
240
282
|
directives: this.parseDirectives(false),
|
|
@@ -279,6 +321,7 @@ export class Parser {
|
|
|
279
321
|
parseVariableDefinition() {
|
|
280
322
|
return this.node(this._lexer.token, {
|
|
281
323
|
kind: Kind.VARIABLE_DEFINITION,
|
|
324
|
+
description: this.parseDescription(),
|
|
282
325
|
variable: this.parseVariable(),
|
|
283
326
|
type: (this.expectToken(TokenKind.COLON), this.parseTypeReference()),
|
|
284
327
|
defaultValue: this.expectOptionalToken(TokenKind.EQUALS)
|
|
@@ -421,6 +464,7 @@ export class Parser {
|
|
|
421
464
|
|
|
422
465
|
parseFragmentDefinition() {
|
|
423
466
|
const start = this._lexer.token;
|
|
467
|
+
const description = this.parseDescription();
|
|
424
468
|
this.expectKeyword('fragment'); // Legacy support for defining variables within fragments changes
|
|
425
469
|
// the grammar of FragmentDefinition:
|
|
426
470
|
// - fragment FragmentName VariableDefinitions? on TypeCondition Directives? SelectionSet
|
|
@@ -428,6 +472,7 @@ export class Parser {
|
|
|
428
472
|
if (this._options.allowLegacyFragmentVariables === true) {
|
|
429
473
|
return this.node(start, {
|
|
430
474
|
kind: Kind.FRAGMENT_DEFINITION,
|
|
475
|
+
description,
|
|
431
476
|
name: this.parseFragmentName(),
|
|
432
477
|
variableDefinitions: this.parseVariableDefinitions(),
|
|
433
478
|
typeCondition: (this.expectKeyword('on'), this.parseNamedType()),
|
|
@@ -438,6 +483,7 @@ export class Parser {
|
|
|
438
483
|
|
|
439
484
|
return this.node(start, {
|
|
440
485
|
kind: Kind.FRAGMENT_DEFINITION,
|
|
486
|
+
description,
|
|
441
487
|
name: this.parseFragmentName(),
|
|
442
488
|
typeCondition: (this.expectKeyword('on'), this.parseNamedType()),
|
|
443
489
|
directives: this.parseDirectives(false),
|
|
@@ -1323,6 +1369,72 @@ export class Parser {
|
|
|
1323
1369
|
}
|
|
1324
1370
|
|
|
1325
1371
|
throw this.unexpected(start);
|
|
1372
|
+
} // Schema Coordinates
|
|
1373
|
+
|
|
1374
|
+
/**
|
|
1375
|
+
* SchemaCoordinate :
|
|
1376
|
+
* - Name
|
|
1377
|
+
* - Name . Name
|
|
1378
|
+
* - Name . Name ( Name : )
|
|
1379
|
+
* - \@ Name
|
|
1380
|
+
* - \@ Name ( Name : )
|
|
1381
|
+
*/
|
|
1382
|
+
|
|
1383
|
+
parseSchemaCoordinate() {
|
|
1384
|
+
const start = this._lexer.token;
|
|
1385
|
+
const ofDirective = this.expectOptionalToken(TokenKind.AT);
|
|
1386
|
+
const name = this.parseName();
|
|
1387
|
+
let memberName;
|
|
1388
|
+
|
|
1389
|
+
if (!ofDirective && this.expectOptionalToken(TokenKind.DOT)) {
|
|
1390
|
+
memberName = this.parseName();
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
let argumentName;
|
|
1394
|
+
|
|
1395
|
+
if (
|
|
1396
|
+
(ofDirective || memberName) &&
|
|
1397
|
+
this.expectOptionalToken(TokenKind.PAREN_L)
|
|
1398
|
+
) {
|
|
1399
|
+
argumentName = this.parseName();
|
|
1400
|
+
this.expectToken(TokenKind.COLON);
|
|
1401
|
+
this.expectToken(TokenKind.PAREN_R);
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
if (ofDirective) {
|
|
1405
|
+
if (argumentName) {
|
|
1406
|
+
return this.node(start, {
|
|
1407
|
+
kind: Kind.DIRECTIVE_ARGUMENT_COORDINATE,
|
|
1408
|
+
name,
|
|
1409
|
+
argumentName,
|
|
1410
|
+
});
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
return this.node(start, {
|
|
1414
|
+
kind: Kind.DIRECTIVE_COORDINATE,
|
|
1415
|
+
name,
|
|
1416
|
+
});
|
|
1417
|
+
} else if (memberName) {
|
|
1418
|
+
if (argumentName) {
|
|
1419
|
+
return this.node(start, {
|
|
1420
|
+
kind: Kind.ARGUMENT_COORDINATE,
|
|
1421
|
+
name,
|
|
1422
|
+
fieldName: memberName,
|
|
1423
|
+
argumentName,
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
return this.node(start, {
|
|
1428
|
+
kind: Kind.MEMBER_COORDINATE,
|
|
1429
|
+
name,
|
|
1430
|
+
memberName,
|
|
1431
|
+
});
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
return this.node(start, {
|
|
1435
|
+
kind: Kind.TYPE_COORDINATE,
|
|
1436
|
+
name,
|
|
1437
|
+
});
|
|
1326
1438
|
} // Core parsing utility functions
|
|
1327
1439
|
|
|
1328
1440
|
/**
|
package/language/predicates.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
ConstValueNode,
|
|
4
4
|
DefinitionNode,
|
|
5
5
|
ExecutableDefinitionNode,
|
|
6
|
+
SchemaCoordinateNode,
|
|
6
7
|
SelectionNode,
|
|
7
8
|
TypeDefinitionNode,
|
|
8
9
|
TypeExtensionNode,
|
|
@@ -31,3 +32,6 @@ export declare function isTypeSystemExtensionNode(
|
|
|
31
32
|
export declare function isTypeExtensionNode(
|
|
32
33
|
node: ASTNode,
|
|
33
34
|
): node is TypeExtensionNode;
|
|
35
|
+
export declare function isSchemaCoordinateNode(
|
|
36
|
+
node: ASTNode,
|
|
37
|
+
): node is SchemaCoordinateNode;
|
package/language/predicates.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, '__esModule', {
|
|
|
6
6
|
exports.isConstValueNode = isConstValueNode;
|
|
7
7
|
exports.isDefinitionNode = isDefinitionNode;
|
|
8
8
|
exports.isExecutableDefinitionNode = isExecutableDefinitionNode;
|
|
9
|
+
exports.isSchemaCoordinateNode = isSchemaCoordinateNode;
|
|
9
10
|
exports.isSelectionNode = isSelectionNode;
|
|
10
11
|
exports.isTypeDefinitionNode = isTypeDefinitionNode;
|
|
11
12
|
exports.isTypeExtensionNode = isTypeExtensionNode;
|
|
@@ -107,3 +108,13 @@ function isTypeExtensionNode(node) {
|
|
|
107
108
|
node.kind === _kinds.Kind.INPUT_OBJECT_TYPE_EXTENSION
|
|
108
109
|
);
|
|
109
110
|
}
|
|
111
|
+
|
|
112
|
+
function isSchemaCoordinateNode(node) {
|
|
113
|
+
return (
|
|
114
|
+
node.kind === _kinds.Kind.TYPE_COORDINATE ||
|
|
115
|
+
node.kind === _kinds.Kind.MEMBER_COORDINATE ||
|
|
116
|
+
node.kind === _kinds.Kind.ARGUMENT_COORDINATE ||
|
|
117
|
+
node.kind === _kinds.Kind.DIRECTIVE_COORDINATE ||
|
|
118
|
+
node.kind === _kinds.Kind.DIRECTIVE_ARGUMENT_COORDINATE
|
|
119
|
+
);
|
|
120
|
+
}
|
package/language/predicates.mjs
CHANGED
|
@@ -79,3 +79,12 @@ export function isTypeExtensionNode(node) {
|
|
|
79
79
|
node.kind === Kind.INPUT_OBJECT_TYPE_EXTENSION
|
|
80
80
|
);
|
|
81
81
|
}
|
|
82
|
+
export function isSchemaCoordinateNode(node) {
|
|
83
|
+
return (
|
|
84
|
+
node.kind === Kind.TYPE_COORDINATE ||
|
|
85
|
+
node.kind === Kind.MEMBER_COORDINATE ||
|
|
86
|
+
node.kind === Kind.ARGUMENT_COORDINATE ||
|
|
87
|
+
node.kind === Kind.DIRECTIVE_COORDINATE ||
|
|
88
|
+
node.kind === Kind.DIRECTIVE_ARGUMENT_COORDINATE
|
|
89
|
+
);
|
|
90
|
+
}
|