@nestia/migrate 0.11.4 → 0.11.6

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 (53) hide show
  1. package/lib/bundles/NEST_TEMPLATE.js +5 -5
  2. package/lib/bundles/NEST_TEMPLATE.js.map +1 -1
  3. package/lib/bundles/SDK_TEMPLATE.js +29 -4
  4. package/lib/bundles/SDK_TEMPLATE.js.map +1 -1
  5. package/lib/utils/openapi-down-convert/converter.js +2 -2
  6. package/package.json +2 -2
  7. package/src/MigrateApplication.ts +81 -81
  8. package/src/analyzers/MigrateAnalyzer.ts +9 -9
  9. package/src/analyzers/MigrateControllerAnalyzer.ts +135 -135
  10. package/src/analyzers/MigrateMethodAnalyzer.ts +439 -439
  11. package/src/archivers/MigrateFileArchiver.ts +38 -38
  12. package/src/bundles/NEST_TEMPLATE.ts +5 -5
  13. package/src/bundles/SDK_TEMPLATE.ts +29 -4
  14. package/src/executable/bundle.ts +110 -110
  15. package/src/internal/MigrateCommander.ts +70 -70
  16. package/src/internal/MigrateInquirer.ts +86 -86
  17. package/src/module.ts +14 -14
  18. package/src/programmers/MigrateApiFileProgrammer.ts +53 -53
  19. package/src/programmers/MigrateApiFunctionProgrammer.ts +199 -199
  20. package/src/programmers/MigrateApiNamespaceProgrammer.ts +431 -431
  21. package/src/programmers/MigrateApiProgrammer.ts +170 -170
  22. package/src/programmers/MigrateApiSimulatationProgrammer.ts +327 -327
  23. package/src/programmers/MigrateApiStartProgrammer.ts +194 -194
  24. package/src/programmers/MigrateDtoProgrammer.ts +78 -78
  25. package/src/programmers/MigrateE2eFileProgrammer.ts +117 -117
  26. package/src/programmers/MigrateE2eProgrammer.ts +36 -36
  27. package/src/programmers/MigrateImportProgrammer.ts +121 -121
  28. package/src/programmers/MigrateNestControllerProgrammer.ts +50 -50
  29. package/src/programmers/MigrateNestMethodProgrammer.ts +250 -250
  30. package/src/programmers/MigrateNestModuleProgrammer.ts +63 -63
  31. package/src/programmers/MigrateNestProgrammer.ts +74 -74
  32. package/src/programmers/MigrateSchemaProgrammer.ts +267 -267
  33. package/src/structures/IMigrateDto.ts +8 -8
  34. package/src/structures/IMigrateProgram.ts +27 -27
  35. package/src/structures/IMigrateRoute.ts +51 -51
  36. package/src/structures/ISwagger.ts +23 -23
  37. package/src/structures/ISwaggerComponents.ts +14 -14
  38. package/src/structures/ISwaggerRoute.ts +20 -20
  39. package/src/structures/ISwaggerRouteBodyContent.ts +15 -15
  40. package/src/structures/ISwaggerRouteParameter.ts +14 -14
  41. package/src/structures/ISwaggerRouteRequestBody.ts +12 -12
  42. package/src/structures/ISwaggerRouteResponse.ts +11 -11
  43. package/src/structures/ISwaggerSchema.ts +90 -90
  44. package/src/structures/ISwaggerSecurityScheme.ts +47 -47
  45. package/src/structures/ISwaggerV20.ts +10 -10
  46. package/src/structures/ISwaggerV31.ts +10 -10
  47. package/src/utils/FilePrinter.ts +36 -36
  48. package/src/utils/OpenApiConverter.ts +19 -19
  49. package/src/utils/StringUtil.ts +60 -60
  50. package/src/utils/SwaggerComponentsExplorer.ts +43 -43
  51. package/src/utils/SwaggerTypeChecker.ts +67 -67
  52. package/src/utils/openapi-down-convert/RefVisitor.ts +139 -139
  53. package/src/utils/openapi-down-convert/converter.ts +527 -527
