@nestia/migrate 12.0.0-dev.20260601.1 → 12.0.0-dev.20260612.2

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 (50) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +93 -93
  3. package/lib/NestiaMigrateApplication.js +19 -1
  4. package/lib/NestiaMigrateApplication.js.map +1 -1
  5. package/lib/bundles/NEST_TEMPLATE.js +47 -47
  6. package/lib/bundles/NEST_TEMPLATE.js.map +1 -1
  7. package/lib/bundles/SDK_TEMPLATE.js +20 -20
  8. package/lib/bundles/SDK_TEMPLATE.js.map +1 -1
  9. package/lib/index.mjs +94 -77
  10. package/lib/index.mjs.map +1 -1
  11. package/lib/programmers/NestiaMigrateApiFunctionProgrammer.js +6 -2
  12. package/lib/programmers/NestiaMigrateApiFunctionProgrammer.js.map +1 -1
  13. package/package.json +5 -5
  14. package/src/NestiaMigrateApplication.ts +196 -167
  15. package/src/analyzers/NestiaMigrateControllerAnalyzer.ts +51 -51
  16. package/src/archivers/NestiaMigrateFileArchiver.ts +28 -28
  17. package/src/bundles/NEST_TEMPLATE.ts +47 -47
  18. package/src/bundles/SDK_TEMPLATE.ts +20 -20
  19. package/src/executable/NestiaMigrateCommander.ts +115 -115
  20. package/src/executable/NestiaMigrateInquirer.ts +106 -106
  21. package/src/executable/bundle.js +349 -349
  22. package/src/executable/migrate.ts +7 -7
  23. package/src/factories/TypeLiteralFactory.ts +63 -63
  24. package/src/index.ts +4 -4
  25. package/src/internal/ts.ts +94 -94
  26. package/src/module.ts +6 -6
  27. package/src/programmers/NestiaMigrateApiFileProgrammer.ts +58 -58
  28. package/src/programmers/NestiaMigrateApiFunctionProgrammer.ts +373 -369
  29. package/src/programmers/NestiaMigrateApiNamespaceProgrammer.ts +528 -528
  30. package/src/programmers/NestiaMigrateApiProgrammer.ts +108 -108
  31. package/src/programmers/NestiaMigrateApiSimulationProgrammer.ts +314 -314
  32. package/src/programmers/NestiaMigrateApiStartProgrammer.ts +198 -198
  33. package/src/programmers/NestiaMigrateDtoProgrammer.ts +99 -99
  34. package/src/programmers/NestiaMigrateE2eFileProgrammer.ts +156 -156
  35. package/src/programmers/NestiaMigrateE2eProgrammer.ts +48 -48
  36. package/src/programmers/NestiaMigrateImportProgrammer.ts +119 -119
  37. package/src/programmers/NestiaMigrateNestControllerProgrammer.ts +70 -70
  38. package/src/programmers/NestiaMigrateNestMethodProgrammer.ts +414 -414
  39. package/src/programmers/NestiaMigrateNestModuleProgrammer.ts +66 -66
  40. package/src/programmers/NestiaMigrateNestProgrammer.ts +89 -89
  41. package/src/programmers/NestiaMigrateSchemaProgrammer.ts +477 -477
  42. package/src/programmers/index.ts +15 -15
  43. package/src/structures/INestiaMigrateConfig.ts +19 -19
  44. package/src/structures/INestiaMigrateContext.ts +9 -9
  45. package/src/structures/INestiaMigrateController.ts +8 -8
  46. package/src/structures/INestiaMigrateFile.ts +5 -5
  47. package/src/structures/index.ts +4 -4
  48. package/src/utils/FilePrinter.ts +44 -44
  49. package/src/utils/MapUtil.ts +13 -13
  50. package/src/utils/StringUtil.ts +109 -109
