ether-code 0.1.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/LICENSE +21 -0
- package/README.md +130 -0
- package/cli/compiler.js +298 -0
- package/cli/ether.js +532 -0
- package/cli/watcher.js +106 -0
- package/generators/css-generator.js +583 -0
- package/generators/graphql-generator.js +868 -0
- package/generators/html-generator.js +745 -0
- package/generators/js-generator.js +909 -0
- package/generators/node-generator.js +467 -0
- package/generators/php-generator.js +706 -0
- package/generators/python-generator.js +913 -0
- package/generators/react-generator.js +599 -0
- package/generators/ruby-generator.js +904 -0
- package/generators/sql-generator.js +988 -0
- package/generators/ts-generator.js +569 -0
- package/i18n/i18n-css.json +743 -0
- package/i18n/i18n-graphql.json +1531 -0
- package/i18n/i18n-html.json +572 -0
- package/i18n/i18n-js.json +2790 -0
- package/i18n/i18n-node.json +2442 -0
- package/i18n/i18n-php.json +4306 -0
- package/i18n/i18n-python.json +3080 -0
- package/i18n/i18n-react.json +1784 -0
- package/i18n/i18n-ruby.json +1858 -0
- package/i18n/i18n-sql.json +3466 -0
- package/i18n/i18n-ts.json +442 -0
- package/lexer/ether-lexer.js +728 -0
- package/lexer/tokens.js +292 -0
- package/package.json +45 -0
- package/parsers/ast-css.js +545 -0
- package/parsers/ast-graphql.js +424 -0
- package/parsers/ast-html.js +886 -0
- package/parsers/ast-js.js +750 -0
- package/parsers/ast-node.js +2440 -0
- package/parsers/ast-php.js +957 -0
- package/parsers/ast-react.js +580 -0
- package/parsers/ast-ruby.js +895 -0
- package/parsers/ast-ts.js +1352 -0
- package/parsers/css-parser.js +1981 -0
- package/parsers/graphql-parser.js +2011 -0
- package/parsers/html-parser.js +1181 -0
- package/parsers/js-parser.js +2564 -0
- package/parsers/node-parser.js +2644 -0
- package/parsers/php-parser.js +3037 -0
- package/parsers/react-parser.js +1035 -0
- package/parsers/ruby-parser.js +2680 -0
- package/parsers/ts-parser.js +3881 -0
|
@@ -0,0 +1,868 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
|
|
3
|
+
class GraphQLGenerator {
|
|
4
|
+
constructor(i18nPath = null) {
|
|
5
|
+
this.i18n = null
|
|
6
|
+
this.indent = 0
|
|
7
|
+
this.output = ''
|
|
8
|
+
this.keywordMap = {}
|
|
9
|
+
this.typeMap = {}
|
|
10
|
+
this.directiveMap = {}
|
|
11
|
+
|
|
12
|
+
if (i18nPath) {
|
|
13
|
+
this.loadI18n(i18nPath)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
loadI18n(filePath) {
|
|
18
|
+
const content = fs.readFileSync(filePath, 'utf-8')
|
|
19
|
+
this.i18n = JSON.parse(content)
|
|
20
|
+
this.buildMaps()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
buildMaps() {
|
|
24
|
+
this.keywordMap = {}
|
|
25
|
+
this.typeMap = {}
|
|
26
|
+
this.directiveMap = {}
|
|
27
|
+
|
|
28
|
+
if (!this.i18n) return
|
|
29
|
+
|
|
30
|
+
const addToMap = (map, section) => {
|
|
31
|
+
if (!section) return
|
|
32
|
+
for (const [key, translations] of Object.entries(section)) {
|
|
33
|
+
if (translations && translations.fr && translations.graphql) {
|
|
34
|
+
map[translations.fr.toLowerCase()] = translations.graphql
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
for (const sectionName of Object.keys(this.i18n)) {
|
|
40
|
+
addToMap(this.keywordMap, this.i18n[sectionName])
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
translate(word) {
|
|
45
|
+
if (!word) return ''
|
|
46
|
+
const lower = word.toLowerCase()
|
|
47
|
+
return this.keywordMap[lower] || this.translateGeneric(word)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
translateGeneric(word) {
|
|
51
|
+
const translations = {
|
|
52
|
+
'type': 'type',
|
|
53
|
+
'requête': 'Query',
|
|
54
|
+
'mutation': 'Mutation',
|
|
55
|
+
'abonnement': 'Subscription',
|
|
56
|
+
'schema': 'schema',
|
|
57
|
+
'interface': 'interface',
|
|
58
|
+
'union': 'union',
|
|
59
|
+
'enum': 'enum',
|
|
60
|
+
'énumération': 'enum',
|
|
61
|
+
'entrée': 'input',
|
|
62
|
+
'scalaire': 'scalar',
|
|
63
|
+
'étend': 'extend',
|
|
64
|
+
'implémente': 'implements',
|
|
65
|
+
'fragment': 'fragment',
|
|
66
|
+
'sur': 'on',
|
|
67
|
+
'directive': 'directive',
|
|
68
|
+
'répéter': '@repeatable',
|
|
69
|
+
'chaîne': 'String',
|
|
70
|
+
'entier': 'Int',
|
|
71
|
+
'flottant': 'Float',
|
|
72
|
+
'booléen': 'Boolean',
|
|
73
|
+
'identifiant': 'ID',
|
|
74
|
+
'date': 'Date',
|
|
75
|
+
'datetime': 'DateTime',
|
|
76
|
+
'json': 'JSON',
|
|
77
|
+
'url': 'URL',
|
|
78
|
+
'courriel': 'Email',
|
|
79
|
+
'vrai': 'true',
|
|
80
|
+
'faux': 'false',
|
|
81
|
+
'nul': 'null',
|
|
82
|
+
'non nul': '!',
|
|
83
|
+
'liste': '[]',
|
|
84
|
+
'déprécié': '@deprecated',
|
|
85
|
+
'ignorer': '@skip',
|
|
86
|
+
'inclure': '@include',
|
|
87
|
+
'si': 'if',
|
|
88
|
+
'raison': 'reason',
|
|
89
|
+
'requiert': '@requires',
|
|
90
|
+
'fournit': '@provides',
|
|
91
|
+
'clé': '@key',
|
|
92
|
+
'externe': '@external',
|
|
93
|
+
'champs': 'fields'
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const lower = word.toLowerCase()
|
|
97
|
+
return translations[lower] || word
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
translateType(type) {
|
|
101
|
+
if (!type) return ''
|
|
102
|
+
|
|
103
|
+
const types = {
|
|
104
|
+
'chaîne': 'String',
|
|
105
|
+
'entier': 'Int',
|
|
106
|
+
'flottant': 'Float',
|
|
107
|
+
'booléen': 'Boolean',
|
|
108
|
+
'identifiant': 'ID',
|
|
109
|
+
'date': 'Date',
|
|
110
|
+
'datetime': 'DateTime',
|
|
111
|
+
'heure': 'Time',
|
|
112
|
+
'json': 'JSON',
|
|
113
|
+
'url': 'URL',
|
|
114
|
+
'courriel': 'Email',
|
|
115
|
+
'telephone': 'Phone',
|
|
116
|
+
'uuid': 'UUID',
|
|
117
|
+
'grand entier': 'BigInt',
|
|
118
|
+
'decimal': 'Decimal',
|
|
119
|
+
'positif entier': 'PositiveInt',
|
|
120
|
+
'négatif entier': 'NegativeInt',
|
|
121
|
+
'non négatif entier': 'NonNegativeInt',
|
|
122
|
+
'non positif entier': 'NonPositiveInt',
|
|
123
|
+
'positif flottant': 'PositiveFloat',
|
|
124
|
+
'négatif flottant': 'NegativeFloat',
|
|
125
|
+
'non vide chaîne': 'NonEmptyString',
|
|
126
|
+
'upload': 'Upload',
|
|
127
|
+
'vide': 'Void'
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const lower = type.toLowerCase()
|
|
131
|
+
return types[lower] || type
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
generate(ast) {
|
|
135
|
+
this.output = ''
|
|
136
|
+
this.indent = 0
|
|
137
|
+
|
|
138
|
+
if (Array.isArray(ast)) {
|
|
139
|
+
for (const node of ast) {
|
|
140
|
+
this.generateNode(node)
|
|
141
|
+
this.output += '\n'
|
|
142
|
+
}
|
|
143
|
+
} else if (ast && ast.type) {
|
|
144
|
+
this.generateNode(ast)
|
|
145
|
+
} else if (ast && ast.definitions) {
|
|
146
|
+
for (const def of ast.definitions) {
|
|
147
|
+
this.generateNode(def)
|
|
148
|
+
this.output += '\n'
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return this.output.trim()
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
generateNode(node) {
|
|
156
|
+
if (!node) return ''
|
|
157
|
+
|
|
158
|
+
switch (node.type || node.kind) {
|
|
159
|
+
case 'SchemaDefinition':
|
|
160
|
+
return this.generateSchema(node)
|
|
161
|
+
case 'TypeDefinition':
|
|
162
|
+
case 'ObjectTypeDefinition':
|
|
163
|
+
return this.generateTypeDefinition(node)
|
|
164
|
+
case 'InterfaceDefinition':
|
|
165
|
+
case 'InterfaceTypeDefinition':
|
|
166
|
+
return this.generateInterface(node)
|
|
167
|
+
case 'UnionDefinition':
|
|
168
|
+
case 'UnionTypeDefinition':
|
|
169
|
+
return this.generateUnion(node)
|
|
170
|
+
case 'EnumDefinition':
|
|
171
|
+
case 'EnumTypeDefinition':
|
|
172
|
+
return this.generateEnum(node)
|
|
173
|
+
case 'InputDefinition':
|
|
174
|
+
case 'InputObjectTypeDefinition':
|
|
175
|
+
return this.generateInput(node)
|
|
176
|
+
case 'ScalarDefinition':
|
|
177
|
+
case 'ScalarTypeDefinition':
|
|
178
|
+
return this.generateScalar(node)
|
|
179
|
+
case 'DirectiveDefinition':
|
|
180
|
+
return this.generateDirectiveDefinition(node)
|
|
181
|
+
case 'ExtendType':
|
|
182
|
+
case 'TypeExtension':
|
|
183
|
+
case 'ObjectTypeExtension':
|
|
184
|
+
return this.generateExtendType(node)
|
|
185
|
+
case 'FragmentDefinition':
|
|
186
|
+
return this.generateFragment(node)
|
|
187
|
+
case 'OperationDefinition':
|
|
188
|
+
return this.generateOperation(node)
|
|
189
|
+
case 'Query':
|
|
190
|
+
return this.generateQuery(node)
|
|
191
|
+
case 'Mutation':
|
|
192
|
+
return this.generateMutation(node)
|
|
193
|
+
case 'Subscription':
|
|
194
|
+
return this.generateSubscription(node)
|
|
195
|
+
case 'Field':
|
|
196
|
+
case 'FieldDefinition':
|
|
197
|
+
return this.generateField(node)
|
|
198
|
+
case 'Argument':
|
|
199
|
+
case 'InputValueDefinition':
|
|
200
|
+
return this.generateArgument(node)
|
|
201
|
+
case 'Directive':
|
|
202
|
+
return this.generateDirective(node)
|
|
203
|
+
case 'Variable':
|
|
204
|
+
return this.generateVariable(node)
|
|
205
|
+
case 'SelectionSet':
|
|
206
|
+
return this.generateSelectionSet(node)
|
|
207
|
+
default:
|
|
208
|
+
return ''
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
generateSchema(node) {
|
|
213
|
+
this.writeLine('schema {')
|
|
214
|
+
this.indent++
|
|
215
|
+
|
|
216
|
+
if (node.query) {
|
|
217
|
+
this.writeLine(`query: ${this.translate(node.query)}`)
|
|
218
|
+
}
|
|
219
|
+
if (node.mutation) {
|
|
220
|
+
this.writeLine(`mutation: ${this.translate(node.mutation)}`)
|
|
221
|
+
}
|
|
222
|
+
if (node.subscription) {
|
|
223
|
+
this.writeLine(`subscription: ${this.translate(node.subscription)}`)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const operations = node.operations || node.operationTypes || []
|
|
227
|
+
for (const op of operations) {
|
|
228
|
+
const opType = this.translate(op.operation || op.type)
|
|
229
|
+
const typeName = this.translate(op.type?.name || op.name)
|
|
230
|
+
this.writeLine(`${opType}: ${typeName}`)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
this.indent--
|
|
234
|
+
this.writeLine('}')
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
generateTypeDefinition(node) {
|
|
238
|
+
const name = node.name?.value || node.name
|
|
239
|
+
const description = node.description?.value || node.description
|
|
240
|
+
const interfaces = node.interfaces || []
|
|
241
|
+
const directives = node.directives || []
|
|
242
|
+
const fields = node.fields || []
|
|
243
|
+
|
|
244
|
+
if (description) {
|
|
245
|
+
this.writeDescription(description)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
let declaration = `type ${name}`
|
|
249
|
+
|
|
250
|
+
if (interfaces.length > 0) {
|
|
251
|
+
const interfaceNames = interfaces.map(i => i.name?.value || i.name || i)
|
|
252
|
+
declaration += ` implements ${interfaceNames.join(' & ')}`
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (directives.length > 0) {
|
|
256
|
+
declaration += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
this.writeLine(declaration + ' {')
|
|
260
|
+
this.indent++
|
|
261
|
+
|
|
262
|
+
for (const field of fields) {
|
|
263
|
+
this.generateField(field)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
this.indent--
|
|
267
|
+
this.writeLine('}')
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
generateInterface(node) {
|
|
271
|
+
const name = node.name?.value || node.name
|
|
272
|
+
const description = node.description?.value || node.description
|
|
273
|
+
const directives = node.directives || []
|
|
274
|
+
const fields = node.fields || []
|
|
275
|
+
|
|
276
|
+
if (description) {
|
|
277
|
+
this.writeDescription(description)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
let declaration = `interface ${name}`
|
|
281
|
+
|
|
282
|
+
if (directives.length > 0) {
|
|
283
|
+
declaration += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
this.writeLine(declaration + ' {')
|
|
287
|
+
this.indent++
|
|
288
|
+
|
|
289
|
+
for (const field of fields) {
|
|
290
|
+
this.generateField(field)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
this.indent--
|
|
294
|
+
this.writeLine('}')
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
generateUnion(node) {
|
|
298
|
+
const name = node.name?.value || node.name
|
|
299
|
+
const description = node.description?.value || node.description
|
|
300
|
+
const types = node.types || []
|
|
301
|
+
const directives = node.directives || []
|
|
302
|
+
|
|
303
|
+
if (description) {
|
|
304
|
+
this.writeDescription(description)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
let declaration = `union ${name}`
|
|
308
|
+
|
|
309
|
+
if (directives.length > 0) {
|
|
310
|
+
declaration += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const typeNames = types.map(t => t.name?.value || t.name || t)
|
|
314
|
+
declaration += ` = ${typeNames.join(' | ')}`
|
|
315
|
+
|
|
316
|
+
this.writeLine(declaration)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
generateEnum(node) {
|
|
320
|
+
const name = node.name?.value || node.name
|
|
321
|
+
const description = node.description?.value || node.description
|
|
322
|
+
const values = node.values || []
|
|
323
|
+
const directives = node.directives || []
|
|
324
|
+
|
|
325
|
+
if (description) {
|
|
326
|
+
this.writeDescription(description)
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
let declaration = `enum ${name}`
|
|
330
|
+
|
|
331
|
+
if (directives.length > 0) {
|
|
332
|
+
declaration += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
this.writeLine(declaration + ' {')
|
|
336
|
+
this.indent++
|
|
337
|
+
|
|
338
|
+
for (const value of values) {
|
|
339
|
+
const valueName = value.name?.value || value.name || value
|
|
340
|
+
const valueDesc = value.description?.value || value.description
|
|
341
|
+
const valueDirectives = value.directives || []
|
|
342
|
+
|
|
343
|
+
if (valueDesc) {
|
|
344
|
+
this.writeDescription(valueDesc)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
let valueLine = valueName
|
|
348
|
+
if (valueDirectives.length > 0) {
|
|
349
|
+
valueLine += ' ' + valueDirectives.map(d => this.generateDirective(d)).join(' ')
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
this.writeLine(valueLine)
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
this.indent--
|
|
356
|
+
this.writeLine('}')
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
generateInput(node) {
|
|
360
|
+
const name = node.name?.value || node.name
|
|
361
|
+
const description = node.description?.value || node.description
|
|
362
|
+
const fields = node.fields || []
|
|
363
|
+
const directives = node.directives || []
|
|
364
|
+
|
|
365
|
+
if (description) {
|
|
366
|
+
this.writeDescription(description)
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
let declaration = `input ${name}`
|
|
370
|
+
|
|
371
|
+
if (directives.length > 0) {
|
|
372
|
+
declaration += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
this.writeLine(declaration + ' {')
|
|
376
|
+
this.indent++
|
|
377
|
+
|
|
378
|
+
for (const field of fields) {
|
|
379
|
+
this.generateInputField(field)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
this.indent--
|
|
383
|
+
this.writeLine('}')
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
generateScalar(node) {
|
|
387
|
+
const name = node.name?.value || node.name
|
|
388
|
+
const description = node.description?.value || node.description
|
|
389
|
+
const directives = node.directives || []
|
|
390
|
+
|
|
391
|
+
if (description) {
|
|
392
|
+
this.writeDescription(description)
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
let declaration = `scalar ${name}`
|
|
396
|
+
|
|
397
|
+
if (directives.length > 0) {
|
|
398
|
+
declaration += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
this.writeLine(declaration)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
generateDirectiveDefinition(node) {
|
|
405
|
+
const name = node.name?.value || node.name
|
|
406
|
+
const description = node.description?.value || node.description
|
|
407
|
+
const args = node.arguments || node.args || []
|
|
408
|
+
const locations = node.locations || []
|
|
409
|
+
const repeatable = node.repeatable
|
|
410
|
+
|
|
411
|
+
if (description) {
|
|
412
|
+
this.writeDescription(description)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
let declaration = `directive @${name}`
|
|
416
|
+
|
|
417
|
+
if (args.length > 0) {
|
|
418
|
+
const argsStr = args.map(a => this.generateArgumentDefinition(a)).join(', ')
|
|
419
|
+
declaration += `(${argsStr})`
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (repeatable) {
|
|
423
|
+
declaration += ' repeatable'
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
const locationNames = locations.map(l => l.value || l)
|
|
427
|
+
declaration += ` on ${locationNames.join(' | ')}`
|
|
428
|
+
|
|
429
|
+
this.writeLine(declaration)
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
generateExtendType(node) {
|
|
433
|
+
const name = node.name?.value || node.name
|
|
434
|
+
const interfaces = node.interfaces || []
|
|
435
|
+
const directives = node.directives || []
|
|
436
|
+
const fields = node.fields || []
|
|
437
|
+
|
|
438
|
+
let declaration = `extend type ${name}`
|
|
439
|
+
|
|
440
|
+
if (interfaces.length > 0) {
|
|
441
|
+
const interfaceNames = interfaces.map(i => i.name?.value || i.name || i)
|
|
442
|
+
declaration += ` implements ${interfaceNames.join(' & ')}`
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (directives.length > 0) {
|
|
446
|
+
declaration += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (fields.length > 0) {
|
|
450
|
+
this.writeLine(declaration + ' {')
|
|
451
|
+
this.indent++
|
|
452
|
+
|
|
453
|
+
for (const field of fields) {
|
|
454
|
+
this.generateField(field)
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
this.indent--
|
|
458
|
+
this.writeLine('}')
|
|
459
|
+
} else {
|
|
460
|
+
this.writeLine(declaration)
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
generateFragment(node) {
|
|
465
|
+
const name = node.name?.value || node.name
|
|
466
|
+
const typeCondition = node.typeCondition?.name?.value || node.typeCondition || node.on
|
|
467
|
+
const directives = node.directives || []
|
|
468
|
+
const selections = node.selectionSet?.selections || node.selections || []
|
|
469
|
+
|
|
470
|
+
let declaration = `fragment ${name} on ${typeCondition}`
|
|
471
|
+
|
|
472
|
+
if (directives.length > 0) {
|
|
473
|
+
declaration += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
this.writeLine(declaration + ' {')
|
|
477
|
+
this.indent++
|
|
478
|
+
|
|
479
|
+
for (const selection of selections) {
|
|
480
|
+
this.generateSelection(selection)
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
this.indent--
|
|
484
|
+
this.writeLine('}')
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
generateOperation(node) {
|
|
488
|
+
const operation = node.operation || 'query'
|
|
489
|
+
const name = node.name?.value || node.name || ''
|
|
490
|
+
const variables = node.variableDefinitions || node.variables || []
|
|
491
|
+
const directives = node.directives || []
|
|
492
|
+
const selections = node.selectionSet?.selections || node.selections || []
|
|
493
|
+
|
|
494
|
+
let declaration = operation
|
|
495
|
+
if (name) {
|
|
496
|
+
declaration += ` ${name}`
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (variables.length > 0) {
|
|
500
|
+
const varsStr = variables.map(v => this.generateVariableDefinition(v)).join(', ')
|
|
501
|
+
declaration += `(${varsStr})`
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (directives.length > 0) {
|
|
505
|
+
declaration += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
this.writeLine(declaration + ' {')
|
|
509
|
+
this.indent++
|
|
510
|
+
|
|
511
|
+
for (const selection of selections) {
|
|
512
|
+
this.generateSelection(selection)
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
this.indent--
|
|
516
|
+
this.writeLine('}')
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
generateQuery(node) {
|
|
520
|
+
node.operation = 'query'
|
|
521
|
+
return this.generateOperation(node)
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
generateMutation(node) {
|
|
525
|
+
node.operation = 'mutation'
|
|
526
|
+
return this.generateOperation(node)
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
generateSubscription(node) {
|
|
530
|
+
node.operation = 'subscription'
|
|
531
|
+
return this.generateOperation(node)
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
generateField(node) {
|
|
535
|
+
const name = this.translate(node.name?.value || node.name)
|
|
536
|
+
const description = node.description?.value || node.description
|
|
537
|
+
const args = node.arguments || node.args || []
|
|
538
|
+
const type = this.generateType(node.type)
|
|
539
|
+
const directives = node.directives || []
|
|
540
|
+
|
|
541
|
+
if (description) {
|
|
542
|
+
this.writeDescription(description)
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
let fieldLine = name
|
|
546
|
+
|
|
547
|
+
if (args.length > 0) {
|
|
548
|
+
if (args.length <= 2) {
|
|
549
|
+
const argsStr = args.map(a => this.generateArgumentDefinition(a)).join(', ')
|
|
550
|
+
fieldLine += `(${argsStr})`
|
|
551
|
+
} else {
|
|
552
|
+
fieldLine += '('
|
|
553
|
+
this.writeLine(fieldLine)
|
|
554
|
+
this.indent++
|
|
555
|
+
for (let i = 0; i < args.length; i++) {
|
|
556
|
+
const argStr = this.generateArgumentDefinition(args[i])
|
|
557
|
+
this.writeLine(argStr + (i < args.length - 1 ? ',' : ''))
|
|
558
|
+
}
|
|
559
|
+
this.indent--
|
|
560
|
+
fieldLine = ')'
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
fieldLine += `: ${type}`
|
|
565
|
+
|
|
566
|
+
if (directives.length > 0) {
|
|
567
|
+
fieldLine += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
this.writeLine(fieldLine)
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
generateInputField(node) {
|
|
574
|
+
const name = this.translate(node.name?.value || node.name)
|
|
575
|
+
const description = node.description?.value || node.description
|
|
576
|
+
const type = this.generateType(node.type)
|
|
577
|
+
const defaultValue = node.defaultValue
|
|
578
|
+
const directives = node.directives || []
|
|
579
|
+
|
|
580
|
+
if (description) {
|
|
581
|
+
this.writeDescription(description)
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
let fieldLine = `${name}: ${type}`
|
|
585
|
+
|
|
586
|
+
if (defaultValue !== undefined) {
|
|
587
|
+
fieldLine += ` = ${this.generateValue(defaultValue)}`
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
if (directives.length > 0) {
|
|
591
|
+
fieldLine += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
this.writeLine(fieldLine)
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
generateArgumentDefinition(arg) {
|
|
598
|
+
const name = this.translate(arg.name?.value || arg.name)
|
|
599
|
+
const description = arg.description?.value || arg.description
|
|
600
|
+
const type = this.generateType(arg.type)
|
|
601
|
+
const defaultValue = arg.defaultValue
|
|
602
|
+
const directives = arg.directives || []
|
|
603
|
+
|
|
604
|
+
let argStr = `${name}: ${type}`
|
|
605
|
+
|
|
606
|
+
if (defaultValue !== undefined) {
|
|
607
|
+
argStr += ` = ${this.generateValue(defaultValue)}`
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
if (directives.length > 0) {
|
|
611
|
+
argStr += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
return argStr
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
generateType(type) {
|
|
618
|
+
if (!type) return 'String'
|
|
619
|
+
|
|
620
|
+
if (typeof type === 'string') {
|
|
621
|
+
return this.translateType(type)
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
const kind = type.kind || type.type
|
|
625
|
+
|
|
626
|
+
if (kind === 'NonNullType' || type.nonNull) {
|
|
627
|
+
const innerType = this.generateType(type.type || type.ofType)
|
|
628
|
+
return `${innerType}!`
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
if (kind === 'ListType' || type.list) {
|
|
632
|
+
const innerType = this.generateType(type.type || type.ofType)
|
|
633
|
+
return `[${innerType}]`
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
if (kind === 'NamedType' || type.name) {
|
|
637
|
+
return this.translateType(type.name?.value || type.name)
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
return this.translateType(String(type))
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
generateDirective(directive) {
|
|
644
|
+
const name = directive.name?.value || directive.name
|
|
645
|
+
const args = directive.arguments || directive.args || []
|
|
646
|
+
|
|
647
|
+
let result = `@${name}`
|
|
648
|
+
|
|
649
|
+
if (args.length > 0) {
|
|
650
|
+
const argsStr = args.map(a => {
|
|
651
|
+
const argName = a.name?.value || a.name
|
|
652
|
+
const argValue = this.generateValue(a.value)
|
|
653
|
+
return `${argName}: ${argValue}`
|
|
654
|
+
}).join(', ')
|
|
655
|
+
result += `(${argsStr})`
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
return result
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
generateVariableDefinition(variable) {
|
|
662
|
+
const name = variable.variable?.name?.value || variable.variable?.name || variable.name
|
|
663
|
+
const type = this.generateType(variable.type)
|
|
664
|
+
const defaultValue = variable.defaultValue
|
|
665
|
+
const directives = variable.directives || []
|
|
666
|
+
|
|
667
|
+
let varStr = `$${name}: ${type}`
|
|
668
|
+
|
|
669
|
+
if (defaultValue !== undefined) {
|
|
670
|
+
varStr += ` = ${this.generateValue(defaultValue)}`
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
if (directives.length > 0) {
|
|
674
|
+
varStr += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
return varStr
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
generateVariable(node) {
|
|
681
|
+
const name = node.name?.value || node.name
|
|
682
|
+
return `$${name}`
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
generateSelection(selection) {
|
|
686
|
+
const kind = selection.kind || selection.type
|
|
687
|
+
|
|
688
|
+
if (kind === 'Field') {
|
|
689
|
+
return this.generateFieldSelection(selection)
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
if (kind === 'FragmentSpread') {
|
|
693
|
+
const name = selection.name?.value || selection.name
|
|
694
|
+
const directives = selection.directives || []
|
|
695
|
+
let line = `...${name}`
|
|
696
|
+
if (directives.length > 0) {
|
|
697
|
+
line += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
698
|
+
}
|
|
699
|
+
this.writeLine(line)
|
|
700
|
+
return
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
if (kind === 'InlineFragment') {
|
|
704
|
+
return this.generateInlineFragment(selection)
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
if (selection.name && selection.selectionSet) {
|
|
708
|
+
return this.generateFieldSelection(selection)
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
if (selection.typeCondition) {
|
|
712
|
+
return this.generateInlineFragment(selection)
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
const name = selection.name?.value || selection.name || selection
|
|
716
|
+
this.writeLine(String(name))
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
generateFieldSelection(field) {
|
|
720
|
+
const alias = field.alias?.value || field.alias
|
|
721
|
+
const name = field.name?.value || field.name
|
|
722
|
+
const args = field.arguments || field.args || []
|
|
723
|
+
const directives = field.directives || []
|
|
724
|
+
const selections = field.selectionSet?.selections || field.selections || []
|
|
725
|
+
|
|
726
|
+
let fieldLine = ''
|
|
727
|
+
|
|
728
|
+
if (alias) {
|
|
729
|
+
fieldLine = `${alias}: ${name}`
|
|
730
|
+
} else {
|
|
731
|
+
fieldLine = name
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
if (args.length > 0) {
|
|
735
|
+
const argsStr = args.map(a => {
|
|
736
|
+
const argName = a.name?.value || a.name
|
|
737
|
+
const argValue = this.generateValue(a.value)
|
|
738
|
+
return `${argName}: ${argValue}`
|
|
739
|
+
}).join(', ')
|
|
740
|
+
fieldLine += `(${argsStr})`
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
if (directives.length > 0) {
|
|
744
|
+
fieldLine += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
if (selections.length > 0) {
|
|
748
|
+
this.writeLine(fieldLine + ' {')
|
|
749
|
+
this.indent++
|
|
750
|
+
for (const sel of selections) {
|
|
751
|
+
this.generateSelection(sel)
|
|
752
|
+
}
|
|
753
|
+
this.indent--
|
|
754
|
+
this.writeLine('}')
|
|
755
|
+
} else {
|
|
756
|
+
this.writeLine(fieldLine)
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
generateInlineFragment(fragment) {
|
|
761
|
+
const typeCondition = fragment.typeCondition?.name?.value || fragment.typeCondition
|
|
762
|
+
const directives = fragment.directives || []
|
|
763
|
+
const selections = fragment.selectionSet?.selections || fragment.selections || []
|
|
764
|
+
|
|
765
|
+
let line = '...'
|
|
766
|
+
if (typeCondition) {
|
|
767
|
+
line += ` on ${typeCondition}`
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
if (directives.length > 0) {
|
|
771
|
+
line += ' ' + directives.map(d => this.generateDirective(d)).join(' ')
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
this.writeLine(line + ' {')
|
|
775
|
+
this.indent++
|
|
776
|
+
|
|
777
|
+
for (const sel of selections) {
|
|
778
|
+
this.generateSelection(sel)
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
this.indent--
|
|
782
|
+
this.writeLine('}')
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
generateSelectionSet(node) {
|
|
786
|
+
const selections = node.selections || []
|
|
787
|
+
|
|
788
|
+
this.writeLine('{')
|
|
789
|
+
this.indent++
|
|
790
|
+
|
|
791
|
+
for (const sel of selections) {
|
|
792
|
+
this.generateSelection(sel)
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
this.indent--
|
|
796
|
+
this.writeLine('}')
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
generateValue(value) {
|
|
800
|
+
if (value === null || value === undefined) return 'null'
|
|
801
|
+
|
|
802
|
+
if (typeof value === 'string') {
|
|
803
|
+
if (value.startsWith('$')) return value
|
|
804
|
+
if (value.startsWith('"') || value.match(/^[A-Z_]+$/)) return value
|
|
805
|
+
return `"${value.replace(/"/g, '\\"')}"`
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
if (typeof value === 'number') return String(value)
|
|
809
|
+
if (typeof value === 'boolean') return value ? 'true' : 'false'
|
|
810
|
+
|
|
811
|
+
if (value.kind === 'Variable' || value.type === 'Variable') {
|
|
812
|
+
return this.generateVariable(value)
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
if (value.kind === 'IntValue') return value.value
|
|
816
|
+
if (value.kind === 'FloatValue') return value.value
|
|
817
|
+
if (value.kind === 'StringValue') return `"${value.value}"`
|
|
818
|
+
if (value.kind === 'BooleanValue') return value.value ? 'true' : 'false'
|
|
819
|
+
if (value.kind === 'NullValue') return 'null'
|
|
820
|
+
if (value.kind === 'EnumValue') return value.value
|
|
821
|
+
|
|
822
|
+
if (value.kind === 'ListValue' || Array.isArray(value.values || value)) {
|
|
823
|
+
const items = (value.values || value).map(v => this.generateValue(v))
|
|
824
|
+
return `[${items.join(', ')}]`
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
if (value.kind === 'ObjectValue' || value.fields) {
|
|
828
|
+
const fields = (value.fields || []).map(f => {
|
|
829
|
+
const fieldName = f.name?.value || f.name
|
|
830
|
+
const fieldValue = this.generateValue(f.value)
|
|
831
|
+
return `${fieldName}: ${fieldValue}`
|
|
832
|
+
})
|
|
833
|
+
return `{ ${fields.join(', ')} }`
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
if (value.value !== undefined) {
|
|
837
|
+
return this.generateValue(value.value)
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
return String(value)
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
writeDescription(description) {
|
|
844
|
+
if (!description) return
|
|
845
|
+
|
|
846
|
+
if (description.includes('\n')) {
|
|
847
|
+
this.writeLine('"""')
|
|
848
|
+
for (const line of description.split('\n')) {
|
|
849
|
+
this.writeLine(line)
|
|
850
|
+
}
|
|
851
|
+
this.writeLine('"""')
|
|
852
|
+
} else {
|
|
853
|
+
this.writeLine(`"${description}"`)
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
writeLine(text) {
|
|
858
|
+
this.output += this.getIndent() + text + '\n'
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
getIndent() {
|
|
862
|
+
return ' '.repeat(this.indent)
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
module.exports = {
|
|
867
|
+
GraphQLGenerator
|
|
868
|
+
}
|