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