@0no-co/graphql.web 0.1.0 → 0.1.1

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/src/parser.ts DELETED
@@ -1,480 +0,0 @@
1
- /**
2
- * This is a spec-compliant implementation of a GraphQL query language parser,
3
- * up-to-date with the October 2021 Edition. Unlike the reference implementation
4
- * in graphql.js it will only parse the query language, but not the schema
5
- * language.
6
- */
7
- import { Kind } from './kind';
8
- import { GraphQLError } from './error';
9
- import type * as ast from './ast';
10
-
11
- let input: string;
12
- let idx: number;
13
-
14
- function error(kind: Kind) {
15
- return new GraphQLError(`Syntax Error: Unexpected token at ${idx} in ${kind}`);
16
- }
17
-
18
- function advance(pattern: RegExp) {
19
- pattern.lastIndex = idx;
20
- if (pattern.test(input)) {
21
- const match = input.slice(idx, idx = pattern.lastIndex);
22
- return match;
23
- }
24
- }
25
-
26
- const leadingRe = / +(?=[^\s])/y;
27
- export function blockString(string: string) {
28
- let out = '';
29
- let commonIndent = 0;
30
- let firstNonEmptyLine = 0;
31
- let lastNonEmptyLine = -1;
32
- const lines = string.split('\n');
33
- for (let i = 0; i < lines.length; i++) {
34
- leadingRe.lastIndex = 0;
35
- if (leadingRe.test(lines[i])) {
36
- if (i && (!commonIndent || leadingRe.lastIndex < commonIndent))
37
- commonIndent = leadingRe.lastIndex;
38
- firstNonEmptyLine = firstNonEmptyLine || i;
39
- lastNonEmptyLine = i;
40
- }
41
- }
42
- for (let i = firstNonEmptyLine; i <= lastNonEmptyLine; i++) {
43
- if (i !== firstNonEmptyLine) out += '\n';
44
- out += lines[i].slice(commonIndent);
45
- }
46
- return out;
47
- }
48
-
49
- const ignoredRe = /(?:[\s,]*|#[^\n\r]*)*/y;
50
- function ignored() {
51
- ignoredRe.lastIndex = idx;
52
- ignoredRe.test(input);
53
- idx = ignoredRe.lastIndex;
54
- }
55
-
56
- const nameRe = /[_\w][_\d\w]*/y;
57
- function name(): ast.NameNode | undefined {
58
- let match: string | undefined;
59
- if (match = advance(nameRe)) {
60
- return {
61
- kind: Kind.NAME,
62
- value: match,
63
- };
64
- }
65
- }
66
-
67
- const nullRe = /null/y;
68
- const boolRe = /true|false/y;
69
- const variableRe = /\$[_\w][_\d\w]*/y;
70
- const intRe = /[-]?\d+/y;
71
- const floatRe = /[-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/y;
72
- const complexStringRe = /\\/g;
73
- const blockStringRe = /"""(?:[\s\S]+(?="""))?"""/y;
74
- const stringRe = /"(?:[^"\r\n]+)?"/y;
75
-
76
- function value(constant: true): ast.ConstValueNode;
77
- function value(constant: boolean): ast.ValueNode;
78
-
79
- function value(constant: boolean): ast.ValueNode | undefined {
80
- let out: ast.ValueNode | undefined;
81
- let match: string | undefined;
82
- if (advance(nullRe)) {
83
- out = { kind: Kind.NULL };
84
- } else if (match = advance(boolRe)) {
85
- out = {
86
- kind: Kind.BOOLEAN,
87
- value: match === 'true',
88
- };
89
- } else if (!constant && (match = advance(variableRe))) {
90
- out = {
91
- kind: Kind.VARIABLE,
92
- name: {
93
- kind: Kind.NAME,
94
- value: match.slice(1),
95
- },
96
- };
97
- } else if (match = advance(floatRe)) {
98
- out = {
99
- kind: Kind.FLOAT,
100
- value: match,
101
- };
102
- } else if (match = advance(intRe)) {
103
- out = {
104
- kind: Kind.INT,
105
- value: match,
106
- };
107
- } else if (match = advance(nameRe)) {
108
- out = {
109
- kind: Kind.ENUM,
110
- value: match,
111
- };
112
- } else if (match = advance(blockStringRe)) {
113
- out = {
114
- kind: Kind.STRING,
115
- value: blockString(match.slice(3, -3)),
116
- block: true,
117
- };
118
- } else if (match = advance(stringRe)) {
119
- out = {
120
- kind: Kind.STRING,
121
- value: complexStringRe.test(match)
122
- ? JSON.parse(match) as string
123
- : match.slice(1, -1),
124
- block: false,
125
- };
126
- } else if (out = list(constant) || object(constant)) {
127
- return out;
128
- }
129
-
130
- ignored();
131
- return out;
132
- }
133
-
134
- function list(constant: boolean): ast.ListValueNode | undefined {
135
- let match: ast.ValueNode | undefined;
136
- if (input.charCodeAt(idx) === 91 /*'['*/) {
137
- idx++;
138
- ignored();
139
- const values: ast.ValueNode[] = [];
140
- while (match = value(constant))
141
- values.push(match);
142
- if (input.charCodeAt(idx++) !== 93 /*']'*/)
143
- throw error(Kind.LIST);
144
- ignored();
145
- return {
146
- kind: Kind.LIST,
147
- values,
148
- };
149
- }
150
- }
151
-
152
- function object(constant: boolean): ast.ObjectValueNode | undefined {
153
- if (input.charCodeAt(idx) === 123 /*'{'*/) {
154
- idx++;
155
- ignored();
156
- const fields: ast.ObjectFieldNode[] = [];
157
- let _name: ast.NameNode | undefined;
158
- while (_name = name()) {
159
- ignored();
160
- if (input.charCodeAt(idx++) !== 58 /*':'*/)
161
- throw error(Kind.OBJECT_FIELD);
162
- ignored();
163
- const _value = value(constant);
164
- if (!_value)
165
- throw error(Kind.OBJECT_FIELD);
166
- fields.push({
167
- kind: Kind.OBJECT_FIELD,
168
- name: _name,
169
- value: _value,
170
- });
171
- }
172
- if (input.charCodeAt(idx++) !== 125 /*'}'*/)
173
- throw error(Kind.OBJECT);
174
- ignored();
175
- return {
176
- kind: Kind.OBJECT,
177
- fields,
178
- };
179
- }
180
- }
181
-
182
- function arguments_(constant: boolean): ast.ArgumentNode[] {
183
- const args: ast.ArgumentNode[] = [];
184
- ignored();
185
- if (input.charCodeAt(idx) === 40 /*'('*/) {
186
- idx++;
187
- ignored();
188
- let _name: ast.NameNode | undefined;
189
- while (_name = name()) {
190
- ignored();
191
- if (input.charCodeAt(idx++) !== 58 /*':'*/)
192
- throw error(Kind.ARGUMENT);
193
- ignored();
194
- const _value = value(constant);
195
- if (!_value)
196
- throw error(Kind.ARGUMENT);
197
- args.push({
198
- kind: Kind.ARGUMENT,
199
- name: _name,
200
- value: _value,
201
- });
202
- }
203
- if (!args.length || input.charCodeAt(idx++) !== 41 /*')'*/)
204
- throw error(Kind.ARGUMENT);
205
- ignored();
206
- }
207
- return args;
208
- }
209
-
210
- function directives(constant: true): ast.ConstDirectiveNode[];
211
- function directives(constant: boolean): ast.DirectiveNode[];
212
-
213
- function directives(constant: boolean): ast.DirectiveNode[] {
214
- const directives: ast.DirectiveNode[] = [];
215
- ignored();
216
- while (input.charCodeAt(idx) === 64 /*'@'*/) {
217
- idx++;
218
- const _name = name();
219
- if (!_name)
220
- throw error(Kind.DIRECTIVE);
221
- ignored();
222
- directives.push({
223
- kind: Kind.DIRECTIVE,
224
- name: _name,
225
- arguments: arguments_(constant),
226
- });
227
- }
228
- return directives;
229
- }
230
-
231
- function field(): ast.FieldNode | undefined {
232
- ignored();
233
- let _name = name();
234
- if (_name) {
235
- ignored();
236
- let _alias: ast.NameNode | undefined;
237
- if (input.charCodeAt(idx) === 58 /*':'*/) {
238
- idx++;
239
- ignored();
240
- _alias = _name;
241
- _name = name();
242
- if (!_name)
243
- throw error(Kind.FIELD);
244
- ignored();
245
- }
246
- return {
247
- kind: Kind.FIELD,
248
- alias: _alias,
249
- name: _name,
250
- arguments: arguments_(false),
251
- directives: directives(false),
252
- selectionSet: selectionSet(),
253
- };
254
- }
255
- }
256
-
257
- function type(): ast.TypeNode | undefined {
258
- let match: ast.NameNode | ast.TypeNode | undefined;
259
- ignored();
260
- if (input.charCodeAt(idx) === 91 /*'['*/) {
261
- idx++;
262
- ignored();
263
- const _type = type();
264
- if (!_type || input.charCodeAt(idx++) !== 93 /*']'*/)
265
- throw error(Kind.LIST_TYPE);
266
- match = {
267
- kind: Kind.LIST_TYPE,
268
- type: _type,
269
- };
270
- } else if (match = name()) {
271
- match = {
272
- kind: Kind.NAMED_TYPE,
273
- name: match,
274
- };
275
- } else {
276
- throw error(Kind.NAMED_TYPE);
277
- }
278
-
279
- ignored();
280
- if (input.charCodeAt(idx) === 33 /*'!'*/) {
281
- idx++;
282
- ignored();
283
- return {
284
- kind: Kind.NON_NULL_TYPE,
285
- type: match,
286
- };
287
- } else {
288
- return match;
289
- }
290
- }
291
-
292
- const typeConditionRe = /on/y;
293
- function typeCondition(): ast.NamedTypeNode | undefined {
294
- if (advance(typeConditionRe)) {
295
- ignored();
296
- const _name = name();
297
- if (!_name)
298
- throw error(Kind.NAMED_TYPE);
299
- ignored();
300
- return {
301
- kind: Kind.NAMED_TYPE,
302
- name: _name,
303
- };
304
- }
305
- }
306
-
307
- const fragmentSpreadRe = /\.\.\./y;
308
-
309
- function fragmentSpread(): ast.FragmentSpreadNode | ast.InlineFragmentNode | undefined {
310
- ignored();
311
- if (advance(fragmentSpreadRe)) {
312
- ignored();
313
- let _name: ast.NameNode | undefined;
314
- if (_name = name()) {
315
- return {
316
- kind: Kind.FRAGMENT_SPREAD,
317
- name: _name,
318
- directives: directives(false),
319
- };
320
- } else {
321
- const _typeCondition = typeCondition();
322
- const _directives = directives(false);
323
- const _selectionSet = selectionSet();
324
- if (!_selectionSet)
325
- throw error(Kind.INLINE_FRAGMENT);
326
- return {
327
- kind: Kind.INLINE_FRAGMENT,
328
- typeCondition: _typeCondition,
329
- directives: _directives,
330
- selectionSet: _selectionSet,
331
- };
332
- }
333
- }
334
- }
335
-
336
- function selectionSet(): ast.SelectionSetNode | undefined {
337
- let match: ast.SelectionNode | undefined;
338
- ignored();
339
- if (input.charCodeAt(idx) === 123 /*'{'*/) {
340
- idx++;
341
- ignored();
342
- const selections: ast.SelectionNode[] = [];
343
- while (match = fragmentSpread() || field())
344
- selections.push(match);
345
- if (!selections.length || input.charCodeAt(idx++) !== 125 /*'}'*/)
346
- throw error(Kind.SELECTION_SET);
347
- ignored();
348
- return {
349
- kind: Kind.SELECTION_SET,
350
- selections,
351
- };
352
- }
353
- }
354
-
355
- function variableDefinitions(): ast.VariableDefinitionNode[] {
356
- let match: string | undefined;
357
- const vars: ast.VariableDefinitionNode[] = [];
358
- ignored();
359
- if (input.charCodeAt(idx) === 40 /*'('*/) {
360
- idx++;
361
- ignored();
362
- while (match = advance(variableRe)) {
363
- ignored();
364
- if (input.charCodeAt(idx++) !== 58 /*':'*/)
365
- throw error(Kind.VARIABLE_DEFINITION);
366
- const _type = type();
367
- if (!_type)
368
- throw error(Kind.VARIABLE_DEFINITION);
369
- let _defaultValue: ast.ValueNode | undefined;
370
- if (input.charCodeAt(idx) === 61 /*'='*/) {
371
- idx++;
372
- ignored();
373
- _defaultValue = value(true);
374
- if (!_defaultValue)
375
- throw error(Kind.VARIABLE_DEFINITION);
376
- }
377
- ignored();
378
- vars.push({
379
- kind: Kind.VARIABLE_DEFINITION,
380
- variable: {
381
- kind: Kind.VARIABLE,
382
- name: {
383
- kind: Kind.NAME,
384
- value: match.slice(1),
385
- },
386
- },
387
- type: _type,
388
- defaultValue: _defaultValue as ast.ConstValueNode,
389
- directives: directives(true),
390
- });
391
- }
392
- if (input.charCodeAt(idx++) !== 41 /*')'*/)
393
- throw error(Kind.VARIABLE_DEFINITION);
394
- ignored();
395
- }
396
- return vars;
397
- }
398
-
399
- const fragmentDefinitionRe = /fragment/y;
400
- function fragmentDefinition(): ast.FragmentDefinitionNode | undefined {
401
- if (advance(fragmentDefinitionRe)) {
402
- ignored();
403
- const _name = name();
404
- if (!_name)
405
- throw error(Kind.FRAGMENT_DEFINITION);
406
- ignored();
407
- const _typeCondition = typeCondition();
408
- if (!_typeCondition)
409
- throw error(Kind.FRAGMENT_DEFINITION);
410
- const _directives = directives(false);
411
- const _selectionSet = selectionSet();
412
- if (!_selectionSet)
413
- throw error(Kind.FRAGMENT_DEFINITION);
414
- return {
415
- kind: Kind.FRAGMENT_DEFINITION,
416
- name: _name,
417
- typeCondition: _typeCondition,
418
- directives: _directives,
419
- selectionSet: _selectionSet,
420
- };
421
- }
422
- }
423
-
424
- const operationDefinitionRe = /query|mutation|subscription/y;
425
- function operationDefinition(): ast.OperationDefinitionNode | undefined {
426
- let _operation: string | undefined;
427
- let _name: ast.NameNode | undefined;
428
- let _variableDefinitions: ast.VariableDefinitionNode[] = [];
429
- let _directives: ast.DirectiveNode[] = [];
430
- if (_operation = advance(operationDefinitionRe)) {
431
- ignored();
432
- _name = name();
433
- _variableDefinitions = variableDefinitions();
434
- _directives = directives(false);
435
- }
436
- const _selectionSet = selectionSet();
437
- if (_selectionSet) {
438
- return {
439
- kind: Kind.OPERATION_DEFINITION,
440
- operation: (_operation || 'query') as ast.OperationTypeNode,
441
- name: _name,
442
- variableDefinitions: _variableDefinitions,
443
- directives: _directives,
444
- selectionSet: _selectionSet,
445
- };
446
- }
447
- }
448
-
449
- function document(): ast.DocumentNode {
450
- let match: ast.DefinitionNode | void;
451
- ignored();
452
- const definitions: ast.DefinitionNode[] = [];
453
- while (match = fragmentDefinition() || operationDefinition())
454
- definitions.push(match);
455
- if (idx !== input.length)
456
- throw error(Kind.DOCUMENT);
457
- return {
458
- kind: Kind.DOCUMENT,
459
- definitions,
460
- };
461
- }
462
-
463
- export function parse(string: string): ast.DocumentNode {
464
- input = string;
465
- idx = 0;
466
- return document();
467
- }
468
-
469
- export function parseValue(string: string): ast.ValueNode | undefined {
470
- input = string;
471
- idx = 0;
472
- ignored();
473
- return value(false);
474
- }
475
-
476
- export function parseType(string: string): ast.TypeNode | undefined {
477
- input = string;
478
- idx = 0;
479
- return type();
480
- }
package/src/printer.ts DELETED
@@ -1,132 +0,0 @@
1
- import { Kind } from './kind';
2
- import { ASTNode } from './ast';
3
-
4
- export function printString(string: string) {
5
- return JSON.stringify(string);
6
- }
7
-
8
- export function printBlockString(string: string) {
9
- return '"""\n' + string.replace(/"""/g, '\\"""') + '\n"""';
10
- }
11
-
12
- const hasItems = <T>(
13
- array: ReadonlyArray<T> | undefined | null
14
- ): array is ReadonlyArray<T> => !!(array && array.length);
15
-
16
- export function print(node: ASTNode): string {
17
- let out: string;
18
- switch (node.kind) {
19
- case Kind.OPERATION_DEFINITION:
20
- if (node.operation === 'query' && !node.name && !hasItems(node.variableDefinitions) && !hasItems(node.directives)) {
21
- return print(node.selectionSet);
22
- }
23
- out = node.operation;
24
- if (node.name)
25
- out += ' ' + node.name.value;
26
- if (hasItems(node.variableDefinitions)) {
27
- if (!node.name) out += ' ';
28
- out += '(' + node.variableDefinitions.map(print).join(', ') + ')';
29
- }
30
- if (hasItems(node.directives))
31
- out += ' ' + node.directives.map(print).join(' ');
32
- return out + ' ' + print(node.selectionSet);
33
-
34
- case Kind.VARIABLE_DEFINITION:
35
- out = print(node.variable) +
36
- ': ' +
37
- print(node.type);
38
- if (node.defaultValue)
39
- out += ' = ' + print(node.defaultValue);
40
- if (hasItems(node.directives))
41
- out += ' ' + node.directives.map(print).join(' ');
42
- return out;
43
-
44
- case Kind.FIELD:
45
- out = (node.alias ? print(node.alias) + ': ' : '') + node.name.value
46
- if (hasItems(node.arguments))
47
- out += '(' + node.arguments.map(print).join(', ') + ')';
48
- if (hasItems(node.directives))
49
- out += ' ' + node.directives.map(print).join(' ');
50
- return node.selectionSet
51
- ? out + ' ' + print(node.selectionSet)
52
- : out;
53
-
54
- case Kind.STRING:
55
- return node.block
56
- ? printBlockString(node.value)
57
- : printString(node.value);
58
-
59
- case Kind.BOOLEAN:
60
- return '' + node.value;
61
-
62
- case Kind.NULL:
63
- return 'null';
64
-
65
- case Kind.INT:
66
- case Kind.FLOAT:
67
- case Kind.ENUM:
68
- case Kind.NAME:
69
- return node.value;
70
-
71
- case Kind.LIST:
72
- return '[' + node.values.map(print).join(', ') + ']';
73
-
74
- case Kind.OBJECT:
75
- return '{' + node.fields.map(print).join(', ') + '}';
76
-
77
- case Kind.OBJECT_FIELD:
78
- return node.name.value + ': ' + print(node.value);
79
-
80
- case Kind.VARIABLE:
81
- return '$' + node.name.value;
82
-
83
- case Kind.DOCUMENT:
84
- return hasItems(node.definitions)
85
- ? node.definitions.map(print).join('\n\n')
86
- : '';
87
-
88
- case Kind.SELECTION_SET:
89
- return '{\n ' +
90
- node.selections.map(print).join('\n').replace(/\n/g, '\n ') +
91
- '\n}';
92
-
93
- case Kind.ARGUMENT:
94
- return node.name.value + ': ' + print(node.value);
95
-
96
- case Kind.FRAGMENT_SPREAD:
97
- out = '...' + node.name.value;
98
- if (hasItems(node.directives))
99
- out += ' ' + node.directives.map(print).join(' ');
100
- return out;
101
-
102
- case Kind.INLINE_FRAGMENT:
103
- out = '...';
104
- if (node.typeCondition)
105
- out += ' on ' + node.typeCondition.name.value;
106
- if (hasItems(node.directives))
107
- out += ' ' + node.directives.map(print).join(' ');
108
- return out + ' ' + print(node.selectionSet);
109
-
110
- case Kind.FRAGMENT_DEFINITION:
111
- out = 'fragment ' + node.name.value;
112
- out += ' on ' + node.typeCondition.name.value;
113
- if (hasItems(node.directives))
114
- out += ' ' + node.directives.map(print).join(' ');
115
- return out + ' ' + print(node.selectionSet);
116
-
117
- case Kind.DIRECTIVE:
118
- out = '@' + node.name.value;
119
- if (hasItems(node.arguments))
120
- out += '(' + node.arguments.map(print).join(', ') + ')';
121
- return out;
122
-
123
- case Kind.NAMED_TYPE:
124
- return node.name.value;
125
-
126
- case Kind.LIST_TYPE:
127
- return '[' + print(node.type) + ']';
128
-
129
- case Kind.NON_NULL_TYPE:
130
- return print(node.type) + '!';
131
- }
132
- }
package/src/types.ts DELETED
@@ -1,5 +0,0 @@
1
- export type Maybe<T> = T | undefined | null;
2
-
3
- export interface Extensions {
4
- [extension: string]: unknown;
5
- }