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