@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,515 +1,515 @@
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 { FilePrinter } from "../utils/FilePrinter";
10
- import { NestiaMigrateApiSimulationProgrammer } from "./NestiaMigrateApiSimulationProgrammer";
11
- import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
12
- import { NestiaMigrateSchemaProgrammer } from "./NestiaMigrateSchemaProgrammer";
13
-
14
- export namespace NestiaMigrateApiNamespaceProgrammer {
15
- export interface IContext {
16
- config: INestiaMigrateConfig;
17
- components: OpenApi.IComponents;
18
- importer: NestiaMigrateImportProgrammer;
19
- route: IHttpMigrateRoute;
20
- }
21
-
22
- export const write = (ctx: IContext): ts.ModuleDeclaration => {
23
- const types: ts.TypeAliasDeclaration[] = writeTypes(ctx);
24
- return ts.factory.createModuleDeclaration(
25
- [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
26
- ts.factory.createIdentifier(ctx.route.accessor.at(-1)!),
27
- ts.factory.createModuleBlock([
28
- ...types,
29
- ...(types.length ? [FilePrinter.newLine()] : []),
30
- writeMetadata(ctx),
31
- FilePrinter.newLine(),
32
- writePathFunction(ctx),
33
- ...(ctx.config.simulate === true
34
- ? [
35
- NestiaMigrateApiSimulationProgrammer.random(ctx),
36
- NestiaMigrateApiSimulationProgrammer.simulate(ctx),
37
- ]
38
- : []),
39
- ]),
40
- ts.NodeFlags.Namespace,
41
- );
42
- };
43
-
44
- export const writePathCallExpression = (
45
- config: INestiaMigrateConfig,
46
- route: IHttpMigrateRoute,
47
- ) =>
48
- ts.factory.createCallExpression(
49
- ts.factory.createIdentifier(`${route.accessor.at(-1)!}.path`),
50
- undefined,
51
- route.parameters.length === 0 && route.query === null
52
- ? []
53
- : config.keyword === true
54
- ? [ts.factory.createIdentifier("props")]
55
- : [...route.parameters, ...(route.query ? [route.query] : [])].map(
56
- (p) => ts.factory.createIdentifier(p.key),
57
- ),
58
- );
59
-
60
- const writeTypes = (ctx: IContext): ts.TypeAliasDeclaration[] => {
61
- const array: ts.TypeAliasDeclaration[] = [];
62
- const declare = (name: string, type: ts.TypeNode) =>
63
- array.push(
64
- ts.factory.createTypeAliasDeclaration(
65
- [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
66
- name,
67
- undefined,
68
- type,
69
- ),
70
- );
71
- if (
72
- ctx.config.keyword === true &&
73
- (ctx.route.parameters.length > 0 || ctx.route.query || ctx.route.body)
74
- )
75
- declare(
76
- "Props",
77
- NestiaMigrateSchemaProgrammer.write({
78
- components: ctx.components,
79
- importer: ctx.importer,
80
- schema: {
81
- type: "object",
82
- properties: Object.fromEntries([
83
- ...ctx.route.parameters.map((p) => [
84
- p.key,
85
- {
86
- ...p.schema,
87
- title: p.parameter().title,
88
- description: p.parameter().description,
89
- },
90
- ]),
91
- ...(ctx.route.query
92
- ? [
93
- [
94
- ctx.route.query.key,
95
- {
96
- ...ctx.route.query.schema,
97
- title: ctx.route.query.title(),
98
- description: ctx.route.query.description(),
99
- },
100
- ],
101
- ]
102
- : []),
103
- ...(ctx.route.body
104
- ? [
105
- [
106
- ctx.route.body.key,
107
- {
108
- ...ctx.route.body.schema,
109
- description: ctx.route.body.description(),
110
- },
111
- ],
112
- ]
113
- : []),
114
- ]),
115
- required: [
116
- ...ctx.route.parameters.map((p) => p.key),
117
- ...(ctx.route.query ? [ctx.route.query.key] : []),
118
- ...(ctx.route.body ? [ctx.route.body.key] : []),
119
- ],
120
- },
121
- }),
122
- );
123
- if (ctx.route.headers)
124
- declare(
125
- "Headers",
126
- NestiaMigrateSchemaProgrammer.write({
127
- components: ctx.components,
128
- importer: ctx.importer,
129
- schema: ctx.route.headers.schema,
130
- }),
131
- );
132
- if (ctx.route.query)
133
- declare(
134
- "Query",
135
- NestiaMigrateSchemaProgrammer.write({
136
- components: ctx.components,
137
- importer: ctx.importer,
138
- schema: ctx.route.query.schema,
139
- }),
140
- );
141
- if (ctx.route.body)
142
- declare(
143
- "Body",
144
- NestiaMigrateSchemaProgrammer.write({
145
- components: ctx.components,
146
- importer: ctx.importer,
147
- schema: ctx.route.body.schema,
148
- }),
149
- );
150
- if (ctx.route.success)
151
- declare(
152
- "Response",
153
- NestiaMigrateSchemaProgrammer.write({
154
- components: ctx.components,
155
- importer: ctx.importer,
156
- schema: ctx.route.success.schema,
157
- }),
158
- );
159
- return array;
160
- };
161
-
162
- const writeMetadata = (ctx: IContext): ts.VariableStatement =>
163
- constant(
164
- "METADATA",
165
- ts.factory.createAsExpression(
166
- ts.factory.createObjectLiteralExpression(
167
- [
168
- ts.factory.createPropertyAssignment(
169
- "method",
170
- ts.factory.createStringLiteral(ctx.route.method.toUpperCase()),
171
- ),
172
- ts.factory.createPropertyAssignment(
173
- "path",
174
- ts.factory.createStringLiteral(getPath(ctx.route)),
175
- ),
176
- ts.factory.createPropertyAssignment(
177
- "request",
178
- ctx.route.body
179
- ? LiteralFactory.write({
180
- type: ctx.route.body.type,
181
- encrypted: !!ctx.route.body["x-nestia-encrypted"],
182
- })
183
- : ts.factory.createNull(),
184
- ),
185
- ts.factory.createPropertyAssignment(
186
- "response",
187
- ctx.route.method.toUpperCase() !== "HEAD"
188
- ? LiteralFactory.write({
189
- type: ctx.route.success?.type ?? "application/json",
190
- encrypted: !!ctx.route.success?.["x-nestia-encrypted"],
191
- })
192
- : ts.factory.createNull(),
193
- ),
194
- ...(ctx.route.success?.type === "application/x-www-form-urlencoded"
195
- ? [
196
- ts.factory.createPropertyAssignment(
197
- "parseQuery",
198
- ts.factory.createCallExpression(
199
- ts.factory.createIdentifier(
200
- `${ctx.importer.external({
201
- type: "default",
202
- library: "typia",
203
- name: "typia",
204
- })}.http.createAssertQuery`,
205
- ),
206
- [
207
- NestiaMigrateSchemaProgrammer.write({
208
- components: ctx.components,
209
- importer: ctx.importer,
210
- schema: ctx.route.success.schema,
211
- }),
212
- ],
213
- undefined,
214
- ),
215
- ),
216
- ]
217
- : []),
218
- ],
219
- true,
220
- ),
221
- ts.factory.createTypeReferenceNode(
222
- ts.factory.createIdentifier("const"),
223
- ),
224
- ),
225
- );
226
-
227
- const writePathFunction = (ctx: IContext): ts.VariableStatement => {
228
- const empty: boolean =
229
- ctx.route.parameters.length === 0 && ctx.route.query === null;
230
- const property = (key: string) =>
231
- ctx.config.keyword === true
232
- ? IdentifierFactory.access(ts.factory.createIdentifier("props"), key)
233
- : ts.factory.createIdentifier(key);
234
- const out = (body: ts.ConciseBody) =>
235
- constant(
236
- "path",
237
- ts.factory.createArrowFunction(
238
- [],
239
- [],
240
- empty
241
- ? []
242
- : ctx.config.keyword === true
243
- ? [
244
- IdentifierFactory.parameter(
245
- "props",
246
- ctx.route.body
247
- ? ts.factory.createTypeReferenceNode("Omit", [
248
- ts.factory.createTypeReferenceNode("Props"),
249
- ts.factory.createLiteralTypeNode(
250
- ts.factory.createStringLiteral(ctx.route.body.key),
251
- ),
252
- ])
253
- : ts.factory.createTypeReferenceNode("Props"),
254
- ),
255
- ]
256
- : [
257
- ...ctx.route.parameters.map((p) =>
258
- IdentifierFactory.parameter(
259
- p.key,
260
- NestiaMigrateSchemaProgrammer.write({
261
- components: ctx.components,
262
- importer: ctx.importer,
263
- schema: p.schema,
264
- }),
265
- ),
266
- ),
267
- ...(ctx.route.query
268
- ? [
269
- IdentifierFactory.parameter(
270
- ctx.route.query.key,
271
- ts.factory.createTypeReferenceNode(
272
- `${ctx.route.accessor.at(-1)!}.Query`,
273
- ),
274
- ),
275
- ]
276
- : []),
277
- ],
278
- undefined,
279
- undefined,
280
- body,
281
- ),
282
- );
283
- const template = () => {
284
- const path: string = getPath(ctx.route);
285
- const split: string[] = path.split(":");
286
- if (split.length === 1) return ts.factory.createStringLiteral(path);
287
- return ts.factory.createTemplateExpression(
288
- ts.factory.createTemplateHead(split[0]),
289
- split.slice(1).map((s, i, arr) => {
290
- const name: string = s.split("/")[0];
291
- return ts.factory.createTemplateSpan(
292
- ts.factory.createCallExpression(
293
- ts.factory.createIdentifier("encodeURIComponent"),
294
- undefined,
295
- [
296
- ts.factory.createBinaryExpression(
297
- property(
298
- ctx.route.parameters.find((p) => p.name === name)!.key,
299
- ),
300
- ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken),
301
- ts.factory.createStringLiteral("null"),
302
- ),
303
- ],
304
- ),
305
- (i !== arr.length - 1
306
- ? ts.factory.createTemplateMiddle
307
- : ts.factory.createTemplateTail)(s.substring(name.length)),
308
- );
309
- }),
310
- );
311
- };
312
- if (!ctx.route.query) return out(template());
313
-
314
- const computeName = (str: string): string =>
315
- ctx.route.parameters.find((p) => p.key === str) !== undefined
316
- ? computeName("_" + str)
317
- : str;
318
- const variables: string = computeName("variables");
319
- return out(
320
- ts.factory.createBlock(
321
- [
322
- local({
323
- name: variables,
324
- type: "URLSearchParams",
325
- expression: ts.factory.createNewExpression(
326
- ts.factory.createIdentifier("URLSearchParams"),
327
- [],
328
- [],
329
- ),
330
- }),
331
- ts.factory.createForOfStatement(
332
- undefined,
333
- ts.factory.createVariableDeclarationList(
334
- [
335
- ts.factory.createVariableDeclaration(
336
- ts.factory.createArrayBindingPattern([
337
- ts.factory.createBindingElement(
338
- undefined,
339
- undefined,
340
- ts.factory.createIdentifier("key"),
341
- undefined,
342
- ),
343
- ts.factory.createBindingElement(
344
- undefined,
345
- undefined,
346
- ts.factory.createIdentifier("value"),
347
- undefined,
348
- ),
349
- ]),
350
- undefined,
351
- undefined,
352
- undefined,
353
- ),
354
- ],
355
- ts.NodeFlags.Const,
356
- ),
357
- ts.factory.createCallExpression(
358
- ts.factory.createIdentifier("Object.entries"),
359
- undefined,
360
- [
361
- ts.factory.createAsExpression(
362
- property(ctx.route.query.key),
363
- TypeFactory.keyword("any"),
364
- ),
365
- ],
366
- ),
367
- ts.factory.createIfStatement(
368
- ts.factory.createStrictEquality(
369
- ts.factory.createIdentifier("undefined"),
370
- ts.factory.createIdentifier("value"),
371
- ),
372
- ts.factory.createContinueStatement(),
373
- ts.factory.createIfStatement(
374
- ts.factory.createCallExpression(
375
- ts.factory.createIdentifier("Array.isArray"),
376
- undefined,
377
- [ts.factory.createIdentifier("value")],
378
- ),
379
- ts.factory.createExpressionStatement(
380
- ts.factory.createCallExpression(
381
- ts.factory.createPropertyAccessExpression(
382
- ts.factory.createIdentifier("value"),
383
- ts.factory.createIdentifier("forEach"),
384
- ),
385
- undefined,
386
- [
387
- ts.factory.createArrowFunction(
388
- undefined,
389
- undefined,
390
- [IdentifierFactory.parameter("elem")],
391
- undefined,
392
- undefined,
393
- ts.factory.createCallExpression(
394
- IdentifierFactory.access(
395
- ts.factory.createIdentifier(variables),
396
- "append",
397
- ),
398
- undefined,
399
- [
400
- ts.factory.createIdentifier("key"),
401
- ts.factory.createCallExpression(
402
- ts.factory.createIdentifier("String"),
403
- undefined,
404
- [ts.factory.createIdentifier("elem")],
405
- ),
406
- ],
407
- ),
408
- ),
409
- ],
410
- ),
411
- ),
412
- ts.factory.createExpressionStatement(
413
- ts.factory.createCallExpression(
414
- IdentifierFactory.access(
415
- ts.factory.createIdentifier(variables),
416
- "set",
417
- ),
418
- undefined,
419
- [
420
- ts.factory.createIdentifier("key"),
421
- ts.factory.createCallExpression(
422
- ts.factory.createIdentifier("String"),
423
- undefined,
424
- [ts.factory.createIdentifier("value")],
425
- ),
426
- ],
427
- ),
428
- ),
429
- ),
430
- ),
431
- ),
432
- local({
433
- name: "location",
434
- type: "string",
435
- expression: template(),
436
- }),
437
- ts.factory.createReturnStatement(
438
- ts.factory.createConditionalExpression(
439
- ts.factory.createStrictEquality(
440
- ExpressionFactory.number(0),
441
- IdentifierFactory.access(
442
- ts.factory.createIdentifier(variables),
443
- "size",
444
- ),
445
- ),
446
- undefined,
447
- ts.factory.createIdentifier("location"),
448
- undefined,
449
- ts.factory.createTemplateExpression(
450
- ts.factory.createTemplateHead(""),
451
- [
452
- ts.factory.createTemplateSpan(
453
- ts.factory.createIdentifier("location"),
454
- ts.factory.createTemplateMiddle("?"),
455
- ),
456
- ts.factory.createTemplateSpan(
457
- ts.factory.createCallExpression(
458
- IdentifierFactory.access(
459
- ts.factory.createIdentifier(variables),
460
- "toString",
461
- ),
462
- undefined,
463
- undefined,
464
- ),
465
- ts.factory.createTemplateTail(""),
466
- ),
467
- ],
468
- ),
469
- ),
470
- ),
471
- ],
472
- true,
473
- ),
474
- );
475
- };
476
- }
477
-
478
- const constant = (name: string, expression: ts.Expression) =>
479
- ts.factory.createVariableStatement(
480
- [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
481
- ts.factory.createVariableDeclarationList(
482
- [
483
- ts.factory.createVariableDeclaration(
484
- name,
485
- undefined,
486
- undefined,
487
- expression,
488
- ),
489
- ],
490
- ts.NodeFlags.Const,
491
- ),
492
- );
493
-
494
- const getPath = (route: IHttpMigrateRoute) =>
495
- (route.emendedPath.startsWith("/") ? "" : "/") + route.emendedPath;
496
-
497
- const local = (props: {
498
- name: string;
499
- type: string;
500
- expression: ts.Expression;
501
- }) =>
502
- ts.factory.createVariableStatement(
503
- [],
504
- ts.factory.createVariableDeclarationList(
505
- [
506
- ts.factory.createVariableDeclaration(
507
- props.name,
508
- undefined,
509
- ts.factory.createTypeReferenceNode(props.type),
510
- props.expression,
511
- ),
512
- ],
513
- ts.NodeFlags.Const,
514
- ),
515
- );
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 { FilePrinter } from "../utils/FilePrinter";
10
+ import { NestiaMigrateApiSimulationProgrammer } from "./NestiaMigrateApiSimulationProgrammer";
11
+ import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
12
+ import { NestiaMigrateSchemaProgrammer } from "./NestiaMigrateSchemaProgrammer";
13
+
14
+ export namespace NestiaMigrateApiNamespaceProgrammer {
15
+ export interface IContext {
16
+ config: INestiaMigrateConfig;
17
+ components: OpenApi.IComponents;
18
+ importer: NestiaMigrateImportProgrammer;
19
+ route: IHttpMigrateRoute;
20
+ }
21
+
22
+ export const write = (ctx: IContext): ts.ModuleDeclaration => {
23
+ const types: ts.TypeAliasDeclaration[] = writeTypes(ctx);
24
+ return ts.factory.createModuleDeclaration(
25
+ [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
26
+ ts.factory.createIdentifier(ctx.route.accessor.at(-1)!),
27
+ ts.factory.createModuleBlock([
28
+ ...types,
29
+ ...(types.length ? [FilePrinter.newLine()] : []),
30
+ writeMetadata(ctx),
31
+ FilePrinter.newLine(),
32
+ writePathFunction(ctx),
33
+ ...(ctx.config.simulate === true
34
+ ? [
35
+ NestiaMigrateApiSimulationProgrammer.random(ctx),
36
+ NestiaMigrateApiSimulationProgrammer.simulate(ctx),
37
+ ]
38
+ : []),
39
+ ]),
40
+ ts.NodeFlags.Namespace,
41
+ );
42
+ };
43
+
44
+ export const writePathCallExpression = (
45
+ config: INestiaMigrateConfig,
46
+ route: IHttpMigrateRoute,
47
+ ) =>
48
+ ts.factory.createCallExpression(
49
+ ts.factory.createIdentifier(`${route.accessor.at(-1)!}.path`),
50
+ undefined,
51
+ route.parameters.length === 0 && route.query === null
52
+ ? []
53
+ : config.keyword === true
54
+ ? [ts.factory.createIdentifier("props")]
55
+ : [...route.parameters, ...(route.query ? [route.query] : [])].map(
56
+ (p) => ts.factory.createIdentifier(p.key),
57
+ ),
58
+ );
59
+
60
+ const writeTypes = (ctx: IContext): ts.TypeAliasDeclaration[] => {
61
+ const array: ts.TypeAliasDeclaration[] = [];
62
+ const declare = (name: string, type: ts.TypeNode) =>
63
+ array.push(
64
+ ts.factory.createTypeAliasDeclaration(
65
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
66
+ name,
67
+ undefined,
68
+ type,
69
+ ),
70
+ );
71
+ if (
72
+ ctx.config.keyword === true &&
73
+ (ctx.route.parameters.length > 0 || ctx.route.query || ctx.route.body)
74
+ )
75
+ declare(
76
+ "Props",
77
+ NestiaMigrateSchemaProgrammer.write({
78
+ components: ctx.components,
79
+ importer: ctx.importer,
80
+ schema: {
81
+ type: "object",
82
+ properties: Object.fromEntries([
83
+ ...ctx.route.parameters.map((p) => [
84
+ p.key,
85
+ {
86
+ ...p.schema,
87
+ title: p.parameter().title,
88
+ description: p.parameter().description,
89
+ },
90
+ ]),
91
+ ...(ctx.route.query
92
+ ? [
93
+ [
94
+ ctx.route.query.key,
95
+ {
96
+ ...ctx.route.query.schema,
97
+ title: ctx.route.query.title(),
98
+ description: ctx.route.query.description(),
99
+ },
100
+ ],
101
+ ]
102
+ : []),
103
+ ...(ctx.route.body
104
+ ? [
105
+ [
106
+ ctx.route.body.key,
107
+ {
108
+ ...ctx.route.body.schema,
109
+ description: ctx.route.body.description(),
110
+ },
111
+ ],
112
+ ]
113
+ : []),
114
+ ]),
115
+ required: [
116
+ ...ctx.route.parameters.map((p) => p.key),
117
+ ...(ctx.route.query ? [ctx.route.query.key] : []),
118
+ ...(ctx.route.body ? [ctx.route.body.key] : []),
119
+ ],
120
+ },
121
+ }),
122
+ );
123
+ if (ctx.route.headers)
124
+ declare(
125
+ "Headers",
126
+ NestiaMigrateSchemaProgrammer.write({
127
+ components: ctx.components,
128
+ importer: ctx.importer,
129
+ schema: ctx.route.headers.schema,
130
+ }),
131
+ );
132
+ if (ctx.route.query)
133
+ declare(
134
+ "Query",
135
+ NestiaMigrateSchemaProgrammer.write({
136
+ components: ctx.components,
137
+ importer: ctx.importer,
138
+ schema: ctx.route.query.schema,
139
+ }),
140
+ );
141
+ if (ctx.route.body)
142
+ declare(
143
+ "Body",
144
+ NestiaMigrateSchemaProgrammer.write({
145
+ components: ctx.components,
146
+ importer: ctx.importer,
147
+ schema: ctx.route.body.schema,
148
+ }),
149
+ );
150
+ if (ctx.route.success)
151
+ declare(
152
+ "Response",
153
+ NestiaMigrateSchemaProgrammer.write({
154
+ components: ctx.components,
155
+ importer: ctx.importer,
156
+ schema: ctx.route.success.schema,
157
+ }),
158
+ );
159
+ return array;
160
+ };
161
+
162
+ const writeMetadata = (ctx: IContext): ts.VariableStatement =>
163
+ constant(
164
+ "METADATA",
165
+ ts.factory.createAsExpression(
166
+ ts.factory.createObjectLiteralExpression(
167
+ [
168
+ ts.factory.createPropertyAssignment(
169
+ "method",
170
+ ts.factory.createStringLiteral(ctx.route.method.toUpperCase()),
171
+ ),
172
+ ts.factory.createPropertyAssignment(
173
+ "path",
174
+ ts.factory.createStringLiteral(getPath(ctx.route)),
175
+ ),
176
+ ts.factory.createPropertyAssignment(
177
+ "request",
178
+ ctx.route.body
179
+ ? LiteralFactory.write({
180
+ type: ctx.route.body.type,
181
+ encrypted: !!ctx.route.body["x-nestia-encrypted"],
182
+ })
183
+ : ts.factory.createNull(),
184
+ ),
185
+ ts.factory.createPropertyAssignment(
186
+ "response",
187
+ ctx.route.method.toUpperCase() !== "HEAD"
188
+ ? LiteralFactory.write({
189
+ type: ctx.route.success?.type ?? "application/json",
190
+ encrypted: !!ctx.route.success?.["x-nestia-encrypted"],
191
+ })
192
+ : ts.factory.createNull(),
193
+ ),
194
+ ...(ctx.route.success?.type === "application/x-www-form-urlencoded"
195
+ ? [
196
+ ts.factory.createPropertyAssignment(
197
+ "parseQuery",
198
+ ts.factory.createCallExpression(
199
+ ts.factory.createIdentifier(
200
+ `${ctx.importer.external({
201
+ type: "default",
202
+ library: "typia",
203
+ name: "typia",
204
+ })}.http.createAssertQuery`,
205
+ ),
206
+ [
207
+ NestiaMigrateSchemaProgrammer.write({
208
+ components: ctx.components,
209
+ importer: ctx.importer,
210
+ schema: ctx.route.success.schema,
211
+ }),
212
+ ],
213
+ undefined,
214
+ ),
215
+ ),
216
+ ]
217
+ : []),
218
+ ],
219
+ true,
220
+ ),
221
+ ts.factory.createTypeReferenceNode(
222
+ ts.factory.createIdentifier("const"),
223
+ ),
224
+ ),
225
+ );
226
+
227
+ const writePathFunction = (ctx: IContext): ts.VariableStatement => {
228
+ const empty: boolean =
229
+ ctx.route.parameters.length === 0 && ctx.route.query === null;
230
+ const property = (key: string) =>
231
+ ctx.config.keyword === true
232
+ ? IdentifierFactory.access(ts.factory.createIdentifier("props"), key)
233
+ : ts.factory.createIdentifier(key);
234
+ const out = (body: ts.ConciseBody) =>
235
+ constant(
236
+ "path",
237
+ ts.factory.createArrowFunction(
238
+ [],
239
+ [],
240
+ empty
241
+ ? []
242
+ : ctx.config.keyword === true
243
+ ? [
244
+ IdentifierFactory.parameter(
245
+ "props",
246
+ ctx.route.body
247
+ ? ts.factory.createTypeReferenceNode("Omit", [
248
+ ts.factory.createTypeReferenceNode("Props"),
249
+ ts.factory.createLiteralTypeNode(
250
+ ts.factory.createStringLiteral(ctx.route.body.key),
251
+ ),
252
+ ])
253
+ : ts.factory.createTypeReferenceNode("Props"),
254
+ ),
255
+ ]
256
+ : [
257
+ ...ctx.route.parameters.map((p) =>
258
+ IdentifierFactory.parameter(
259
+ p.key,
260
+ NestiaMigrateSchemaProgrammer.write({
261
+ components: ctx.components,
262
+ importer: ctx.importer,
263
+ schema: p.schema,
264
+ }),
265
+ ),
266
+ ),
267
+ ...(ctx.route.query
268
+ ? [
269
+ IdentifierFactory.parameter(
270
+ ctx.route.query.key,
271
+ ts.factory.createTypeReferenceNode(
272
+ `${ctx.route.accessor.at(-1)!}.Query`,
273
+ ),
274
+ ),
275
+ ]
276
+ : []),
277
+ ],
278
+ undefined,
279
+ undefined,
280
+ body,
281
+ ),
282
+ );
283
+ const template = () => {
284
+ const path: string = getPath(ctx.route);
285
+ const split: string[] = path.split(":");
286
+ if (split.length === 1) return ts.factory.createStringLiteral(path);
287
+ return ts.factory.createTemplateExpression(
288
+ ts.factory.createTemplateHead(split[0]),
289
+ split.slice(1).map((s, i, arr) => {
290
+ const name: string = s.split("/")[0];
291
+ return ts.factory.createTemplateSpan(
292
+ ts.factory.createCallExpression(
293
+ ts.factory.createIdentifier("encodeURIComponent"),
294
+ undefined,
295
+ [
296
+ ts.factory.createBinaryExpression(
297
+ property(
298
+ ctx.route.parameters.find((p) => p.name === name)!.key,
299
+ ),
300
+ ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken),
301
+ ts.factory.createStringLiteral("null"),
302
+ ),
303
+ ],
304
+ ),
305
+ (i !== arr.length - 1
306
+ ? ts.factory.createTemplateMiddle
307
+ : ts.factory.createTemplateTail)(s.substring(name.length)),
308
+ );
309
+ }),
310
+ );
311
+ };
312
+ if (!ctx.route.query) return out(template());
313
+
314
+ const computeName = (str: string): string =>
315
+ ctx.route.parameters.find((p) => p.key === str) !== undefined
316
+ ? computeName("_" + str)
317
+ : str;
318
+ const variables: string = computeName("variables");
319
+ return out(
320
+ ts.factory.createBlock(
321
+ [
322
+ local({
323
+ name: variables,
324
+ type: "URLSearchParams",
325
+ expression: ts.factory.createNewExpression(
326
+ ts.factory.createIdentifier("URLSearchParams"),
327
+ [],
328
+ [],
329
+ ),
330
+ }),
331
+ ts.factory.createForOfStatement(
332
+ undefined,
333
+ ts.factory.createVariableDeclarationList(
334
+ [
335
+ ts.factory.createVariableDeclaration(
336
+ ts.factory.createArrayBindingPattern([
337
+ ts.factory.createBindingElement(
338
+ undefined,
339
+ undefined,
340
+ ts.factory.createIdentifier("key"),
341
+ undefined,
342
+ ),
343
+ ts.factory.createBindingElement(
344
+ undefined,
345
+ undefined,
346
+ ts.factory.createIdentifier("value"),
347
+ undefined,
348
+ ),
349
+ ]),
350
+ undefined,
351
+ undefined,
352
+ undefined,
353
+ ),
354
+ ],
355
+ ts.NodeFlags.Const,
356
+ ),
357
+ ts.factory.createCallExpression(
358
+ ts.factory.createIdentifier("Object.entries"),
359
+ undefined,
360
+ [
361
+ ts.factory.createAsExpression(
362
+ property(ctx.route.query.key),
363
+ TypeFactory.keyword("any"),
364
+ ),
365
+ ],
366
+ ),
367
+ ts.factory.createIfStatement(
368
+ ts.factory.createStrictEquality(
369
+ ts.factory.createIdentifier("undefined"),
370
+ ts.factory.createIdentifier("value"),
371
+ ),
372
+ ts.factory.createContinueStatement(),
373
+ ts.factory.createIfStatement(
374
+ ts.factory.createCallExpression(
375
+ ts.factory.createIdentifier("Array.isArray"),
376
+ undefined,
377
+ [ts.factory.createIdentifier("value")],
378
+ ),
379
+ ts.factory.createExpressionStatement(
380
+ ts.factory.createCallExpression(
381
+ ts.factory.createPropertyAccessExpression(
382
+ ts.factory.createIdentifier("value"),
383
+ ts.factory.createIdentifier("forEach"),
384
+ ),
385
+ undefined,
386
+ [
387
+ ts.factory.createArrowFunction(
388
+ undefined,
389
+ undefined,
390
+ [IdentifierFactory.parameter("elem")],
391
+ undefined,
392
+ undefined,
393
+ ts.factory.createCallExpression(
394
+ IdentifierFactory.access(
395
+ ts.factory.createIdentifier(variables),
396
+ "append",
397
+ ),
398
+ undefined,
399
+ [
400
+ ts.factory.createIdentifier("key"),
401
+ ts.factory.createCallExpression(
402
+ ts.factory.createIdentifier("String"),
403
+ undefined,
404
+ [ts.factory.createIdentifier("elem")],
405
+ ),
406
+ ],
407
+ ),
408
+ ),
409
+ ],
410
+ ),
411
+ ),
412
+ ts.factory.createExpressionStatement(
413
+ ts.factory.createCallExpression(
414
+ IdentifierFactory.access(
415
+ ts.factory.createIdentifier(variables),
416
+ "set",
417
+ ),
418
+ undefined,
419
+ [
420
+ ts.factory.createIdentifier("key"),
421
+ ts.factory.createCallExpression(
422
+ ts.factory.createIdentifier("String"),
423
+ undefined,
424
+ [ts.factory.createIdentifier("value")],
425
+ ),
426
+ ],
427
+ ),
428
+ ),
429
+ ),
430
+ ),
431
+ ),
432
+ local({
433
+ name: "location",
434
+ type: "string",
435
+ expression: template(),
436
+ }),
437
+ ts.factory.createReturnStatement(
438
+ ts.factory.createConditionalExpression(
439
+ ts.factory.createStrictEquality(
440
+ ExpressionFactory.number(0),
441
+ IdentifierFactory.access(
442
+ ts.factory.createIdentifier(variables),
443
+ "size",
444
+ ),
445
+ ),
446
+ undefined,
447
+ ts.factory.createIdentifier("location"),
448
+ undefined,
449
+ ts.factory.createTemplateExpression(
450
+ ts.factory.createTemplateHead(""),
451
+ [
452
+ ts.factory.createTemplateSpan(
453
+ ts.factory.createIdentifier("location"),
454
+ ts.factory.createTemplateMiddle("?"),
455
+ ),
456
+ ts.factory.createTemplateSpan(
457
+ ts.factory.createCallExpression(
458
+ IdentifierFactory.access(
459
+ ts.factory.createIdentifier(variables),
460
+ "toString",
461
+ ),
462
+ undefined,
463
+ undefined,
464
+ ),
465
+ ts.factory.createTemplateTail(""),
466
+ ),
467
+ ],
468
+ ),
469
+ ),
470
+ ),
471
+ ],
472
+ true,
473
+ ),
474
+ );
475
+ };
476
+ }
477
+
478
+ const constant = (name: string, expression: ts.Expression) =>
479
+ ts.factory.createVariableStatement(
480
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
481
+ ts.factory.createVariableDeclarationList(
482
+ [
483
+ ts.factory.createVariableDeclaration(
484
+ name,
485
+ undefined,
486
+ undefined,
487
+ expression,
488
+ ),
489
+ ],
490
+ ts.NodeFlags.Const,
491
+ ),
492
+ );
493
+
494
+ const getPath = (route: IHttpMigrateRoute) =>
495
+ (route.emendedPath.startsWith("/") ? "" : "/") + route.emendedPath;
496
+
497
+ const local = (props: {
498
+ name: string;
499
+ type: string;
500
+ expression: ts.Expression;
501
+ }) =>
502
+ ts.factory.createVariableStatement(
503
+ [],
504
+ ts.factory.createVariableDeclarationList(
505
+ [
506
+ ts.factory.createVariableDeclaration(
507
+ props.name,
508
+ undefined,
509
+ ts.factory.createTypeReferenceNode(props.type),
510
+ props.expression,
511
+ ),
512
+ ],
513
+ ts.NodeFlags.Const,
514
+ ),
515
+ );