ether-code 0.7.8 → 0.7.9

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.
@@ -0,0 +1,539 @@
1
+ const { EtherParserBase, TokenType } = require('./ether-parser-base')
2
+
3
+ class EtherParserGraphQL extends EtherParserBase {
4
+ constructor(options = {}) {
5
+ super(options)
6
+ this.loadI18n(['i18n-graphql.json'])
7
+ }
8
+
9
+ parse(source) {
10
+ this.tokenize(source)
11
+ return this.parseGraphQLProgram()
12
+ }
13
+
14
+ parseGraphQLProgram() {
15
+ const document = {
16
+ type: 'GraphQLDocument',
17
+ definitions: []
18
+ }
19
+
20
+ this.skipNewlines()
21
+
22
+ while (!this.isAtEnd()) {
23
+ const def = this.parseGraphQLDefinition()
24
+ if (def) {
25
+ document.definitions.push(def)
26
+ }
27
+ this.skipNewlines()
28
+ }
29
+
30
+ return document
31
+ }
32
+
33
+ parseGraphQLDefinition() {
34
+ this.skipNewlines()
35
+ const token = this.current()
36
+
37
+ if (!token || token.type === TokenType.EOF) return null
38
+
39
+ const value = token.value ? token.value.toLowerCase() : ''
40
+
41
+ if (value === 'type' || value === 'modele') {
42
+ return this.parseGraphQLType()
43
+ }
44
+
45
+ if (value === 'query' || value === 'requete') {
46
+ return this.parseGraphQLOperation('query')
47
+ }
48
+
49
+ if (value === 'mutation') {
50
+ return this.parseGraphQLOperation('mutation')
51
+ }
52
+
53
+ if (value === 'subscription' || value === 'abonnement') {
54
+ return this.parseGraphQLOperation('subscription')
55
+ }
56
+
57
+ if (value === 'input' || value === 'entree') {
58
+ return this.parseGraphQLInput()
59
+ }
60
+
61
+ if (value === 'enum' || value === 'enumeration') {
62
+ return this.parseGraphQLEnum()
63
+ }
64
+
65
+ if (value === 'interface') {
66
+ return this.parseGraphQLInterface()
67
+ }
68
+
69
+ if (value === 'schema' || value === 'schéma') {
70
+ return this.parseGraphQLSchema()
71
+ }
72
+
73
+ this.advance()
74
+ return null
75
+ }
76
+
77
+ parseGraphQLType() {
78
+ this.advance()
79
+
80
+ const nameToken = this.current()
81
+ let name = null
82
+ if (nameToken && nameToken.type === TokenType.IDENTIFIER) {
83
+ name = nameToken.value
84
+ this.advance()
85
+ }
86
+
87
+ let implements_ = []
88
+ if (this.matchValue('implements') || this.matchValue('implemente')) {
89
+ while (!this.isAtEnd()) {
90
+ const implToken = this.current()
91
+ if (!implToken || implToken.type !== TokenType.IDENTIFIER) break
92
+ if (implToken.value.toLowerCase() === 'implements' ||
93
+ implToken.value === '{') break
94
+ implements_.push(implToken.value)
95
+ this.advance()
96
+ this.match(TokenType.COMMA) || this.match(TokenType.AMPERSAND)
97
+ }
98
+ }
99
+
100
+ const fields = this.parseGraphQLFields()
101
+
102
+ return {
103
+ type: 'TypeDefinition',
104
+ name: name,
105
+ implements: implements_,
106
+ fields: fields
107
+ }
108
+ }
109
+
110
+ parseGraphQLFields() {
111
+ const fields = []
112
+
113
+ this.skipNewlines()
114
+
115
+ if (this.match(TokenType.LBRACE)) {
116
+ while (!this.isAtEnd() && !this.match(TokenType.RBRACE)) {
117
+ this.skipNewlines()
118
+ const field = this.parseGraphQLField()
119
+ if (field) {
120
+ fields.push(field)
121
+ }
122
+ this.skipNewlines()
123
+ }
124
+ } else if (this.match(TokenType.INDENT)) {
125
+ while (!this.isAtEnd()) {
126
+ const current = this.current()
127
+
128
+ if (current && current.type === TokenType.DEDENT) {
129
+ this.advance()
130
+ break
131
+ }
132
+
133
+ if (current && current.type === TokenType.NEWLINE) {
134
+ this.advance()
135
+ continue
136
+ }
137
+
138
+ const field = this.parseGraphQLField()
139
+ if (field) {
140
+ fields.push(field)
141
+ }
142
+ }
143
+ }
144
+
145
+ return fields
146
+ }
147
+
148
+ parseGraphQLField() {
149
+ const nameToken = this.current()
150
+ if (!nameToken || nameToken.type !== TokenType.IDENTIFIER) return null
151
+
152
+ const name = nameToken.value
153
+ this.advance()
154
+
155
+ const args = []
156
+ if (this.match(TokenType.LPAREN)) {
157
+ while (!this.isAtEnd() && !this.match(TokenType.RPAREN)) {
158
+ const arg = this.parseGraphQLArgument()
159
+ if (arg) {
160
+ args.push(arg)
161
+ }
162
+ this.match(TokenType.COMMA)
163
+ }
164
+ }
165
+
166
+ this.match(TokenType.COLON)
167
+
168
+ const fieldType = this.parseGraphQLType_()
169
+
170
+ return {
171
+ name: name,
172
+ arguments: args,
173
+ type: fieldType
174
+ }
175
+ }
176
+
177
+ parseGraphQLArgument() {
178
+ const nameToken = this.current()
179
+ if (!nameToken || nameToken.type !== TokenType.IDENTIFIER) return null
180
+
181
+ const name = nameToken.value
182
+ this.advance()
183
+
184
+ this.match(TokenType.COLON)
185
+
186
+ const argType = this.parseGraphQLType_()
187
+
188
+ let defaultValue = null
189
+ if (this.match(TokenType.EQUALS)) {
190
+ defaultValue = this.parseGraphQLValue()
191
+ }
192
+
193
+ return {
194
+ name: name,
195
+ type: argType,
196
+ defaultValue: defaultValue
197
+ }
198
+ }
199
+
200
+ parseGraphQLType_() {
201
+ let isNonNull = false
202
+ let isList = false
203
+ let listItemNonNull = false
204
+
205
+ let typeName = null
206
+
207
+ if (this.match(TokenType.LBRACKET)) {
208
+ isList = true
209
+ const innerType = this.current()
210
+ if (innerType && innerType.type === TokenType.IDENTIFIER) {
211
+ typeName = this.translateGraphQLType(innerType.value)
212
+ this.advance()
213
+ }
214
+ if (this.match(TokenType.BANG)) {
215
+ listItemNonNull = true
216
+ }
217
+ this.match(TokenType.RBRACKET)
218
+ } else {
219
+ const typeToken = this.current()
220
+ if (typeToken && typeToken.type === TokenType.IDENTIFIER) {
221
+ typeName = this.translateGraphQLType(typeToken.value)
222
+ this.advance()
223
+ }
224
+ }
225
+
226
+ if (this.match(TokenType.BANG)) {
227
+ isNonNull = true
228
+ }
229
+
230
+ return {
231
+ name: typeName,
232
+ isList: isList,
233
+ isNonNull: isNonNull,
234
+ listItemNonNull: listItemNonNull
235
+ }
236
+ }
237
+
238
+ translateGraphQLType(type) {
239
+ const map = {
240
+ 'chaine': 'String',
241
+ 'texte': 'String',
242
+ 'entier': 'Int',
243
+ 'nombre': 'Int',
244
+ 'flottant': 'Float',
245
+ 'decimal': 'Float',
246
+ 'booleen': 'Boolean',
247
+ 'bool': 'Boolean',
248
+ 'identifiant': 'ID',
249
+ 'id': 'ID'
250
+ }
251
+
252
+ return map[type.toLowerCase()] || type
253
+ }
254
+
255
+ parseGraphQLValue() {
256
+ const token = this.current()
257
+ if (!token) return null
258
+
259
+ if (token.type === TokenType.STRING) {
260
+ this.advance()
261
+ return { type: 'StringValue', value: token.value.replace(/^["']|["']$/g, '') }
262
+ }
263
+
264
+ if (token.type === TokenType.NUMBER || token.type === TokenType.INTEGER) {
265
+ this.advance()
266
+ return { type: 'NumberValue', value: parseFloat(token.value) }
267
+ }
268
+
269
+ if (token.type === TokenType.IDENTIFIER) {
270
+ const val = token.value.toLowerCase()
271
+ this.advance()
272
+
273
+ if (val === 'vrai' || val === 'true') {
274
+ return { type: 'BooleanValue', value: true }
275
+ }
276
+ if (val === 'faux' || val === 'false') {
277
+ return { type: 'BooleanValue', value: false }
278
+ }
279
+ if (val === 'nul' || val === 'null') {
280
+ return { type: 'NullValue' }
281
+ }
282
+
283
+ return { type: 'EnumValue', value: token.value }
284
+ }
285
+
286
+ return null
287
+ }
288
+
289
+ parseGraphQLOperation(opType) {
290
+ this.advance()
291
+
292
+ let name = null
293
+ const nameToken = this.current()
294
+ if (nameToken && nameToken.type === TokenType.IDENTIFIER) {
295
+ name = nameToken.value
296
+ this.advance()
297
+ }
298
+
299
+ const variables = []
300
+ if (this.match(TokenType.LPAREN)) {
301
+ while (!this.isAtEnd() && !this.match(TokenType.RPAREN)) {
302
+ const varToken = this.current()
303
+ if (varToken && varToken.type === TokenType.IDENTIFIER) {
304
+ const varName = varToken.value
305
+ this.advance()
306
+ this.match(TokenType.COLON)
307
+ const varType = this.parseGraphQLType_()
308
+ variables.push({ name: varName, type: varType })
309
+ }
310
+ this.match(TokenType.COMMA)
311
+ }
312
+ }
313
+
314
+ const selections = this.parseGraphQLSelectionSet()
315
+
316
+ return {
317
+ type: 'OperationDefinition',
318
+ operation: opType,
319
+ name: name,
320
+ variables: variables,
321
+ selectionSet: selections
322
+ }
323
+ }
324
+
325
+ parseGraphQLSelectionSet() {
326
+ const selections = []
327
+
328
+ this.skipNewlines()
329
+
330
+ if (this.match(TokenType.LBRACE)) {
331
+ while (!this.isAtEnd() && !this.match(TokenType.RBRACE)) {
332
+ this.skipNewlines()
333
+ const selection = this.parseGraphQLSelection()
334
+ if (selection) {
335
+ selections.push(selection)
336
+ }
337
+ this.skipNewlines()
338
+ }
339
+ } else if (this.match(TokenType.INDENT)) {
340
+ while (!this.isAtEnd()) {
341
+ const current = this.current()
342
+
343
+ if (current && current.type === TokenType.DEDENT) {
344
+ this.advance()
345
+ break
346
+ }
347
+
348
+ if (current && current.type === TokenType.NEWLINE) {
349
+ this.advance()
350
+ continue
351
+ }
352
+
353
+ const selection = this.parseGraphQLSelection()
354
+ if (selection) {
355
+ selections.push(selection)
356
+ }
357
+ }
358
+ }
359
+
360
+ return selections
361
+ }
362
+
363
+ parseGraphQLSelection() {
364
+ const nameToken = this.current()
365
+ if (!nameToken || nameToken.type !== TokenType.IDENTIFIER) return null
366
+
367
+ const name = nameToken.value
368
+ this.advance()
369
+
370
+ const args = []
371
+ if (this.match(TokenType.LPAREN)) {
372
+ while (!this.isAtEnd() && !this.match(TokenType.RPAREN)) {
373
+ const argName = this.current()
374
+ if (argName && argName.type === TokenType.IDENTIFIER) {
375
+ const argNameVal = argName.value
376
+ this.advance()
377
+ this.match(TokenType.COLON)
378
+ const argValue = this.parseGraphQLValue()
379
+ args.push({ name: argNameVal, value: argValue })
380
+ }
381
+ this.match(TokenType.COMMA)
382
+ }
383
+ }
384
+
385
+ let nestedSelections = []
386
+ const next = this.current()
387
+ if (next && (next.type === TokenType.LBRACE || next.type === TokenType.INDENT)) {
388
+ nestedSelections = this.parseGraphQLSelectionSet()
389
+ }
390
+
391
+ return {
392
+ type: 'Field',
393
+ name: name,
394
+ arguments: args,
395
+ selectionSet: nestedSelections
396
+ }
397
+ }
398
+
399
+ parseGraphQLInput() {
400
+ this.advance()
401
+
402
+ const nameToken = this.current()
403
+ let name = null
404
+ if (nameToken && nameToken.type === TokenType.IDENTIFIER) {
405
+ name = nameToken.value
406
+ this.advance()
407
+ }
408
+
409
+ const fields = this.parseGraphQLFields()
410
+
411
+ return {
412
+ type: 'InputTypeDefinition',
413
+ name: name,
414
+ fields: fields
415
+ }
416
+ }
417
+
418
+ parseGraphQLEnum() {
419
+ this.advance()
420
+
421
+ const nameToken = this.current()
422
+ let name = null
423
+ if (nameToken && nameToken.type === TokenType.IDENTIFIER) {
424
+ name = nameToken.value
425
+ this.advance()
426
+ }
427
+
428
+ const values = []
429
+
430
+ this.skipNewlines()
431
+
432
+ if (this.match(TokenType.LBRACE)) {
433
+ while (!this.isAtEnd() && !this.match(TokenType.RBRACE)) {
434
+ this.skipNewlines()
435
+ const valueToken = this.current()
436
+ if (valueToken && valueToken.type === TokenType.IDENTIFIER) {
437
+ values.push(valueToken.value)
438
+ this.advance()
439
+ }
440
+ this.skipNewlines()
441
+ }
442
+ } else if (this.match(TokenType.INDENT)) {
443
+ while (!this.isAtEnd()) {
444
+ const current = this.current()
445
+
446
+ if (current && current.type === TokenType.DEDENT) {
447
+ this.advance()
448
+ break
449
+ }
450
+
451
+ if (current && current.type === TokenType.NEWLINE) {
452
+ this.advance()
453
+ continue
454
+ }
455
+
456
+ if (current && current.type === TokenType.IDENTIFIER) {
457
+ values.push(current.value)
458
+ this.advance()
459
+ }
460
+ }
461
+ }
462
+
463
+ return {
464
+ type: 'EnumDefinition',
465
+ name: name,
466
+ values: values
467
+ }
468
+ }
469
+
470
+ parseGraphQLInterface() {
471
+ this.advance()
472
+
473
+ const nameToken = this.current()
474
+ let name = null
475
+ if (nameToken && nameToken.type === TokenType.IDENTIFIER) {
476
+ name = nameToken.value
477
+ this.advance()
478
+ }
479
+
480
+ const fields = this.parseGraphQLFields()
481
+
482
+ return {
483
+ type: 'InterfaceDefinition',
484
+ name: name,
485
+ fields: fields
486
+ }
487
+ }
488
+
489
+ parseGraphQLSchema() {
490
+ this.advance()
491
+
492
+ const definitions = {}
493
+
494
+ this.skipNewlines()
495
+
496
+ if (this.match(TokenType.LBRACE) || this.match(TokenType.INDENT)) {
497
+ while (!this.isAtEnd()) {
498
+ const current = this.current()
499
+
500
+ if (current && (current.type === TokenType.RBRACE || current.type === TokenType.DEDENT)) {
501
+ this.advance()
502
+ break
503
+ }
504
+
505
+ if (current && current.type === TokenType.NEWLINE) {
506
+ this.advance()
507
+ continue
508
+ }
509
+
510
+ if (current && current.type === TokenType.IDENTIFIER) {
511
+ const opType = current.value.toLowerCase()
512
+ this.advance()
513
+ this.match(TokenType.COLON)
514
+
515
+ const typeToken = this.current()
516
+ if (typeToken && typeToken.type === TokenType.IDENTIFIER) {
517
+ definitions[opType] = typeToken.value
518
+ this.advance()
519
+ }
520
+ }
521
+ }
522
+ }
523
+
524
+ return {
525
+ type: 'SchemaDefinition',
526
+ definitions: definitions
527
+ }
528
+ }
529
+
530
+ parseStatement(lang) {
531
+ return this.parseGraphQLDefinition()
532
+ }
533
+
534
+ parseExpression(lang) {
535
+ return null
536
+ }
537
+ }
538
+
539
+ module.exports = { EtherParserGraphQL }