@@ -1,250 +1,250 @@
1
- import ts from "typescript";
2
- import { ExpressionFactory } from "typia/lib/factories/ExpressionFactory";
3
- import { IdentifierFactory } from "typia/lib/factories/IdentifierFactory";
4
- import { TypeFactory } from "typia/lib/factories/TypeFactory";
5
-
6
- import { IMigrateRoute } from "../structures/IMigrateRoute";
7
- import { ISwaggerComponents } from "../structures/ISwaggerComponents";
8
- import { ISwaggerSchema } from "../structures/ISwaggerSchema";
9
- import { FilePrinter } from "../utils/FilePrinter";
10
- import { StringUtil } from "../utils/StringUtil";
11
- import { MigrateImportProgrammer } from "./MigrateImportProgrammer";
12
- import { MigrateSchemaProgrammer } from "./MigrateSchemaProgrammer";
13
-
14
- export namespace MigrateNestMethodProgrammer {
15
- export const write =
16
- (components: ISwaggerComponents) =>
17
- (importer: MigrateImportProgrammer) =>
18
- (route: IMigrateRoute): ts.MethodDeclaration => {
19
- const output: ts.TypeNode = route.success
20
- ? MigrateSchemaProgrammer.write(components)(importer)(
21
- route.success.schema,
22
- )
23
- : TypeFactory.keyword("void");
24
-
25
- const method: ts.MethodDeclaration = ts.factory.createMethodDeclaration(
26
- [
27
- ...writeMethodDecorators(components)(importer)(route),
28
- ts.factory.createToken(ts.SyntaxKind.PublicKeyword),
29
- ts.factory.createToken(ts.SyntaxKind.AsyncKeyword),
30
- ],
31
- undefined,
32
- route.name,
33
- undefined,
34
- undefined,
35
- writeParameters(components)(importer)(route),
36
- ts.factory.createTypeReferenceNode("Promise", [output]),
37
- ts.factory.createBlock(
38
- [
39
- ...[
40
- ...route.parameters.map((p) => StringUtil.normalize(p.key)),
41
- ...(route.headers ? ["headers"] : []),
42
- ...(route.query ? ["query"] : []),
43
- ...(route.body ? ["body"] : []),
44
- ].map((str) =>
45
- ts.factory.createExpressionStatement(
46
- ts.factory.createIdentifier(str),
47
- ),
48
- ),
49
- ts.factory.createReturnStatement(
50
- ts.factory.createCallExpression(
51
- IdentifierFactory.access(
52
- ts.factory.createIdentifier(
53
- importer.external({
54
- type: "default",
55
- library: "typia",
56
- name: "typia",
57
- }),
58
- ),
59
- )("random"),
60
- [output],
61
- undefined,
62
- ),
63
- ),
64
- ],
65
- true,
66
- ),
67
- );
68
- return FilePrinter.description(method, writeDescription(route));
69
- };
70
-
71
- const writeDescription = (method: IMigrateRoute): string =>
72
- [
73
- method.comment(),
74
- "@nestia Generated by Nestia - https://github.com/samchon/nestia",
75
- ].join("\n");
76
-
77
- const writeMethodDecorators =
78
- (components: ISwaggerComponents) =>
79
- (importer: MigrateImportProgrammer) =>
80
- (route: IMigrateRoute): ts.Decorator[] => {
81
- const external =
82
- (lib: string) =>
83
- (instance: string): ts.Identifier =>
84
- ts.factory.createIdentifier(
85
- importer.external({
86
- type: "instance",
87
- library: lib,
88
- name: instance,
89
- }),
90
- );
91
- const router = (instance: string) =>
92
- ts.factory.createDecorator(
93
- ts.factory.createCallExpression(
94
- IdentifierFactory.access(external("@nestia/core")(instance))(
95
- StringUtil.capitalize(route.method),
96
- ),
97
- [],
98
- [ts.factory.createStringLiteral(route.path)],
99
- ),
100
- );
101
-
102
- const decorators: ts.Decorator[] = [];
103
- if (route.success?.["x-nestia-encrypted"])
104
- decorators.push(router("EncryptedRoute"));
105
- else if (route.success?.type === "text/plain")
106
- decorators.push(
107
- ts.factory.createDecorator(
108
- ts.factory.createCallExpression(
109
- external("@nestjs/common")(StringUtil.capitalize(route.method)),
110
- [],
111
- [ts.factory.createStringLiteral(route.path)],
112
- ),
113
- ),
114
- );
115
- else if (route.success?.type === "application/x-www-form-urlencoded")
116
- decorators.push(router("TypedQuery"));
117
- else if (route.method === "head")
118
- decorators.push(
119
- ts.factory.createDecorator(
120
- ts.factory.createCallExpression(
121
- external("@nestjs/common")("Head"),
122
- [],
123
- [ts.factory.createStringLiteral(route.path)],
124
- ),
125
- ),
126
- );
127
- else if (
128
- route.success === null ||
129
- route.success?.type === "application/json"
130
- )
131
- decorators.push(router("TypedRoute"));
132
- for (const [key, value] of Object.entries(route.exceptions ?? {}))
133
- decorators.push(
134
- ts.factory.createDecorator(
135
- ts.factory.createCallExpression(
136
- external("@nestia/core")("TypedException"),
137
- [
138
- MigrateSchemaProgrammer.write(components)(importer)(
139
- value.schema,
140
- ),
141
- ],
142
- [
143
- isNaN(Number(key))
144
- ? ts.factory.createStringLiteral(key)
145
- : ExpressionFactory.number(Number(key)),
146
- ...(value.description?.length
147
- ? [ts.factory.createStringLiteral(value.description)]
148
- : []),
149
- ],
150
- ),
151
- ),
152
- );
153
- return decorators;
154
- };
155
-
156
- const writeParameters =
157
- (components: ISwaggerComponents) =>
158
- (importer: MigrateImportProgrammer) =>
159
- (route: IMigrateRoute): ts.ParameterDeclaration[] => [
160
- ...route.parameters.map(({ key, schema: value }) =>
161
- ts.factory.createParameterDeclaration(
162
- [
163
- ts.factory.createDecorator(
164
- ts.factory.createCallExpression(
165
- ts.factory.createIdentifier(
166
- importer.external({
167
- type: "instance",
168
- library: "@nestia/core",
169
- name: "TypedParam",
170
- }),
171
- ),
172
- undefined,
173
- [ts.factory.createStringLiteral(key)],
174
- ),
175
- ),
176
- ],
177
- undefined,
178
- StringUtil.normalize(key),
179
- undefined,
180
- MigrateSchemaProgrammer.write(components)(importer)(value),
181
- ),
182
- ),
183
- ...(route.headers
184
- ? [
185
- writeDtoParameter({ method: "TypedHeaders", variable: "headers" })(
186
- components,
187
- )(importer)(route.headers.schema),
188
- ]
189
- : []),
190
- ...(route.query
191
- ? [
192
- writeDtoParameter({ method: "TypedQuery", variable: "query" })(
193
- components,
194
- )(importer)(route.query.schema),
195
- ]
196
- : []),
197
- ...(route.body
198
- ? [
199
- writeDtoParameter({
200
- method: route.body["x-nestia-encrypted"]
201
- ? "EncryptedBody"
202
- : route.body.type === "application/json"
203
- ? "TypedBody"
204
- : route.body.type === "application/x-www-form-urlencoded"
205
- ? ["TypedQuery", "Body"]
206
- : route.body.type === "text/plain"
207
- ? "PlainBody"
208
- : route.body.type === "multipart/form-data"
209
- ? ["TypedFormData", "Body"]
210
- : "TypedBody",
211
- variable: "body",
212
- })(components)(importer)(route.body.schema),
213
- ]
214
- : []),
215
- ];
216
-
217
- const writeDtoParameter =
218
- (accessor: { method: string | [string, string]; variable: string }) =>
219
- (components: ISwaggerComponents) =>
220
- (importer: MigrateImportProgrammer) =>
221
- (schema: ISwaggerSchema): ts.ParameterDeclaration => {
222
- const instance = ts.factory.createIdentifier(
223
- importer.external({
224
- type: "instance",
225
- library: "@nestia/core",
226
- name:
227
- typeof accessor.method === "string"
228
- ? accessor.method
229
- : accessor.method[0],
230
- }),
231
- );
232
- return ts.factory.createParameterDeclaration(
233
- [
234
- ts.factory.createDecorator(
235
- ts.factory.createCallExpression(
236
- typeof accessor.method === "string"
237
- ? instance
238
- : IdentifierFactory.access(instance)(accessor.method[1]),
239
- undefined,
240
- undefined,
241
- ),
242
- ),
243
- ],
244
- undefined,
245
- StringUtil.normalize(accessor.variable),
246
- undefined,
247
- MigrateSchemaProgrammer.write(components)(importer)(schema),
248
- );
249
- };
250
- }
1
+ import ts from "typescript";
2
+ import { ExpressionFactory } from "typia/lib/factories/ExpressionFactory";
3
+ import { IdentifierFactory } from "typia/lib/factories/IdentifierFactory";
4
+ import { TypeFactory } from "typia/lib/factories/TypeFactory";
5
+
6
+ import { IMigrateRoute } from "../structures/IMigrateRoute";
7
+ import { ISwaggerComponents } from "../structures/ISwaggerComponents";
8
+ import { ISwaggerSchema } from "../structures/ISwaggerSchema";
9
+ import { FilePrinter } from "../utils/FilePrinter";
10
+ import { StringUtil } from "../utils/StringUtil";
11
+ import { MigrateImportProgrammer } from "./MigrateImportProgrammer";
12
+ import { MigrateSchemaProgrammer } from "./MigrateSchemaProgrammer";
13
+
14
+ export namespace MigrateNestMethodProgrammer {
15
+ export const write =
16
+ (components: ISwaggerComponents) =>
17
+ (importer: MigrateImportProgrammer) =>
18
+ (route: IMigrateRoute): ts.MethodDeclaration => {
19
+ const output: ts.TypeNode = route.success
20
+ ? MigrateSchemaProgrammer.write(components)(importer)(
21
+ route.success.schema,
22
+ )
23
+ : TypeFactory.keyword("void");
24
+
25
+ const method: ts.MethodDeclaration = ts.factory.createMethodDeclaration(
26
+ [
27
+ ...writeMethodDecorators(components)(importer)(route),
28
+ ts.factory.createToken(ts.SyntaxKind.PublicKeyword),
29
+ ts.factory.createToken(ts.SyntaxKind.AsyncKeyword),
30
+ ],
31
+ undefined,
32
+ route.name,
33
+ undefined,
34
+ undefined,
35
+ writeParameters(components)(importer)(route),
36
+ ts.factory.createTypeReferenceNode("Promise", [output]),
37
+ ts.factory.createBlock(
38
+ [
39
+ ...[
40
+ ...route.parameters.map((p) => StringUtil.normalize(p.key)),
41
+ ...(route.headers ? ["headers"] : []),
42
+ ...(route.query ? ["query"] : []),
43
+ ...(route.body ? ["body"] : []),
44
+ ].map((str) =>
45
+ ts.factory.createExpressionStatement(
46
+ ts.factory.createIdentifier(str),
47
+ ),
48
+ ),
49
+ ts.factory.createReturnStatement(
50
+ ts.factory.createCallExpression(
51
+ IdentifierFactory.access(
52
+ ts.factory.createIdentifier(
53
+ importer.external({
54
+ type: "default",
55
+ library: "typia",
56
+ name: "typia",
57
+ }),
58
+ ),
59
+ )("random"),
60
+ [output],
61
+ undefined,
62
+ ),
63
+ ),
64
+ ],
65
+ true,
66
+ ),
67
+ );
68
+ return FilePrinter.description(method, writeDescription(route));
69
+ };
70
+
71
+ const writeDescription = (method: IMigrateRoute): string =>
72
+ [
73
+ method.comment(),
74
+ "@nestia Generated by Nestia - https://github.com/samchon/nestia",
75
+ ].join("\n");
76
+
77
+ const writeMethodDecorators =
78
+ (components: ISwaggerComponents) =>
79
+ (importer: MigrateImportProgrammer) =>
80
+ (route: IMigrateRoute): ts.Decorator[] => {
81
+ const external =
82
+ (lib: string) =>
83
+ (instance: string): ts.Identifier =>
84
+ ts.factory.createIdentifier(
85
+ importer.external({
86
+ type: "instance",
87
+ library: lib,
88
+ name: instance,
89
+ }),
90
+ );
91
+ const router = (instance: string) =>
92
+ ts.factory.createDecorator(
93
+ ts.factory.createCallExpression(
94
+ IdentifierFactory.access(external("@nestia/core")(instance))(
95
+ StringUtil.capitalize(route.method),
96
+ ),
97
+ [],
98
+ [ts.factory.createStringLiteral(route.path)],
99
+ ),
100
+ );
101
+
102
+ const decorators: ts.Decorator[] = [];
103
+ if (route.success?.["x-nestia-encrypted"])
104
+ decorators.push(router("EncryptedRoute"));
105
+ else if (route.success?.type === "text/plain")
106
+ decorators.push(
107
+ ts.factory.createDecorator(
108
+ ts.factory.createCallExpression(
109
+ external("@nestjs/common")(StringUtil.capitalize(route.method)),
110
+ [],
111
+ [ts.factory.createStringLiteral(route.path)],
112
+ ),
113
+ ),
114
+ );
115
+ else if (route.success?.type === "application/x-www-form-urlencoded")
116
+ decorators.push(router("TypedQuery"));
117
+ else if (route.method === "head")
118
+ decorators.push(
119
+ ts.factory.createDecorator(
120
+ ts.factory.createCallExpression(
121
+ external("@nestjs/common")("Head"),
122
+ [],
123
+ [ts.factory.createStringLiteral(route.path)],
124
+ ),
125
+ ),
126
+ );
127
+ else if (
128
+ route.success === null ||
129
+ route.success?.type === "application/json"
130
+ )
131
+ decorators.push(router("TypedRoute"));
132
+ for (const [key, value] of Object.entries(route.exceptions ?? {}))
133
+ decorators.push(
134
+ ts.factory.createDecorator(
135
+ ts.factory.createCallExpression(
136
+ external("@nestia/core")("TypedException"),
137
+ [
138
+ MigrateSchemaProgrammer.write(components)(importer)(
139
+ value.schema,
140
+ ),
141
+ ],
142
+ [
143
+ isNaN(Number(key))
144
+ ? ts.factory.createStringLiteral(key)
145
+ : ExpressionFactory.number(Number(key)),
146
+ ...(value.description?.length
147
+ ? [ts.factory.createStringLiteral(value.description)]
148
+ : []),
149
+ ],
150
+ ),
151
+ ),
152
+ );
153
+ return decorators;
154
+ };
155
+
156
+ const writeParameters =
157
+ (components: ISwaggerComponents) =>
158
+ (importer: MigrateImportProgrammer) =>
159
+ (route: IMigrateRoute): ts.ParameterDeclaration[] => [
160
+ ...route.parameters.map(({ key, schema: value }) =>
161
+ ts.factory.createParameterDeclaration(
162
+ [
163
+ ts.factory.createDecorator(
164
+ ts.factory.createCallExpression(
165
+ ts.factory.createIdentifier(
166
+ importer.external({
167
+ type: "instance",
168
+ library: "@nestia/core",
169
+ name: "TypedParam",
170
+ }),
171
+ ),
172
+ undefined,
173
+ [ts.factory.createStringLiteral(key)],
174
+ ),
175
+ ),
176
+ ],
177
+ undefined,
178
+ StringUtil.normalize(key),
179
+ undefined,
180
+ MigrateSchemaProgrammer.write(components)(importer)(value),
181
+ ),
182
+ ),
183
+ ...(route.headers
184
+ ? [
185
+ writeDtoParameter({ method: "TypedHeaders", variable: "headers" })(
186
+ components,
187
+ )(importer)(route.headers.schema),
188
+ ]
189
+ : []),
190
+ ...(route.query
191
+ ? [
192
+ writeDtoParameter({ method: "TypedQuery", variable: "query" })(
193
+ components,
194
+ )(importer)(route.query.schema),
195
+ ]
196
+ : []),
197
+ ...(route.body
198
+ ? [
199
+ writeDtoParameter({
200
+ method: route.body["x-nestia-encrypted"]
201
+ ? "EncryptedBody"
202
+ : route.body.type === "application/json"
203
+ ? "TypedBody"
204
+ : route.body.type === "application/x-www-form-urlencoded"
205
+ ? ["TypedQuery", "Body"]
206
+ : route.body.type === "text/plain"
207
+ ? "PlainBody"
208
+ : route.body.type === "multipart/form-data"
209
+ ? ["TypedFormData", "Body"]
210
+ : "TypedBody",
211
+ variable: "body",
212
+ })(components)(importer)(route.body.schema),
213
+ ]
214
+ : []),
215
+ ];
216
+
217
+ const writeDtoParameter =
218
+ (accessor: { method: string | [string, string]; variable: string }) =>
219
+ (components: ISwaggerComponents) =>
220
+ (importer: MigrateImportProgrammer) =>
221
+ (schema: ISwaggerSchema): ts.ParameterDeclaration => {
222
+ const instance = ts.factory.createIdentifier(
223
+ importer.external({
224
+ type: "instance",
225
+ library: "@nestia/core",
226
+ name:
227
+ typeof accessor.method === "string"
228
+ ? accessor.method
229
+ : accessor.method[0],
230
+ }),
231
+ );
232
+ return ts.factory.createParameterDeclaration(
233
+ [
234
+ ts.factory.createDecorator(
235
+ ts.factory.createCallExpression(
236
+ typeof accessor.method === "string"
237
+ ? instance
238
+ : IdentifierFactory.access(instance)(accessor.method[1]),
239
+ undefined,
240
+ undefined,
241
+ ),
242
+ ),
243
+ ],
244
+ undefined,
245
+ StringUtil.normalize(accessor.variable),
246
+ undefined,
247
+ MigrateSchemaProgrammer.write(components)(importer)(schema),
248
+ );
249
+ };
250
+ }
@@ -1,63 +1,63 @@
1
- import ts from "typescript";
2
-
3
- import { IMigrateController } from "../structures/IMigrateController";
4
- import { FilePrinter } from "../utils/FilePrinter";
5
-
6
- export namespace MigrateNestModuleProgrammer {
7
- export const write = (controllers: IMigrateController[]): ts.Statement[] => [
8
- $import("@nestjs/common")("Module"),
9
- ...(controllers.length ? [FilePrinter.newLine()] : []),
10
- ...controllers.map((c) =>
11
- $import(`${c.location.replace("src/", "./")}/${c.name}`)(c.name),
12
- ),
13
- ...(controllers.length ? [FilePrinter.newLine()] : []),
14
- ts.factory.createClassDeclaration(
15
- [
16
- ts.factory.createDecorator(
17
- ts.factory.createCallExpression(
18
- ts.factory.createIdentifier("Module"),
19
- undefined,
20
- [
21
- ts.factory.createObjectLiteralExpression(
22
- [
23
- ts.factory.createPropertyAssignment(
24
- ts.factory.createIdentifier("controllers"),
25
- ts.factory.createArrayLiteralExpression(
26
- controllers.map((c) =>
27
- ts.factory.createIdentifier(c.name),
28
- ),
29
- true,
30
- ),
31
- ),
32
- ],
33
- true,
34
- ),
35
- ],
36
- ),
37
- ),
38
- ts.factory.createToken(ts.SyntaxKind.ExportKeyword),
39
- ],
40
- "MyModule",
41
- undefined,
42
- undefined,
43
- [],
44
- ),
45
- ];
46
- }
47
-
48
- const $import = (file: string) => (instance: string) =>
49
- ts.factory.createImportDeclaration(
50
- undefined,
51
- ts.factory.createImportClause(
52
- false,
53
- undefined,
54
- ts.factory.createNamedImports([
55
- ts.factory.createImportSpecifier(
56
- false,
57
- undefined,
58
- ts.factory.createIdentifier(instance),
59
- ),
60
- ]),
61
- ),
62
- ts.factory.createStringLiteral(file),
63
- );
1
+ import ts from "typescript";
2
+
3
+ import { IMigrateController } from "../structures/IMigrateController";
4
+ import { FilePrinter } from "../utils/FilePrinter";
5
+
6
+ export namespace MigrateNestModuleProgrammer {
7
+ export const write = (controllers: IMigrateController[]): ts.Statement[] => [
8
+ $import("@nestjs/common")("Module"),
9
+ ...(controllers.length ? [FilePrinter.newLine()] : []),
10
+ ...controllers.map((c) =>
11
+ $import(`${c.location.replace("src/", "./")}/${c.name}`)(c.name),
12
+ ),
13
+ ...(controllers.length ? [FilePrinter.newLine()] : []),
14
+ ts.factory.createClassDeclaration(
15
+ [
16
+ ts.factory.createDecorator(
17
+ ts.factory.createCallExpression(
18
+ ts.factory.createIdentifier("Module"),
19
+ undefined,
20
+ [
21
+ ts.factory.createObjectLiteralExpression(
22
+ [
23
+ ts.factory.createPropertyAssignment(
24
+ ts.factory.createIdentifier("controllers"),
25
+ ts.factory.createArrayLiteralExpression(
26
+ controllers.map((c) =>
27
+ ts.factory.createIdentifier(c.name),
28
+ ),
29
+ true,
30
+ ),
31
+ ),
32
+ ],
33
+ true,
34
+ ),
35
+ ],
36
+ ),
37
+ ),
38
+ ts.factory.createToken(ts.SyntaxKind.ExportKeyword),
39
+ ],
40
+ "MyModule",
41
+ undefined,
42
+ undefined,
43
+ [],
44
+ ),
45
+ ];
46
+ }
47
+
48
+ const $import = (file: string) => (instance: string) =>
49
+ ts.factory.createImportDeclaration(
50
+ undefined,
51
+ ts.factory.createImportClause(
52
+ false,
53
+ undefined,
54
+ ts.factory.createNamedImports([
55
+ ts.factory.createImportSpecifier(
56
+ false,
57
+ undefined,
58
+ ts.factory.createIdentifier(instance),
59
+ ),
60
+ ]),
61
+ ),
62
+ ts.factory.createStringLiteral(file),
63
+ );