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

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