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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +130 -0
  3. package/cli/compiler.js +298 -0
  4. package/cli/ether.js +532 -0
  5. package/cli/watcher.js +106 -0
  6. package/generators/css-generator.js +583 -0
  7. package/generators/graphql-generator.js +868 -0
  8. package/generators/html-generator.js +745 -0
  9. package/generators/js-generator.js +909 -0
  10. package/generators/node-generator.js +467 -0
  11. package/generators/php-generator.js +706 -0
  12. package/generators/python-generator.js +913 -0
  13. package/generators/react-generator.js +599 -0
  14. package/generators/ruby-generator.js +904 -0
  15. package/generators/sql-generator.js +988 -0
  16. package/generators/ts-generator.js +569 -0
  17. package/i18n/i18n-css.json +743 -0
  18. package/i18n/i18n-graphql.json +1531 -0
  19. package/i18n/i18n-html.json +572 -0
  20. package/i18n/i18n-js.json +2790 -0
  21. package/i18n/i18n-node.json +2442 -0
  22. package/i18n/i18n-php.json +4306 -0
  23. package/i18n/i18n-python.json +3080 -0
  24. package/i18n/i18n-react.json +1784 -0
  25. package/i18n/i18n-ruby.json +1858 -0
  26. package/i18n/i18n-sql.json +3466 -0
  27. package/i18n/i18n-ts.json +442 -0
  28. package/lexer/ether-lexer.js +728 -0
  29. package/lexer/tokens.js +292 -0
  30. package/package.json +45 -0
  31. package/parsers/ast-css.js +545 -0
  32. package/parsers/ast-graphql.js +424 -0
  33. package/parsers/ast-html.js +886 -0
  34. package/parsers/ast-js.js +750 -0
  35. package/parsers/ast-node.js +2440 -0
  36. package/parsers/ast-php.js +957 -0
  37. package/parsers/ast-react.js +580 -0
  38. package/parsers/ast-ruby.js +895 -0
  39. package/parsers/ast-ts.js +1352 -0
  40. package/parsers/css-parser.js +1981 -0
  41. package/parsers/graphql-parser.js +2011 -0
  42. package/parsers/html-parser.js +1181 -0
  43. package/parsers/js-parser.js +2564 -0
  44. package/parsers/node-parser.js +2644 -0
  45. package/parsers/php-parser.js +3037 -0
  46. package/parsers/react-parser.js +1035 -0
  47. package/parsers/ruby-parser.js +2680 -0
  48. package/parsers/ts-parser.js +3881 -0
