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