@@ -1,414 +1,414 @@
1
- import { TypeScriptFactory } from "@nestia/factory";
2
- import {
3
- ExpressionFactory,
4
- IdentifierFactory,
5
- LiteralFactory,
6
- TypeFactory,
7
- } from "@nestia/factory";
8
- import { IHttpMigrateRoute } from "@typia/interface";
9
- import ts from "../internal/ts";
10
- import { OpenApi } from "typia";
11
-
12
- import { INestiaMigrateConfig } from "../structures/INestiaMigrateConfig";
13
- import { INestiaMigrateController } from "../structures/INestiaMigrateController";
14
- import { FilePrinter } from "../utils/FilePrinter";
15
- import { StringUtil } from "../utils/StringUtil";
16
- import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
17
- import { NestiaMigrateSchemaProgrammer } from "./NestiaMigrateSchemaProgrammer";
18
-
19
- export namespace NestiaMigrateNestMethodProgrammer {
20
- export interface IContext {
21
- config: INestiaMigrateConfig;
22
- components: OpenApi.IComponents;
23
- importer: NestiaMigrateImportProgrammer;
24
- controller: INestiaMigrateController;
25
- route: IHttpMigrateRoute;
26
- }
27
-
28
- export const write = (ctx: IContext): ts.MethodDeclaration => {
29
- const output: ts.TypeNode = ctx.route.success
30
- ? NestiaMigrateSchemaProgrammer.write({
31
- components: ctx.components,
32
- importer: ctx.importer,
33
- schema: ctx.route.success.schema,
34
- })
35
- : TypeFactory.keyword("void");
36
-
37
- const method: ts.MethodDeclaration =
38
- TypeScriptFactory.createMethodDeclaration(
39
- [
40
- ...writeMethodDecorators(ctx),
41
- TypeScriptFactory.createToken(ts.SyntaxKind.PublicKeyword),
42
- TypeScriptFactory.createToken(ts.SyntaxKind.AsyncKeyword),
43
- ],
44
- undefined,
45
- ctx.route.accessor.at(-1)!,
46
- undefined,
47
- undefined,
48
- writeParameters(ctx),
49
- TypeScriptFactory.createTypeReferenceNode("Promise", [output]),
50
- TypeScriptFactory.createBlock(
51
- [
52
- ...[
53
- ...ctx.route.parameters.map((p) => p.key),
54
- ...(ctx.route.headers ? ["headers"] : []),
55
- ...(ctx.route.query ? ["query"] : []),
56
- ...(ctx.route.body ? ["body"] : []),
57
- ].map((str) =>
58
- TypeScriptFactory.createExpressionStatement(
59
- TypeScriptFactory.createIdentifier(str),
60
- ),
61
- ),
62
- TypeScriptFactory.createReturnStatement(
63
- TypeScriptFactory.createCallExpression(
64
- IdentifierFactory.access(
65
- TypeScriptFactory.createIdentifier(
66
- ctx.importer.external({
67
- type: "default",
68
- library: "typia",
69
- name: "typia",
70
- }),
71
- ),
72
- "random",
73
- ),
74
- [output],
75
- undefined,
76
- ),
77
- ),
78
- ],
79
- true,
80
- ),
81
- );
82
- return FilePrinter.description(
83
- method,
84
- writeDescription(ctx.config, ctx.route),
85
- );
86
- };
87
-
88
- const writeDescription = (
89
- config: INestiaMigrateConfig,
90
- method: IHttpMigrateRoute,
91
- ): string =>
92
- [
93
- method.comment(),
94
- `@${config.author?.tag ?? "nestia"} ${config.author?.value ?? "Generated by Nestia - https://github.com/samchon/nestia"}`,
95
- ].join("\n");
96
-
97
- const writeMethodDecorators = (ctx: IContext): ts.Decorator[] => {
98
- const external = (lib: string, instance: string): ts.Identifier =>
99
- TypeScriptFactory.createIdentifier(
100
- ctx.importer.external({
101
- type: "instance",
102
- library: lib,
103
- name: instance,
104
- }),
105
- );
106
-
107
- // EXAMPLES
108
- const decorators: ts.Decorator[] = [];
109
- if (ctx.route.success)
110
- decorators.push(
111
- ...writeExampleDecorators("Response")(ctx.importer)(
112
- ctx.route.success.media(),
113
- ),
114
- );
115
-
116
- // HUMAN-ONLY
117
- if (ctx.route.operation()["x-samchon-human"] === true)
118
- decorators.push(
119
- TypeScriptFactory.createDecorator(
120
- TypeScriptFactory.createCallExpression(
121
- external("@nestia/core", "HumanRoute"),
122
- undefined,
123
- undefined,
124
- ),
125
- ),
126
- );
127
-
128
- // ROUTER
129
- const localPath: string = ctx.route.emendedPath
130
- .slice(ctx.controller.path.length)
131
- .split("/")
132
- .filter((str) => !!str.length)
133
- .join("/");
134
- const router = (instance: string) =>
135
- TypeScriptFactory.createDecorator(
136
- TypeScriptFactory.createCallExpression(
137
- IdentifierFactory.access(
138
- external("@nestia/core", instance),
139
- StringUtil.capitalize(ctx.route.method),
140
- ),
141
- [],
142
- localPath.length
143
- ? [TypeScriptFactory.createStringLiteral(localPath)]
144
- : undefined,
145
- ),
146
- );
147
- if (ctx.route.success?.["x-nestia-encrypted"])
148
- decorators.push(router("EncryptedRoute"));
149
- else if (ctx.route.success?.type === "text/plain")
150
- decorators.push(
151
- TypeScriptFactory.createDecorator(
152
- TypeScriptFactory.createCallExpression(
153
- external("@nestjs/common", StringUtil.capitalize(ctx.route.method)),
154
- [],
155
- [TypeScriptFactory.createStringLiteral(ctx.route.path)],
156
- ),
157
- ),
158
- );
159
- else if (ctx.route.success?.type === "application/x-www-form-urlencoded")
160
- decorators.push(router("TypedQuery"));
161
- else if (ctx.route.method === "head")
162
- decorators.push(
163
- TypeScriptFactory.createDecorator(
164
- TypeScriptFactory.createCallExpression(
165
- external("@nestjs/common", "Head"),
166
- [],
167
- [TypeScriptFactory.createStringLiteral(ctx.route.path)],
168
- ),
169
- ),
170
- );
171
- else if (
172
- ctx.route.success === null ||
173
- ctx.route.success?.type === "application/json"
174
- )
175
- decorators.push(router("TypedRoute"));
176
- for (const [key, value] of Object.entries(ctx.route.exceptions ?? {}))
177
- decorators.push(
178
- TypeScriptFactory.createDecorator(
179
- TypeScriptFactory.createCallExpression(
180
- external("@nestia/core", "TypedException"),
181
- [
182
- NestiaMigrateSchemaProgrammer.write({
183
- components: ctx.components,
184
- importer: ctx.importer,
185
- schema: value.schema,
186
- }),
187
- ],
188
- [
189
- isNaN(Number(key))
190
- ? TypeScriptFactory.createStringLiteral(key)
191
- : ExpressionFactory.number(Number(key)),
192
- ...(value.response().description?.length
193
- ? [
194
- TypeScriptFactory.createStringLiteral(
195
- value.response().description!,
196
- ),
197
- ]
198
- : []),
199
- ],
200
- ),
201
- ),
202
- );
203
- return decorators;
204
- };
205
-
206
- const writeParameters = (ctx: IContext): ts.ParameterDeclaration[] => [
207
- ...ctx.route.parameters.map((p) =>
208
- TypeScriptFactory.createParameterDeclaration(
209
- [
210
- ...writeExampleDecorators("Parameter")(ctx.importer)(p.parameter()),
211
- TypeScriptFactory.createDecorator(
212
- TypeScriptFactory.createCallExpression(
213
- TypeScriptFactory.createIdentifier(
214
- ctx.importer.external({
215
- type: "instance",
216
- library: "@nestia/core",
217
- name: "TypedParam",
218
- }),
219
- ),
220
- undefined,
221
- [TypeScriptFactory.createStringLiteral(p.key)],
222
- ),
223
- ),
224
- ],
225
- undefined,
226
- p.key,
227
- undefined,
228
- NestiaMigrateSchemaProgrammer.write({
229
- components: ctx.components,
230
- importer: ctx.importer,
231
- schema: p.schema,
232
- }),
233
- ),
234
- ),
235
- ...(ctx.route.headers
236
- ? [
237
- writeDtoParameter({
238
- method: "TypedHeaders",
239
- variable: "headers",
240
- arguments: [],
241
- })(ctx.components)(ctx.importer)({
242
- required: true,
243
- schema: ctx.route.headers.schema,
244
- example: ctx.route.headers.example(),
245
- examples: ctx.route.headers.examples(),
246
- }),
247
- ]
248
- : []),
249
- ...(ctx.route.query
250
- ? [
251
- writeDtoParameter({
252
- method: "TypedQuery",
253
- variable: "query",
254
- arguments: [],
255
- })(ctx.components)(ctx.importer)({
256
- required: true,
257
- schema: ctx.route.query.schema,
258
- example: ctx.route.query.example(),
259
- examples: ctx.route.query.examples(),
260
- }),
261
- ]
262
- : []),
263
- ...(ctx.route.body
264
- ? [
265
- writeDtoParameter({
266
- method: ctx.route.body["x-nestia-encrypted"]
267
- ? "EncryptedBody"
268
- : ctx.route.body.type === "application/json"
269
- ? "TypedBody"
270
- : ctx.route.body.type === "application/x-www-form-urlencoded"
271
- ? ["TypedQuery", "Body"]
272
- : ctx.route.body.type === "text/plain"
273
- ? "PlainBody"
274
- : ctx.route.body.type === "multipart/form-data"
275
- ? ["TypedFormData", "Body"]
276
- : "TypedBody",
277
- variable: "body",
278
- arguments:
279
- ctx.route.body.type === "multipart/form-data"
280
- ? [
281
- TypeScriptFactory.createArrowFunction(
282
- undefined,
283
- undefined,
284
- [],
285
- undefined,
286
- undefined,
287
- TypeScriptFactory.createCallExpression(
288
- TypeScriptFactory.createIdentifier(
289
- ctx.importer.external({
290
- type: "default",
291
- library: "multer",
292
- name: "Multer",
293
- }),
294
- ),
295
- undefined,
296
- undefined,
297
- ),
298
- ),
299
- ]
300
- : [],
301
- })(ctx.components)(ctx.importer)({
302
- schema: ctx.route.body.schema,
303
- required: !(
304
- (ctx.route.body.type === "application/json" ||
305
- ctx.route.body.type === "text/plain") &&
306
- ctx.route.operation().requestBody?.required === false
307
- ),
308
- example: ctx.route.body.media().example,
309
- examples: ctx.route.body.media().examples,
310
- }),
311
- ]
312
- : []),
313
- ];
314
-
315
- const writeDtoParameter =
316
- (accessor: {
317
- method: string | [string, string];
318
- variable: string;
319
- arguments: ts.Expression[];
320
- }) =>
321
- (components: OpenApi.IComponents) =>
322
- (importer: NestiaMigrateImportProgrammer) =>
323
- (props: {
324
- schema: OpenApi.IJsonSchema;
325
- required: boolean;
326
- example?: any;
327
- examples?: Record<string, any>;
328
- }): ts.ParameterDeclaration => {
329
- const instance = TypeScriptFactory.createIdentifier(
330
- importer.external({
331
- type: "instance",
332
- library: "@nestia/core",
333
- name:
334
- typeof accessor.method === "string"
335
- ? accessor.method
336
- : accessor.method[0],
337
- }),
338
- );
339
- return TypeScriptFactory.createParameterDeclaration(
340
- [
341
- ...writeExampleDecorators("Parameter")(importer)(props),
342
- TypeScriptFactory.createDecorator(
343
- TypeScriptFactory.createCallExpression(
344
- typeof accessor.method === "string"
345
- ? instance
346
- : IdentifierFactory.access(instance, accessor.method[1]),
347
- undefined,
348
- accessor.arguments,
349
- ),
350
- ),
351
- ],
352
- undefined,
353
- accessor.variable,
354
- props.required === false
355
- ? TypeScriptFactory.createToken(ts.SyntaxKind.QuestionToken)
356
- : undefined,
357
- NestiaMigrateSchemaProgrammer.write({
358
- components,
359
- importer,
360
- schema: props.schema,
361
- }),
362
- );
363
- };
364
-
365
- const writeExampleDecorators =
366
- (kind: "Response" | "Parameter") =>
367
- (importer: NestiaMigrateImportProgrammer) =>
368
- (media: {
369
- example?: any;
370
- examples?: Record<string, any>;
371
- }): ts.Decorator[] => [
372
- ...(media.example !== undefined
373
- ? [
374
- TypeScriptFactory.createDecorator(
375
- TypeScriptFactory.createCallExpression(
376
- IdentifierFactory.access(
377
- TypeScriptFactory.createIdentifier(
378
- importer.external({
379
- type: "instance",
380
- library: "@nestia/core",
381
- name: "SwaggerExample",
382
- }),
383
- ),
384
- kind,
385
- ),
386
- [],
387
- [LiteralFactory.write(media.example)],
388
- ),
389
- ),
390
- ]
391
- : []),
392
- ...Object.entries(media.examples ?? {}).map(([key, value]) =>
393
- TypeScriptFactory.createDecorator(
394
- TypeScriptFactory.createCallExpression(
395
- IdentifierFactory.access(
396
- TypeScriptFactory.createIdentifier(
397
- importer.external({
398
- type: "instance",
399
- library: "@nestia/core",
400
- name: "SwaggerExample",
401
- }),
402
- ),
403
- kind,
404
- ),
405
- [],
406
- [
407
- TypeScriptFactory.createStringLiteral(key),
408
- LiteralFactory.write(value),
409
- ],
410
- ),
411
- ),
412
- ),
413
- ];
414
- }
1
+ import { TypeScriptFactory } from "@nestia/factory";
2
+ import {
3
+ ExpressionFactory,
4
+ IdentifierFactory,
5
+ LiteralFactory,
6
+ TypeFactory,
7
+ } from "@nestia/factory";
8
+ import { IHttpMigrateRoute } from "@typia/interface";
9
+ import ts from "../internal/ts";
10
+ import { OpenApi } from "typia";
11
+
12
+ import { INestiaMigrateConfig } from "../structures/INestiaMigrateConfig";
13
+ import { INestiaMigrateController } from "../structures/INestiaMigrateController";
14
+ import { FilePrinter } from "../utils/FilePrinter";
15
+ import { StringUtil } from "../utils/StringUtil";
16
+ import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
17
+ import { NestiaMigrateSchemaProgrammer } from "./NestiaMigrateSchemaProgrammer";
18
+
19
+ export namespace NestiaMigrateNestMethodProgrammer {
20
+ export interface IContext {
21
+ config: INestiaMigrateConfig;
22
+ components: OpenApi.IComponents;
23
+ importer: NestiaMigrateImportProgrammer;
24
+ controller: INestiaMigrateController;
25
+ route: IHttpMigrateRoute;
26
+ }
27
+
28
+ export const write = (ctx: IContext): ts.MethodDeclaration => {
29
+ const output: ts.TypeNode = ctx.route.success
30
+ ? NestiaMigrateSchemaProgrammer.write({
31
+ components: ctx.components,
32
+ importer: ctx.importer,
33
+ schema: ctx.route.success.schema,
34
+ })
35
+ : TypeFactory.keyword("void");
36
+
37
+ const method: ts.MethodDeclaration =
38
+ TypeScriptFactory.createMethodDeclaration(
39
+ [
40
+ ...writeMethodDecorators(ctx),
41
+ TypeScriptFactory.createToken(ts.SyntaxKind.PublicKeyword),
42
+ TypeScriptFactory.createToken(ts.SyntaxKind.AsyncKeyword),
43
+ ],
44
+ undefined,
45
+ ctx.route.accessor.at(-1)!,
46
+ undefined,
47
+ undefined,
48
+ writeParameters(ctx),
49
+ TypeScriptFactory.createTypeReferenceNode("Promise", [output]),
50
+ TypeScriptFactory.createBlock(
51
+ [
52
+ ...[
53
+ ...ctx.route.parameters.map((p) => p.key),
54
+ ...(ctx.route.headers ? ["headers"] : []),
55
+ ...(ctx.route.query ? ["query"] : []),
56
+ ...(ctx.route.body ? ["body"] : []),
57
+ ].map((str) =>
58
+ TypeScriptFactory.createExpressionStatement(
59
+ TypeScriptFactory.createIdentifier(str),
60
+ ),
61
+ ),
62
+ TypeScriptFactory.createReturnStatement(
63
+ TypeScriptFactory.createCallExpression(
64
+ IdentifierFactory.access(
65
+ TypeScriptFactory.createIdentifier(
66
+ ctx.importer.external({
67
+ type: "default",
68
+ library: "typia",
69
+ name: "typia",
70
+ }),
71
+ ),
72
+ "random",
73
+ ),
74
+ [output],
75
+ undefined,
76
+ ),
77
+ ),
78
+ ],
79
+ true,
80
+ ),
81
+ );
82
+ return FilePrinter.description(
83
+ method,
84
+ writeDescription(ctx.config, ctx.route),
85
+ );
86
+ };
87
+
88
+ const writeDescription = (
89
+ config: INestiaMigrateConfig,
90
+ method: IHttpMigrateRoute,
91
+ ): string =>
92
+ [
93
+ method.comment(),
94
+ `@${config.author?.tag ?? "nestia"} ${config.author?.value ?? "Generated by Nestia - https://github.com/samchon/nestia"}`,
95
+ ].join("\n");
96
+
97
+ const writeMethodDecorators = (ctx: IContext): ts.Decorator[] => {
98
+ const external = (lib: string, instance: string): ts.Identifier =>
99
+ TypeScriptFactory.createIdentifier(
100
+ ctx.importer.external({
101
+ type: "instance",
102
+ library: lib,
103
+ name: instance,
104
+ }),
105
+ );
106
+
107
+ // EXAMPLES
108
+ const decorators: ts.Decorator[] = [];
109
+ if (ctx.route.success)
110
+ decorators.push(
111
+ ...writeExampleDecorators("Response")(ctx.importer)(
112
+ ctx.route.success.media(),
113
+ ),
114
+ );
115
+
116
+ // HUMAN-ONLY
117
+ if (ctx.route.operation()["x-samchon-human"] === true)
118
+ decorators.push(
119
+ TypeScriptFactory.createDecorator(
120
+ TypeScriptFactory.createCallExpression(
121
+ external("@nestia/core", "HumanRoute"),
122
+ undefined,
123
+ undefined,
124
+ ),
125
+ ),
126
+ );
127
+
128
+ // ROUTER
129
+ const localPath: string = ctx.route.emendedPath
130
+ .slice(ctx.controller.path.length)
131
+ .split("/")
132
+ .filter((str) => !!str.length)
133
+ .join("/");
134
+ const router = (instance: string) =>
135
+ TypeScriptFactory.createDecorator(
136
+ TypeScriptFactory.createCallExpression(
137
+ IdentifierFactory.access(
138
+ external("@nestia/core", instance),
139
+ StringUtil.capitalize(ctx.route.method),
140
+ ),
141
+ [],
142
+ localPath.length
143
+ ? [TypeScriptFactory.createStringLiteral(localPath)]
144
+ : undefined,
145
+ ),
146
+ );
147
+ if (ctx.route.success?.["x-nestia-encrypted"])
148
+ decorators.push(router("EncryptedRoute"));
149
+ else if (ctx.route.success?.type === "text/plain")
150
+ decorators.push(
151
+ TypeScriptFactory.createDecorator(
152
+ TypeScriptFactory.createCallExpression(
153
+ external("@nestjs/common", StringUtil.capitalize(ctx.route.method)),
154
+ [],
155
+ [TypeScriptFactory.createStringLiteral(ctx.route.path)],
156
+ ),
157
+ ),
158
+ );
159
+ else if (ctx.route.success?.type === "application/x-www-form-urlencoded")
160
+ decorators.push(router("TypedQuery"));
161
+ else if (ctx.route.method === "head")
162
+ decorators.push(
163
+ TypeScriptFactory.createDecorator(
164
+ TypeScriptFactory.createCallExpression(
165
+ external("@nestjs/common", "Head"),
166
+ [],
167
+ [TypeScriptFactory.createStringLiteral(ctx.route.path)],
168
+ ),
169
+ ),
170
+ );
171
+ else if (
172
+ ctx.route.success === null ||
173
+ ctx.route.success?.type === "application/json"
174
+ )
175
+ decorators.push(router("TypedRoute"));
176
+ for (const [key, value] of Object.entries(ctx.route.exceptions ?? {}))
177
+ decorators.push(
178
+ TypeScriptFactory.createDecorator(
179
+ TypeScriptFactory.createCallExpression(
180
+ external("@nestia/core", "TypedException"),
181
+ [
182
+ NestiaMigrateSchemaProgrammer.write({
183
+ components: ctx.components,
184
+ importer: ctx.importer,
185
+ schema: value.schema,
186
+ }),
187
+ ],
188
+ [
189
+ isNaN(Number(key))
190
+ ? TypeScriptFactory.createStringLiteral(key)
191
+ : ExpressionFactory.number(Number(key)),
192
+ ...(value.response().description?.length
193
+ ? [
194
+ TypeScriptFactory.createStringLiteral(
195
+ value.response().description!,
196
+ ),
197
+ ]
198
+ : []),
199
+ ],
200
+ ),
201
+ ),
202
+ );
203
+ return decorators;
204
+ };
205
+
206
+ const writeParameters = (ctx: IContext): ts.ParameterDeclaration[] => [
207
+ ...ctx.route.parameters.map((p) =>
208
+ TypeScriptFactory.createParameterDeclaration(
209
+ [
210
+ ...writeExampleDecorators("Parameter")(ctx.importer)(p.parameter()),
211
+ TypeScriptFactory.createDecorator(
212
+ TypeScriptFactory.createCallExpression(
213
+ TypeScriptFactory.createIdentifier(
214
+ ctx.importer.external({
215
+ type: "instance",
216
+ library: "@nestia/core",
217
+ name: "TypedParam",
218
+ }),
219
+ ),
220
+ undefined,
221
+ [TypeScriptFactory.createStringLiteral(p.key)],
222
+ ),
223
+ ),
224
+ ],
225
+ undefined,
226
+ p.key,
227
+ undefined,
228
+ NestiaMigrateSchemaProgrammer.write({
229
+ components: ctx.components,
230
+ importer: ctx.importer,
231
+ schema: p.schema,
232
+ }),
233
+ ),
234
+ ),
235
+ ...(ctx.route.headers
236
+ ? [
237
+ writeDtoParameter({
238
+ method: "TypedHeaders",
239
+ variable: "headers",
240
+ arguments: [],
241
+ })(ctx.components)(ctx.importer)({
242
+ required: true,
243
+ schema: ctx.route.headers.schema,
244
+ example: ctx.route.headers.example(),
245
+ examples: ctx.route.headers.examples(),
246
+ }),
247
+ ]
248
+ : []),
249
+ ...(ctx.route.query
250
+ ? [
251
+ writeDtoParameter({
252
+ method: "TypedQuery",
253
+ variable: "query",
254
+ arguments: [],
255
+ })(ctx.components)(ctx.importer)({
256
+ required: true,
257
+ schema: ctx.route.query.schema,
258
+ example: ctx.route.query.example(),
259
+ examples: ctx.route.query.examples(),
260
+ }),
261
+ ]
262
+ : []),
263
+ ...(ctx.route.body
264
+ ? [
265
+ writeDtoParameter({
266
+ method: ctx.route.body["x-nestia-encrypted"]
267
+ ? "EncryptedBody"
268
+ : ctx.route.body.type === "application/json"
269
+ ? "TypedBody"
270
+ : ctx.route.body.type === "application/x-www-form-urlencoded"
271
+ ? ["TypedQuery", "Body"]
272
+ : ctx.route.body.type === "text/plain"
273
+ ? "PlainBody"
274
+ : ctx.route.body.type === "multipart/form-data"
275
+ ? ["TypedFormData", "Body"]
276
+ : "TypedBody",
277
+ variable: "body",
278
+ arguments:
279
+ ctx.route.body.type === "multipart/form-data"
280
+ ? [
281
+ TypeScriptFactory.createArrowFunction(
282
+ undefined,
283
+ undefined,
284
+ [],
285
+ undefined,
286
+ undefined,
287
+ TypeScriptFactory.createCallExpression(
288
+ TypeScriptFactory.createIdentifier(
289
+ ctx.importer.external({
290
+ type: "default",
291
+ library: "multer",
292
+ name: "Multer",
293
+ }),
294
+ ),
295
+ undefined,
296
+ undefined,
297
+ ),
298
+ ),
299
+ ]
300
+ : [],
301
+ })(ctx.components)(ctx.importer)({
302
+ schema: ctx.route.body.schema,
303
+ required: !(
304
+ (ctx.route.body.type === "application/json" ||
305
+ ctx.route.body.type === "text/plain") &&
306
+ ctx.route.operation().requestBody?.required === false
307
+ ),
308
+ example: ctx.route.body.media().example,
309
+ examples: ctx.route.body.media().examples,
310
+ }),
311
+ ]
312
+ : []),
313
+ ];
314
+
315
+ const writeDtoParameter =
316
+ (accessor: {
317
+ method: string | [string, string];
318
+ variable: string;
319
+ arguments: ts.Expression[];
320
+ }) =>
321
+ (components: OpenApi.IComponents) =>
322
+ (importer: NestiaMigrateImportProgrammer) =>
323
+ (props: {
324
+ schema: OpenApi.IJsonSchema;
325
+ required: boolean;
326
+ example?: any;
327
+ examples?: Record<string, any>;
328
+ }): ts.ParameterDeclaration => {
329
+ const instance = TypeScriptFactory.createIdentifier(
330
+ importer.external({
331
+ type: "instance",
332
+ library: "@nestia/core",
333
+ name:
334
+ typeof accessor.method === "string"
335
+ ? accessor.method
336
+ : accessor.method[0],
337
+ }),
338
+ );
339
+ return TypeScriptFactory.createParameterDeclaration(
340
+ [
341
+ ...writeExampleDecorators("Parameter")(importer)(props),
342
+ TypeScriptFactory.createDecorator(
343
+ TypeScriptFactory.createCallExpression(
344
+ typeof accessor.method === "string"
345
+ ? instance
346
+ : IdentifierFactory.access(instance, accessor.method[1]),
347
+ undefined,
348
+ accessor.arguments,
349
+ ),
350
+ ),
351
+ ],
352
+ undefined,
353
+ accessor.variable,
354
+ props.required === false
355
+ ? TypeScriptFactory.createToken(ts.SyntaxKind.QuestionToken)
356
+ : undefined,
357
+ NestiaMigrateSchemaProgrammer.write({
358
+ components,
359
+ importer,
360
+ schema: props.schema,
361
+ }),
362
+ );
363
+ };
364
+
365
+ const writeExampleDecorators =
366
+ (kind: "Response" | "Parameter") =>
367
+ (importer: NestiaMigrateImportProgrammer) =>
368
+ (media: {
369
+ example?: any;
370
+ examples?: Record<string, any>;
371
+ }): ts.Decorator[] => [
372
+ ...(media.example !== undefined
373
+ ? [
374
+ TypeScriptFactory.createDecorator(
375
+ TypeScriptFactory.createCallExpression(
376
+ IdentifierFactory.access(
377
+ TypeScriptFactory.createIdentifier(
378
+ importer.external({
379
+ type: "instance",
380
+ library: "@nestia/core",
381
+ name: "SwaggerExample",
382
+ }),
383
+ ),
384
+ kind,
385
+ ),
386
+ [],
387
+ [LiteralFactory.write(media.example)],
388
+ ),
389
+ ),
390
+ ]
391
+ : []),
392
+ ...Object.entries(media.examples ?? {}).map(([key, value]) =>
393
+ TypeScriptFactory.createDecorator(
394
+ TypeScriptFactory.createCallExpression(
395
+ IdentifierFactory.access(
396
+ TypeScriptFactory.createIdentifier(
397
+ importer.external({
398
+ type: "instance",
399
+ library: "@nestia/core",
400
+ name: "SwaggerExample",
401
+ }),
402
+ ),
403
+ kind,
404
+ ),
405
+ [],
406
+ [
407
+ TypeScriptFactory.createStringLiteral(key),
408
+ LiteralFactory.write(value),
409
+ ],
410
+ ),
411
+ ),
412
+ ),
413
+ ];
414
+ }