@@ -0,0 +1,569 @@
1
+ const fs = require('fs')
2
+ const { JSGenerator } = require('./js-generator')
3
+
4
+ class TSGenerator extends JSGenerator {
5
+ constructor(i18nPath = null) {
6
+ super(i18nPath)
7
+ this.extendMaps()
8
+ }
9
+
10
+ extendMaps() {
11
+ const tsTranslations = {
12
+ 'type': 'type',
13
+ 'interface': 'interface',
14
+ 'enum': 'enum',
15
+ 'énumération': 'enum',
16
+ 'declare': 'declare',
17
+ 'déclarer': 'declare',
18
+ 'namespace': 'namespace',
19
+ 'espace de noms': 'namespace',
20
+ 'module': 'module',
21
+ 'abstract': 'abstract',
22
+ 'abstrait': 'abstract',
23
+ 'implements': 'implements',
24
+ 'implémente': 'implements',
25
+ 'extends': 'extends',
26
+ 'étend': 'extends',
27
+ 'readonly': 'readonly',
28
+ 'lecture seule': 'readonly',
29
+ 'public': 'public',
30
+ 'private': 'private',
31
+ 'privé': 'private',
32
+ 'protected': 'protected',
33
+ 'protégé': 'protected',
34
+ 'override': 'override',
35
+ 'remplacer': 'override',
36
+ 'keyof': 'keyof',
37
+ 'clé de': 'keyof',
38
+ 'typeof': 'typeof',
39
+ 'type de': 'typeof',
40
+ 'infer': 'infer',
41
+ 'inférer': 'infer',
42
+ 'satisfies': 'satisfies',
43
+ 'satisfait': 'satisfies',
44
+ 'as': 'as',
45
+ 'comme': 'as',
46
+ 'is': 'is',
47
+ 'est': 'is',
48
+ 'asserts': 'asserts',
49
+ 'affirme': 'asserts',
50
+ 'chaîne': 'string',
51
+ 'nombre': 'number',
52
+ 'booléen': 'boolean',
53
+ 'symbole': 'symbol',
54
+ 'vide': 'void',
55
+ 'nul type': 'null',
56
+ 'indefini type': 'undefined',
57
+ 'jamais': 'never',
58
+ 'inconnu': 'unknown',
59
+ 'quelconque': 'any',
60
+ 'objet': 'object',
61
+ 'tableau type': 'Array',
62
+ 'promesse': 'Promise',
63
+ 'partial': 'Partial',
64
+ 'partiel': 'Partial',
65
+ 'required': 'Required',
66
+ 'requis type': 'Required',
67
+ 'readonly type': 'Readonly',
68
+ 'record': 'Record',
69
+ 'enregistrement': 'Record',
70
+ 'pick': 'Pick',
71
+ 'choisir': 'Pick',
72
+ 'omit': 'Omit',
73
+ 'omettre': 'Omit',
74
+ 'exclude': 'Exclude',
75
+ 'exclure': 'Exclude',
76
+ 'extract': 'Extract',
77
+ 'extraire type': 'Extract',
78
+ 'nonnullable': 'NonNullable',
79
+ 'non nullable': 'NonNullable',
80
+ 'returntype': 'ReturnType',
81
+ 'type retour': 'ReturnType',
82
+ 'parameters': 'Parameters',
83
+ 'paramètres type': 'Parameters',
84
+ 'awaited': 'Awaited',
85
+ 'attendu type': 'Awaited'
86
+ }
87
+
88
+ for (const [fr, ts] of Object.entries(tsTranslations)) {
89
+ this.keywordMap[fr] = ts
90
+ }
91
+ }
92
+
93
+ generateNode(node) {
94
+ if (!node) return ''
95
+
96
+ switch (node.type) {
97
+ case 'TypeAlias':
98
+ case 'TypeAliasDeclaration':
99
+ return this.generateTypeAlias(node)
100
+ case 'InterfaceDeclaration':
101
+ return this.generateInterface(node)
102
+ case 'EnumDeclaration':
103
+ return this.generateEnum(node)
104
+ case 'TypeAnnotation':
105
+ return this.generateTypeAnnotation(node)
106
+ case 'GenericType':
107
+ return this.generateGenericType(node)
108
+ case 'UnionType':
109
+ return this.generateUnionType(node)
110
+ case 'IntersectionType':
111
+ return this.generateIntersectionType(node)
112
+ case 'TupleType':
113
+ return this.generateTupleType(node)
114
+ case 'FunctionType':
115
+ return this.generateFunctionType(node)
116
+ case 'ConditionalType':
117
+ return this.generateConditionalType(node)
118
+ case 'MappedType':
119
+ return this.generateMappedType(node)
120
+ case 'IndexedAccessType':
121
+ return this.generateIndexedAccessType(node)
122
+ case 'TypeAssertion':
123
+ return this.generateTypeAssertion(node)
124
+ case 'NamespaceDeclaration':
125
+ return this.generateNamespace(node)
126
+ default:
127
+ return super.generateNode(node)
128
+ }
129
+ }
130
+
131
+ generateTypeAlias(node) {
132
+ const name = node.name
133
+ const typeParams = node.typeParameters ? this.generateTypeParams(node.typeParameters) : ''
134
+ const typeNode = node.aliasType || node.typeValue ||
135
+ (typeof node.type === 'object' ? node.type : null)
136
+ const type = this.generateType(typeNode)
137
+
138
+ this.writeLine(`type ${name}${typeParams} = ${type};`)
139
+ }
140
+
141
+ generateInterface(node) {
142
+ const name = node.name
143
+ const typeParams = node.typeParameters ? this.generateTypeParams(node.typeParameters) : ''
144
+ const extend = node.extends && node.extends.length > 0
145
+ ? ' extends ' + node.extends.map(e => this.generateType(e)).join(', ')
146
+ : ''
147
+
148
+ this.writeLine(`interface ${name}${typeParams}${extend} {`)
149
+ this.indent++
150
+
151
+ for (const member of node.members || node.properties || []) {
152
+ this.generateInterfaceMember(member)
153
+ }
154
+
155
+ this.indent--
156
+ this.writeLine('}')
157
+ this.writeLine('')
158
+ }
159
+
160
+ generateInterfaceMember(member) {
161
+ const readonly = member.readonly ? 'readonly ' : ''
162
+ const optional = member.optional ? '?' : ''
163
+ const name = member.name || member.key
164
+
165
+ if (member.kind === 'method' || member.method) {
166
+ const typeParams = member.typeParameters ? this.generateTypeParams(member.typeParameters) : ''
167
+ const params = this.generateTypedParams(member.params || member.parameters || [])
168
+ const returnType = this.generateType(member.returnType || member.type || 'void')
169
+ this.writeLine(`${readonly}${name}${optional}${typeParams}(${params}): ${returnType};`)
170
+ } else if (member.kind === 'index' || member.index) {
171
+ const keyName = member.keyName || 'key'
172
+ const keyType = this.generateType(member.keyType || 'string')
173
+ const valueType = this.generateType(member.type || member.valueType || 'any')
174
+ this.writeLine(`[${keyName}: ${keyType}]: ${valueType};`)
175
+ } else {
176
+ const type = this.generateType(member.type || member.value)
177
+ this.writeLine(`${readonly}${name}${optional}: ${type};`)
178
+ }
179
+ }
180
+
181
+ generateEnum(node) {
182
+ const name = node.name
183
+ const isConst = node.const ? 'const ' : ''
184
+
185
+ this.writeLine(`${isConst}enum ${name} {`)
186
+ this.indent++
187
+
188
+ const members = node.members || []
189
+ for (let i = 0; i < members.length; i++) {
190
+ const member = members[i]
191
+ const memberName = member.name || member
192
+ const value = member.value !== undefined ? ` = ${this.generateNode(member.value)}` : ''
193
+ this.writeLine(`${memberName}${value},`)
194
+ }
195
+
196
+ this.indent--
197
+ this.writeLine('}')
198
+ }
199
+
200
+ generateType(type) {
201
+ if (!type) return 'any'
202
+ if (typeof type === 'string') return this.translate(type)
203
+
204
+ const typeKind = type.kind || (typeof type.type === 'string' ? type.type : null)
205
+
206
+ switch (typeKind) {
207
+ case 'string':
208
+ case 'chaîne':
209
+ return 'string'
210
+ case 'number':
211
+ case 'nombre':
212
+ return 'number'
213
+ case 'boolean':
214
+ case 'booléen':
215
+ return 'boolean'
216
+ case 'void':
217
+ return 'void'
218
+ case 'null':
219
+ return 'null'
220
+ case 'undefined':
221
+ return 'undefined'
222
+ case 'any':
223
+ return 'any'
224
+ case 'never':
225
+ return 'never'
226
+ case 'unknown':
227
+ return 'unknown'
228
+ case 'référence':
229
+ const refName = this.translate(type.name)
230
+ if (type.typeArguments) {
231
+ return `${refName}<${type.typeArguments.map(a => this.generateType(a)).join(', ')}>`
232
+ }
233
+ return refName
234
+ case 'literal':
235
+ if (typeof type.value === 'string') return `"${type.value}"`
236
+ if (typeof type.value === 'boolean') return type.value ? 'true' : 'false'
237
+ return String(type.value)
238
+ case 'union':
239
+ return (type.types || []).map(t => this.generateType(t)).join(' | ')
240
+ case 'intersection':
241
+ return (type.types || []).map(t => this.generateType(t)).join(' & ')
242
+ case 'array':
243
+ return `${this.generateType(type.elementType)}[]`
244
+ case 'tuple':
245
+ return `[${(type.elements || type.elementTypes || []).map(e => this.generateType(e)).join(', ')}]`
246
+ case 'generic':
247
+ const base = this.generateType(type.base)
248
+ const args = type.arguments.map(a => this.generateType(a)).join(', ')
249
+ return `${base}<${args}>`
250
+ case 'function':
251
+ const params = this.generateTypedParams(type.parameters || [])
252
+ const ret = this.generateType(type.returnType)
253
+ return `(${params}) => ${ret}`
254
+ case 'object':
255
+ return this.generateObjectType(type)
256
+ case 'conditional':
257
+ const check = this.generateType(type.checkType)
258
+ const ext = this.generateType(type.extendsType)
259
+ const trueT = this.generateType(type.trueType)
260
+ const falseT = this.generateType(type.falseType)
261
+ return `${check} extends ${ext} ? ${trueT} : ${falseT}`
262
+ case 'keyof':
263
+ return `keyof ${this.generateType(type.type || type.operand)}`
264
+ case 'typeof':
265
+ return `typeof ${type.expression || this.generateNode(type.operand)}`
266
+ case 'indexed':
267
+ return `${this.generateType(type.objectType || type.object)}[${this.generateType(type.indexType || type.index)}]`
268
+ case 'mapped':
269
+ return this.generateMappedType(type)
270
+ case 'infer':
271
+ return `infer ${type.name}`
272
+ case 'template':
273
+ return this.generateTemplateLiteralType(type)
274
+ default:
275
+ if (type.name) {
276
+ const name = this.translate(type.name)
277
+ if (type.typeArguments) {
278
+ return `${name}<${type.typeArguments.map(a => this.generateType(a)).join(', ')}>`
279
+ }
280
+ return name
281
+ }
282
+ return 'any'
283
+ }
284
+ }
285
+
286
+ generateTemplateLiteralType(type) {
287
+ const parts = (type.parts || []).map(p => {
288
+ if (typeof p === 'string') return p
289
+ if (p.name) return '${' + this.generateType(p) + '}'
290
+ return this.generateType(p)
291
+ })
292
+ return '`' + parts.join('') + '`'
293
+ }
294
+
295
+ generateObjectType(type) {
296
+ const members = (type.members || type.properties || []).map(m => {
297
+ const readonly = m.readonly ? 'readonly ' : ''
298
+ const optional = m.optional ? '?' : ''
299
+ const name = m.name || m.key
300
+ const memberType = this.generateType(m.type || m.value)
301
+ return `${readonly}${name}${optional}: ${memberType}`
302
+ })
303
+ return `{ ${members.join('; ')} }`
304
+ }
305
+
306
+ generateLiteralType(type) {
307
+ if (typeof type.value === 'string') return `"${type.value}"`
308
+ if (typeof type.value === 'boolean') return type.value ? 'true' : 'false'
309
+ return String(type.value)
310
+ }
311
+
312
+ generateMappedType(type) {
313
+ const readonly = type.readonly ? (type.readonly === '-' ? '-readonly ' : 'readonly ') : ''
314
+ const optional = type.optional ? (type.optional === '-' ? '-?' : '?') : ''
315
+
316
+ let key, constraint
317
+ if (type.typeParameter) {
318
+ key = type.typeParameter.name || 'K'
319
+ constraint = this.generateType(type.typeParameter.constraint)
320
+ } else {
321
+ key = type.key || 'K'
322
+ constraint = this.generateType(type.constraint)
323
+ }
324
+
325
+ const as = type.as ? ` as ${this.generateType(type.as)}` : ''
326
+ const valueType = this.generateType(type.valueType || type.value || type.type)
327
+
328
+ return `{ ${readonly}[${key} in ${constraint}${as}]${optional}: ${valueType} }`
329
+ }
330
+
331
+ generateTypeParams(params) {
332
+ const items = params.map(p => {
333
+ let param = p.name || p
334
+ if (p.constraint) {
335
+ param += ` extends ${this.generateType(p.constraint)}`
336
+ }
337
+ if (p.default) {
338
+ param += ` = ${this.generateType(p.default)}`
339
+ }
340
+ return param
341
+ })
342
+ return `<${items.join(', ')}>`
343
+ }
344
+
345
+ generateTypedParams(params) {
346
+ return params.map(p => {
347
+ let param = ''
348
+ if (p.rest) param += '...'
349
+ param += p.name || p.arg || p
350
+ if (p.optional) param += '?'
351
+ if (p.type) param += ': ' + this.generateType(p.type)
352
+ if (p.default !== undefined) {
353
+ param += ' = ' + this.generateNode(p.default)
354
+ }
355
+ return param
356
+ }).join(', ')
357
+ }
358
+
359
+ generateTypeAnnotation(node) {
360
+ return this.generateType(node.typeAnnotation || node.type)
361
+ }
362
+
363
+ generateGenericType(node) {
364
+ const base = this.generateType(node.base || node.name)
365
+ const args = (node.typeArguments || node.arguments || []).map(a => this.generateType(a))
366
+ return `${base}<${args.join(', ')}>`
367
+ }
368
+
369
+ generateUnionType(node) {
370
+ return (node.types || []).map(t => this.generateType(t)).join(' | ')
371
+ }
372
+
373
+ generateIntersectionType(node) {
374
+ return (node.types || []).map(t => this.generateType(t)).join(' & ')
375
+ }
376
+
377
+ generateTupleType(node) {
378
+ const elements = (node.elements || node.types || []).map(e => {
379
+ if (e.optional) return this.generateType(e.type) + '?'
380
+ if (e.rest) return '...' + this.generateType(e.type)
381
+ return this.generateType(e)
382
+ })
383
+ return `[${elements.join(', ')}]`
384
+ }
385
+
386
+ generateFunctionType(node) {
387
+ const params = this.generateTypedParams(node.parameters || [])
388
+ const returnType = this.generateType(node.returnType)
389
+ return `(${params}) => ${returnType}`
390
+ }
391
+
392
+ generateConditionalType(node) {
393
+ const check = this.generateType(node.checkType)
394
+ const ext = this.generateType(node.extendsType)
395
+ const trueType = this.generateType(node.trueType)
396
+ const falseType = this.generateType(node.falseType)
397
+ return `${check} extends ${ext} ? ${trueType} : ${falseType}`
398
+ }
399
+
400
+ generateIndexedAccessType(node) {
401
+ const object = this.generateType(node.objectType)
402
+ const index = this.generateType(node.indexType)
403
+ return `${object}[${index}]`
404
+ }
405
+
406
+ generateTypeAssertion(node) {
407
+ const expression = this.generateNode(node.expression)
408
+ const typeNode = node.typeAnnotation || node.assertedType ||
409
+ (node.type !== 'TypeAssertion' ? node.type : null)
410
+ const type = this.generateType(typeNode)
411
+
412
+ if (node.asStyle !== false) {
413
+ return `${expression} as ${type}`
414
+ }
415
+ return `<${type}>${expression}`
416
+ }
417
+
418
+ generateNamespace(node) {
419
+ const name = node.name
420
+ this.writeLine(`namespace ${name} {`)
421
+ this.indent++
422
+
423
+ for (const member of node.body || node.members || []) {
424
+ const exported = member.exported ? 'export ' : ''
425
+ if (exported) {
426
+ this.output += this.getIndent() + 'export '
427
+ }
428
+ this.generateNode(member)
429
+ }
430
+
431
+ this.indent--
432
+ this.writeLine('}')
433
+ this.writeLine('')
434
+ }
435
+
436
+ generateVariableDeclaration(node) {
437
+ const kind = this.translate(node.kind || 'let')
438
+
439
+ for (const decl of node.declarations || []) {
440
+ let name
441
+ if (typeof decl.id === 'string') {
442
+ name = decl.id
443
+ } else if (decl.id?.name) {
444
+ name = decl.id.name
445
+ } else if (typeof decl.name === 'string') {
446
+ name = decl.name
447
+ } else if (decl.name?.name) {
448
+ name = decl.name.name
449
+ } else {
450
+ name = this.generateNode(decl.id || decl.name)
451
+ }
452
+
453
+ const typeNode = decl.typeAnnotation || decl.type
454
+ const type = typeNode ? ': ' + this.generateType(typeNode) : ''
455
+
456
+ if (decl.init) {
457
+ const init = this.generateNode(decl.init)
458
+ this.writeLine(`${kind} ${name}${type} = ${init};`)
459
+ } else {
460
+ this.writeLine(`${kind} ${name}${type};`)
461
+ }
462
+ }
463
+ }
464
+
465
+ generateFunctionDeclaration(node) {
466
+ const async = node.async ? 'async ' : ''
467
+ const generator = node.generator ? '*' : ''
468
+ const name = this.translate(node.id?.name || node.name || '')
469
+ const typeParams = node.typeParameters ? this.generateTypeParams(node.typeParameters) : ''
470
+ const params = this.generateTypedParams(node.params || [])
471
+ const returnType = node.returnType ? ': ' + this.generateType(node.returnType) : ''
472
+
473
+ this.writeLine(`${async}function${generator} ${name}${typeParams}(${params})${returnType} {`)
474
+ this.indent++
475
+ this.generateNode(node.body)
476
+ this.indent--
477
+ this.writeLine('}')
478
+ this.writeLine('')
479
+ }
480
+
481
+ generateClassDeclaration(node) {
482
+ const abstract = node.abstract ? 'abstract ' : ''
483
+ const name = this.translate(node.id?.name || node.name || '')
484
+ const typeParams = node.typeParameters ? this.generateTypeParams(node.typeParameters) : ''
485
+ const extend = node.superClass ? ` extends ${this.generateNode(node.superClass)}` : ''
486
+ const implement = node.implements && node.implements.length > 0
487
+ ? ` implements ${node.implements.map(i => this.generateType(i)).join(', ')}`
488
+ : ''
489
+
490
+ this.writeLine(`${abstract}class ${name}${typeParams}${extend}${implement} {`)
491
+ this.indent++
492
+
493
+ const body = node.body?.body || node.body || []
494
+ for (const member of body) {
495
+ this.generateClassMemberTS(member)
496
+ }
497
+
498
+ this.indent--
499
+ this.writeLine('}')
500
+ this.writeLine('')
501
+ }
502
+
503
+ generateClassMemberTS(node) {
504
+ const visibility = node.accessibility || node.visibility || ''
505
+ const isStatic = node.static ? 'static ' : ''
506
+ const readonly = node.readonly ? 'readonly ' : ''
507
+ const abstract = node.abstract ? 'abstract ' : ''
508
+ const override = node.override ? 'override ' : ''
509
+
510
+ const modifiers = [visibility, isStatic, readonly, abstract, override].filter(m => m).join(' ')
511
+
512
+ if (node.kind === 'property' || node.type === 'PropertyDefinition' || node.property) {
513
+ const name = this.translate(node.key?.name || node.name || '')
514
+ const optional = node.optional ? '?' : ''
515
+ const typeNode = node.typeAnnotation || node.type
516
+ const type = typeNode && typeof typeNode === 'object' ? ': ' + this.generateType(typeNode) : ''
517
+ const value = node.value ? ' = ' + this.generateNode(node.value) : ''
518
+ this.writeLine(`${modifiers}${name}${optional}${type}${value};`)
519
+ return
520
+ }
521
+
522
+ const name = this.translate(node.key?.name || node.name || '')
523
+ const typeParams = node.typeParameters ? this.generateTypeParams(node.typeParameters) : ''
524
+ const params = this.generateTypedParams(node.value?.params || node.params || [])
525
+ const returnType = node.returnType ? ': ' + this.generateType(node.returnType) : ''
526
+
527
+ if (name === 'constructor' || name === 'constructeur') {
528
+ this.writeLine(`constructor(${params}) {`)
529
+ } else if (node.kind === 'get') {
530
+ this.writeLine(`${modifiers}get ${name}()${returnType} {`)
531
+ } else if (node.kind === 'set') {
532
+ this.writeLine(`${modifiers}set ${name}(${params}) {`)
533
+ } else {
534
+ const async = node.value?.async || node.async ? 'async ' : ''
535
+ this.writeLine(`${modifiers}${async}${name}${typeParams}(${params})${returnType} {`)
536
+ }
537
+
538
+ this.indent++
539
+ this.generateNode(node.value?.body || node.body)
540
+ this.indent--
541
+ this.writeLine('}')
542
+ this.writeLine('')
543
+ }
544
+
545
+ generateArrowFunction(node) {
546
+ const async = node.async ? 'async ' : ''
547
+ const params = this.generateTypedParams(node.params || [])
548
+ const returnType = node.returnType ? ': ' + this.generateType(node.returnType) : ''
549
+
550
+ if (node.body?.type === 'BlockStatement') {
551
+ let body = ''
552
+ const savedOutput = this.output
553
+ this.output = ''
554
+ this.indent++
555
+ this.generateNode(node.body)
556
+ this.indent--
557
+ body = this.output.trim()
558
+ this.output = savedOutput
559
+ return `${async}(${params})${returnType} => {\n${body}\n${this.getIndent()}}`
560
+ } else {
561
+ const body = this.generateNode(node.body)
562
+ return `${async}(${params})${returnType} => ${body}`
563
+ }
564
+ }
565
+ }
566
+
567
+ module.exports = {
568
+ TSGenerator
569
+ }