@atproto/lex-cli 0.5.7 → 0.6.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/CHANGELOG.md +26 -0
- package/dist/codegen/client.js +18 -50
- package/dist/codegen/client.js.map +1 -1
- package/dist/codegen/common.d.ts.map +1 -1
- package/dist/codegen/common.js +173 -22
- package/dist/codegen/common.js.map +1 -1
- package/dist/codegen/lex-gen.d.ts +4 -5
- package/dist/codegen/lex-gen.d.ts.map +1 -1
- package/dist/codegen/lex-gen.js +161 -49
- package/dist/codegen/lex-gen.js.map +1 -1
- package/dist/codegen/server.js +9 -45
- package/dist/codegen/server.js.map +1 -1
- package/package.json +3 -3
- package/src/codegen/client.ts +22 -60
- package/src/codegen/common.ts +182 -27
- package/src/codegen/lex-gen.ts +212 -71
- package/src/codegen/server.ts +12 -55
package/src/codegen/client.ts
CHANGED
|
@@ -9,9 +9,9 @@ import { NSID } from '@atproto/syntax'
|
|
|
9
9
|
import { GeneratedAPI } from '../types'
|
|
10
10
|
import { gen, lexiconsTs, utilTs } from './common'
|
|
11
11
|
import {
|
|
12
|
+
genCommonImports,
|
|
12
13
|
genImports,
|
|
13
|
-
|
|
14
|
-
genObject,
|
|
14
|
+
genRecord,
|
|
15
15
|
genUserType,
|
|
16
16
|
genXrpcInput,
|
|
17
17
|
genXrpcOutput,
|
|
@@ -70,9 +70,9 @@ const indexTs = (
|
|
|
70
70
|
{ name: 'FetchHandler' },
|
|
71
71
|
{ name: 'FetchHandlerOptions' },
|
|
72
72
|
])
|
|
73
|
-
//= import {schemas} from './lexicons'
|
|
73
|
+
//= import {schemas} from './lexicons.js'
|
|
74
74
|
file
|
|
75
|
-
.addImportDeclaration({ moduleSpecifier: './lexicons' })
|
|
75
|
+
.addImportDeclaration({ moduleSpecifier: './lexicons.js' })
|
|
76
76
|
.addNamedImports([{ name: 'schemas' }])
|
|
77
77
|
//= import {CID} from 'multiformats/cid'
|
|
78
78
|
file
|
|
@@ -81,9 +81,14 @@ const indexTs = (
|
|
|
81
81
|
})
|
|
82
82
|
.addNamedImports([{ name: 'CID' }])
|
|
83
83
|
|
|
84
|
+
//= import {OmitKey} from './util.js'
|
|
85
|
+
file
|
|
86
|
+
.addImportDeclaration({ moduleSpecifier: `./util.js` })
|
|
87
|
+
.addNamedImports([{ name: 'OmitKey' }, { name: 'Un$Typed' }])
|
|
88
|
+
|
|
84
89
|
// generate type imports and re-exports
|
|
85
90
|
for (const lexicon of lexiconDocs) {
|
|
86
|
-
const moduleSpecifier = `./types/${lexicon.id.split('.').join('/')}`
|
|
91
|
+
const moduleSpecifier = `./types/${lexicon.id.split('.').join('/')}.js`
|
|
87
92
|
file
|
|
88
93
|
.addImportDeclaration({ moduleSpecifier })
|
|
89
94
|
.setNamespaceImport(toTitleCase(lexicon.id))
|
|
@@ -312,7 +317,7 @@ function genRecordCls(file: SourceFile, nsid: string, lexRecord: LexRecord) {
|
|
|
312
317
|
})
|
|
313
318
|
method.addParameter({
|
|
314
319
|
name: 'params',
|
|
315
|
-
type: `
|
|
320
|
+
type: `OmitKey<${toTitleCase(ATP_METHODS.list)}.QueryParams, "collection">`,
|
|
316
321
|
})
|
|
317
322
|
method.setBodyText(
|
|
318
323
|
[
|
|
@@ -330,7 +335,7 @@ function genRecordCls(file: SourceFile, nsid: string, lexRecord: LexRecord) {
|
|
|
330
335
|
})
|
|
331
336
|
method.addParameter({
|
|
332
337
|
name: 'params',
|
|
333
|
-
type: `
|
|
338
|
+
type: `OmitKey<${toTitleCase(ATP_METHODS.get)}.QueryParams, "collection">`,
|
|
334
339
|
})
|
|
335
340
|
method.setBodyText(
|
|
336
341
|
[
|
|
@@ -348,13 +353,13 @@ function genRecordCls(file: SourceFile, nsid: string, lexRecord: LexRecord) {
|
|
|
348
353
|
})
|
|
349
354
|
method.addParameter({
|
|
350
355
|
name: 'params',
|
|
351
|
-
type: `
|
|
356
|
+
type: `OmitKey<${toTitleCase(
|
|
352
357
|
ATP_METHODS.create,
|
|
353
358
|
)}.InputSchema, "collection" | "record">`,
|
|
354
359
|
})
|
|
355
360
|
method.addParameter({
|
|
356
361
|
name: 'record',
|
|
357
|
-
type:
|
|
362
|
+
type: `Un$Typed<${typeModule}.Record>`,
|
|
358
363
|
})
|
|
359
364
|
method.addParameter({
|
|
360
365
|
name: 'headers?',
|
|
@@ -365,8 +370,8 @@ function genRecordCls(file: SourceFile, nsid: string, lexRecord: LexRecord) {
|
|
|
365
370
|
: ''
|
|
366
371
|
method.setBodyText(
|
|
367
372
|
[
|
|
368
|
-
`
|
|
369
|
-
`const res = await this._client.call('${ATP_METHODS.create}', undefined, { collection
|
|
373
|
+
`const collection = '${nsid}'`,
|
|
374
|
+
`const res = await this._client.call('${ATP_METHODS.create}', undefined, { collection, ${maybeRkeyPart}...params, record: { ...record, $type: collection} }, {encoding: 'application/json', headers })`,
|
|
370
375
|
`return res.data`,
|
|
371
376
|
].join('\n'),
|
|
372
377
|
)
|
|
@@ -380,7 +385,7 @@ function genRecordCls(file: SourceFile, nsid: string, lexRecord: LexRecord) {
|
|
|
380
385
|
// })
|
|
381
386
|
// method.addParameter({
|
|
382
387
|
// name: 'params',
|
|
383
|
-
// type: `
|
|
388
|
+
// type: `OmitKey<${toTitleCase(ATP_METHODS.put)}.InputSchema, "collection" | "record">`,
|
|
384
389
|
// })
|
|
385
390
|
// method.addParameter({
|
|
386
391
|
// name: 'record',
|
|
@@ -407,7 +412,7 @@ function genRecordCls(file: SourceFile, nsid: string, lexRecord: LexRecord) {
|
|
|
407
412
|
})
|
|
408
413
|
method.addParameter({
|
|
409
414
|
name: 'params',
|
|
410
|
-
type: `
|
|
415
|
+
type: `OmitKey<${toTitleCase(
|
|
411
416
|
ATP_METHODS.delete,
|
|
412
417
|
)}.InputSchema, "collection">`,
|
|
413
418
|
})
|
|
@@ -429,8 +434,6 @@ const lexiconTs = (project, lexicons: Lexicons, lexiconDoc: LexiconDoc) =>
|
|
|
429
434
|
project,
|
|
430
435
|
`/types/${lexiconDoc.id.split('.').join('/')}.ts`,
|
|
431
436
|
async (file) => {
|
|
432
|
-
const imports: Set<string> = new Set()
|
|
433
|
-
|
|
434
437
|
const main = lexiconDoc.defs.main
|
|
435
438
|
if (
|
|
436
439
|
main?.type === 'query' ||
|
|
@@ -446,37 +449,10 @@ const lexiconTs = (project, lexicons: Lexicons, lexiconDoc: LexiconDoc) =>
|
|
|
446
449
|
{ name: 'XRPCError' },
|
|
447
450
|
])
|
|
448
451
|
}
|
|
449
|
-
//= import {ValidationResult, BlobRef} from '@atproto/lexicon'
|
|
450
|
-
file
|
|
451
|
-
.addImportDeclaration({
|
|
452
|
-
moduleSpecifier: '@atproto/lexicon',
|
|
453
|
-
})
|
|
454
|
-
.addNamedImports([{ name: 'ValidationResult' }, { name: 'BlobRef' }])
|
|
455
|
-
//= import {isObj, hasProp} from '../../util.ts'
|
|
456
|
-
file
|
|
457
|
-
.addImportDeclaration({
|
|
458
|
-
moduleSpecifier: `${lexiconDoc.id
|
|
459
|
-
.split('.')
|
|
460
|
-
.map((_str) => '..')
|
|
461
|
-
.join('/')}/util`,
|
|
462
|
-
})
|
|
463
|
-
.addNamedImports([{ name: 'isObj' }, { name: 'hasProp' }])
|
|
464
|
-
//= import {lexicons} from '../../lexicons.ts'
|
|
465
|
-
file
|
|
466
|
-
.addImportDeclaration({
|
|
467
|
-
moduleSpecifier: `${lexiconDoc.id
|
|
468
|
-
.split('.')
|
|
469
|
-
.map((_str) => '..')
|
|
470
|
-
.join('/')}/lexicons`,
|
|
471
|
-
})
|
|
472
|
-
.addNamedImports([{ name: 'lexicons' }])
|
|
473
|
-
//= import {CID} from 'multiformats/cid'
|
|
474
|
-
file
|
|
475
|
-
.addImportDeclaration({
|
|
476
|
-
moduleSpecifier: 'multiformats/cid',
|
|
477
|
-
})
|
|
478
|
-
.addNamedImports([{ name: 'CID' }])
|
|
479
452
|
|
|
453
|
+
genCommonImports(file, lexiconDoc.id)
|
|
454
|
+
|
|
455
|
+
const imports: Set<string> = new Set()
|
|
480
456
|
for (const defId in lexiconDoc.defs) {
|
|
481
457
|
const def = lexiconDoc.defs[defId]
|
|
482
458
|
const lexUri = `${lexiconDoc.id}#${defId}`
|
|
@@ -489,7 +465,7 @@ const lexiconTs = (project, lexicons: Lexicons, lexiconDoc: LexiconDoc) =>
|
|
|
489
465
|
} else if (def.type === 'subscription') {
|
|
490
466
|
continue
|
|
491
467
|
} else if (def.type === 'record') {
|
|
492
|
-
|
|
468
|
+
genRecord(file, imports, lexicons, lexUri)
|
|
493
469
|
} else {
|
|
494
470
|
genUserType(file, imports, lexicons, lexUri)
|
|
495
471
|
}
|
|
@@ -586,17 +562,3 @@ function genClientXrpcCommon(
|
|
|
586
562
|
: ['return e'],
|
|
587
563
|
})
|
|
588
564
|
}
|
|
589
|
-
|
|
590
|
-
function genClientRecord(
|
|
591
|
-
file: SourceFile,
|
|
592
|
-
imports: Set<string>,
|
|
593
|
-
lexicons: Lexicons,
|
|
594
|
-
lexUri: string,
|
|
595
|
-
) {
|
|
596
|
-
const def = lexicons.getDefOrThrow(lexUri, ['record'])
|
|
597
|
-
|
|
598
|
-
//= export interface Record {...}
|
|
599
|
-
genObject(file, imports, lexUri, def.record, 'Record')
|
|
600
|
-
//= export function isRecord(v: unknown): v is Record {...}
|
|
601
|
-
genObjHelpers(file, lexUri, 'Record')
|
|
602
|
-
}
|
package/src/codegen/common.ts
CHANGED
|
@@ -1,28 +1,133 @@
|
|
|
1
|
-
import { format } from 'prettier'
|
|
1
|
+
import { Options as PrettierOptions, format } from 'prettier'
|
|
2
2
|
import { Project, SourceFile, VariableDeclarationKind } from 'ts-morph'
|
|
3
3
|
import { LexiconDoc } from '@atproto/lexicon'
|
|
4
4
|
import { GeneratedFile } from '../types'
|
|
5
5
|
|
|
6
|
-
const PRETTIER_OPTS = {
|
|
6
|
+
const PRETTIER_OPTS: PrettierOptions = {
|
|
7
7
|
parser: 'typescript',
|
|
8
8
|
tabWidth: 2,
|
|
9
9
|
semi: false,
|
|
10
10
|
singleQuote: true,
|
|
11
|
-
trailingComma: 'all'
|
|
11
|
+
trailingComma: 'all',
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export const utilTs = (project) =>
|
|
15
15
|
gen(project, '/util.ts', async (file) => {
|
|
16
16
|
file.replaceWithText(`
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
import { ValidationResult } from '@atproto/lexicon'
|
|
18
|
+
|
|
19
|
+
export type OmitKey<T, K extends keyof T> = {
|
|
20
|
+
[K2 in keyof T as K2 extends K ? never : K2]: T[K2]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type $Typed<V, T extends string = string> = V & { $type: T }
|
|
24
|
+
export type Un$Typed<V extends { $type?: string }> = OmitKey<V, '$type'>
|
|
25
|
+
|
|
26
|
+
export type $Type<Id extends string, Hash extends string> = Hash extends 'main'
|
|
27
|
+
? Id
|
|
28
|
+
: \`\${Id}#\${Hash}\`
|
|
29
|
+
|
|
30
|
+
function isObject<V>(v: V): v is V & object {
|
|
31
|
+
return v != null && typeof v === 'object'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function is$type<Id extends string, Hash extends string>(
|
|
35
|
+
$type: unknown,
|
|
36
|
+
id: Id,
|
|
37
|
+
hash: Hash,
|
|
38
|
+
): $type is $Type<Id, Hash> {
|
|
39
|
+
return hash === 'main'
|
|
40
|
+
? $type === id
|
|
41
|
+
: // $type === \`\${id}#\${hash}\`
|
|
42
|
+
typeof $type === 'string' &&
|
|
43
|
+
$type.length === id.length + 1 + hash.length &&
|
|
44
|
+
$type.charCodeAt(id.length) === 35 /* '#' */ &&
|
|
45
|
+
$type.startsWith(id) &&
|
|
46
|
+
$type.endsWith(hash)
|
|
47
|
+
}
|
|
48
|
+
${
|
|
49
|
+
/**
|
|
50
|
+
* The construct below allows to properly distinguish open unions. Consider
|
|
51
|
+
* the following example:
|
|
52
|
+
*
|
|
53
|
+
* ```ts
|
|
54
|
+
* type Foo = { $type?: $Type<'foo', 'main'>; foo: string }
|
|
55
|
+
* type Bar = { $type?: $Type<'bar', 'main'>; bar: string }
|
|
56
|
+
* type OpenFooBarUnion = $Typed<Foo> | $Typed<Bar> | { $type: string }
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* In the context of lexicons, when there is a open union as shown above, the
|
|
60
|
+
* if `$type` if either `foo` or `bar`, then the object IS of type `Foo` or
|
|
61
|
+
* `Bar`.
|
|
62
|
+
*
|
|
63
|
+
* ```ts
|
|
64
|
+
* declare const obj1: OpenFooBarUnion
|
|
65
|
+
* if (is$typed(obj1, 'foo', 'main')) {
|
|
66
|
+
* obj1.$type // $Type<'foo', 'main'>
|
|
67
|
+
* obj1.foo // string
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* Similarly, if an object is of type `unknown`, then the `is$typed` function
|
|
72
|
+
* should only return assurance about the `$type` property, which is what it
|
|
73
|
+
* actually checks:
|
|
74
|
+
*
|
|
75
|
+
* ```ts
|
|
76
|
+
* declare const obj2: unknown
|
|
77
|
+
* if (is$typed(obj2, 'foo', 'main')) {
|
|
78
|
+
* obj2.$type // $Type<'foo', 'main'>
|
|
79
|
+
* // @ts-expect-error
|
|
80
|
+
* obj2.foo
|
|
81
|
+
* }
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
84
|
+
* The construct bellow is what makes these two scenarios possible.
|
|
85
|
+
*/
|
|
86
|
+
''
|
|
19
87
|
}
|
|
88
|
+
export type $TypedObject<V, Id extends string, Hash extends string> = V extends {
|
|
89
|
+
$type: $Type<Id, Hash>
|
|
90
|
+
}
|
|
91
|
+
? V
|
|
92
|
+
: V extends { $type?: string }
|
|
93
|
+
? V extends { $type?: infer T extends $Type<Id, Hash> }
|
|
94
|
+
? V & { $type: T }
|
|
95
|
+
: never
|
|
96
|
+
: V & { $type: $Type<Id, Hash> }
|
|
97
|
+
|
|
98
|
+
export function is$typed<V, Id extends string, Hash extends string>(
|
|
99
|
+
v: V,
|
|
100
|
+
id: Id,
|
|
101
|
+
hash: Hash,
|
|
102
|
+
): v is $TypedObject<V, Id, Hash> {
|
|
103
|
+
return isObject(v) && '$type' in v && is$type(v.$type, id, hash)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function maybe$typed<V, Id extends string, Hash extends string>(
|
|
107
|
+
v: V,
|
|
108
|
+
id: Id,
|
|
109
|
+
hash: Hash,
|
|
110
|
+
): v is V & object & { $type?: $Type<Id, Hash> } {
|
|
111
|
+
return (
|
|
112
|
+
isObject(v) &&
|
|
113
|
+
('$type' in v
|
|
114
|
+
? v.$type === undefined || is$type(v.$type, id, hash)
|
|
115
|
+
: true)
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export type Validator<R = unknown> = (v: unknown) => ValidationResult<R>
|
|
120
|
+
export type ValidatorParam<V extends Validator> =
|
|
121
|
+
V extends Validator<infer R> ? R : never
|
|
20
122
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
123
|
+
/**
|
|
124
|
+
* Utility function that allows to convert a "validate*" utility function into a
|
|
125
|
+
* type predicate.
|
|
126
|
+
*/
|
|
127
|
+
export function asPredicate<V extends Validator>(validate: V) {
|
|
128
|
+
return function <T>(v: T): v is T & ValidatorParam<V> {
|
|
129
|
+
return validate(v).success
|
|
130
|
+
}
|
|
26
131
|
}
|
|
27
132
|
`)
|
|
28
133
|
})
|
|
@@ -41,7 +146,23 @@ export const lexiconsTs = (project, lexicons: LexiconDoc[]) =>
|
|
|
41
146
|
.addImportDeclaration({
|
|
42
147
|
moduleSpecifier: '@atproto/lexicon',
|
|
43
148
|
})
|
|
44
|
-
.addNamedImports([
|
|
149
|
+
.addNamedImports([
|
|
150
|
+
{ name: 'LexiconDoc' },
|
|
151
|
+
{ name: 'Lexicons' },
|
|
152
|
+
{ name: 'ValidationError' },
|
|
153
|
+
{ name: 'ValidationResult' },
|
|
154
|
+
])
|
|
155
|
+
|
|
156
|
+
//= import {is$typed, maybe$typed, $Typed} from './util'
|
|
157
|
+
file
|
|
158
|
+
.addImportDeclaration({
|
|
159
|
+
moduleSpecifier: './util.js',
|
|
160
|
+
})
|
|
161
|
+
.addNamedImports([
|
|
162
|
+
{ name: '$Typed' },
|
|
163
|
+
{ name: 'is$typed' },
|
|
164
|
+
{ name: 'maybe$typed' },
|
|
165
|
+
])
|
|
45
166
|
|
|
46
167
|
//= export const schemaDict = {...} as const satisfies Record<string, LexiconDoc>
|
|
47
168
|
file.addVariableStatement({
|
|
@@ -66,14 +187,14 @@ export const lexiconsTs = (project, lexicons: LexiconDoc[]) =>
|
|
|
66
187
|
],
|
|
67
188
|
})
|
|
68
189
|
|
|
69
|
-
//= export const schemas = Object.values(schemaDict)
|
|
190
|
+
//= export const schemas = Object.values(schemaDict) satisfies LexiconDoc[]
|
|
70
191
|
file.addVariableStatement({
|
|
71
192
|
isExported: true,
|
|
72
193
|
declarationKind: VariableDeclarationKind.Const,
|
|
73
194
|
declarations: [
|
|
74
195
|
{
|
|
75
196
|
name: 'schemas',
|
|
76
|
-
initializer: 'Object.values(schemaDict)',
|
|
197
|
+
initializer: 'Object.values(schemaDict) satisfies LexiconDoc[]',
|
|
77
198
|
},
|
|
78
199
|
],
|
|
79
200
|
})
|
|
@@ -91,6 +212,44 @@ export const lexiconsTs = (project, lexicons: LexiconDoc[]) =>
|
|
|
91
212
|
],
|
|
92
213
|
})
|
|
93
214
|
|
|
215
|
+
file.addFunction({
|
|
216
|
+
isExported: true,
|
|
217
|
+
name: 'validate',
|
|
218
|
+
overloads: [
|
|
219
|
+
{
|
|
220
|
+
typeParameters: ['T extends { $type: string }'],
|
|
221
|
+
parameters: [
|
|
222
|
+
{ name: 'v', type: 'unknown' },
|
|
223
|
+
{ name: 'id', type: 'string' },
|
|
224
|
+
{ name: 'hash', type: 'string' },
|
|
225
|
+
{ name: 'requiredType', type: 'true' },
|
|
226
|
+
],
|
|
227
|
+
returnType: 'ValidationResult<T>',
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
typeParameters: ['T extends { $type?: string }'],
|
|
231
|
+
parameters: [
|
|
232
|
+
{ name: 'v', type: 'unknown' },
|
|
233
|
+
{ name: 'id', type: 'string' },
|
|
234
|
+
{ name: 'hash', type: 'string' },
|
|
235
|
+
{ name: 'requiredType', type: 'false', hasQuestionToken: true },
|
|
236
|
+
],
|
|
237
|
+
returnType: 'ValidationResult<T>',
|
|
238
|
+
},
|
|
239
|
+
],
|
|
240
|
+
parameters: [
|
|
241
|
+
{ name: 'v', type: 'unknown' },
|
|
242
|
+
{ name: 'id', type: 'string' },
|
|
243
|
+
{ name: 'hash', type: 'string' },
|
|
244
|
+
{ name: 'requiredType', type: 'boolean', hasQuestionToken: true },
|
|
245
|
+
],
|
|
246
|
+
statements: [
|
|
247
|
+
// If $type is present, make sure it is valid before validating the rest of the object
|
|
248
|
+
'return (requiredType ? is$typed : maybe$typed)(v, id, hash) ? lexicons.validate(`${id}#${hash}`, v) : { success: false, error: new ValidationError(`Must be an object with "${hash === \'main\' ? id : `${id}#${hash}`}" $type property`) }',
|
|
249
|
+
],
|
|
250
|
+
returnType: 'ValidationResult',
|
|
251
|
+
})
|
|
252
|
+
|
|
94
253
|
//= export const ids = {...}
|
|
95
254
|
file.addVariableStatement({
|
|
96
255
|
isExported: true,
|
|
@@ -98,14 +257,11 @@ export const lexiconsTs = (project, lexicons: LexiconDoc[]) =>
|
|
|
98
257
|
declarations: [
|
|
99
258
|
{
|
|
100
259
|
name: 'ids',
|
|
101
|
-
initializer:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
}, {}),
|
|
108
|
-
),
|
|
260
|
+
initializer: `{${lexicons
|
|
261
|
+
.map(
|
|
262
|
+
(lex) => `\n ${nsidToEnum(lex.id)}: ${JSON.stringify(lex.id)},`,
|
|
263
|
+
)
|
|
264
|
+
.join('')}\n} as const`,
|
|
109
265
|
},
|
|
110
266
|
],
|
|
111
267
|
})
|
|
@@ -118,12 +274,11 @@ export async function gen(
|
|
|
118
274
|
): Promise<GeneratedFile> {
|
|
119
275
|
const file = project.createSourceFile(path)
|
|
120
276
|
await gen(file)
|
|
121
|
-
file.
|
|
122
|
-
const src =
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
277
|
+
await file.save() // Save in the "in memory" file system
|
|
278
|
+
const src = `${banner()}${file.getFullText()}`
|
|
279
|
+
const content = await format(src, PRETTIER_OPTS)
|
|
280
|
+
|
|
281
|
+
return { path, content }
|
|
127
282
|
}
|
|
128
283
|
|
|
129
284
|
function banner() {
|