@nestia/migrate 4.5.2 → 4.6.1-dev.20250117

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