@nestia/migrate 10.0.2 → 11.0.0-dev.20260312

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 (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -93
  3. package/lib/NestiaMigrateApplication.d.ts +3 -3
  4. package/lib/NestiaMigrateApplication.js +10086 -7707
  5. package/lib/NestiaMigrateApplication.js.map +1 -1
  6. package/lib/analyzers/NestiaMigrateControllerAnalyzer.d.ts +1 -1
  7. package/lib/analyzers/NestiaMigrateControllerAnalyzer.js.map +1 -1
  8. package/lib/bundles/NEST_TEMPLATE.js +48 -48
  9. package/lib/bundles/NEST_TEMPLATE.js.map +1 -1
  10. package/lib/bundles/SDK_TEMPLATE.js +21 -21
  11. package/lib/bundles/SDK_TEMPLATE.js.map +1 -1
  12. package/lib/executable/NestiaMigrateCommander.js +4 -4
  13. package/lib/executable/NestiaMigrateCommander.js.map +1 -1
  14. package/lib/executable/NestiaMigrateInquirer.js +13 -16
  15. package/lib/executable/NestiaMigrateInquirer.js.map +1 -1
  16. package/lib/factories/TypeLiteralFactory.js +2 -2
  17. package/lib/factories/TypeLiteralFactory.js.map +1 -1
  18. package/lib/index.mjs +9540 -7065
  19. package/lib/index.mjs.map +1 -1
  20. package/lib/module.d.ts +3 -0
  21. package/lib/module.js +3 -0
  22. package/lib/module.js.map +1 -1
  23. package/lib/programmers/NestiaMigrateApiFileProgrammer.d.ts +1 -1
  24. package/lib/programmers/NestiaMigrateApiFunctionProgrammer.d.ts +1 -1
  25. package/lib/programmers/NestiaMigrateApiFunctionProgrammer.js +16 -15
  26. package/lib/programmers/NestiaMigrateApiFunctionProgrammer.js.map +1 -1
  27. package/lib/programmers/NestiaMigrateApiNamespaceProgrammer.d.ts +2 -1
  28. package/lib/programmers/NestiaMigrateApiNamespaceProgrammer.js +12 -15
  29. package/lib/programmers/NestiaMigrateApiNamespaceProgrammer.js.map +1 -1
  30. package/lib/programmers/NestiaMigrateApiSimulationProgrammer.d.ts +2 -1
  31. package/lib/programmers/NestiaMigrateApiSimulationProgrammer.js +11 -13
  32. package/lib/programmers/NestiaMigrateApiSimulationProgrammer.js.map +1 -1
  33. package/lib/programmers/NestiaMigrateApiStartProgrammer.js +3 -4
  34. package/lib/programmers/NestiaMigrateApiStartProgrammer.js.map +1 -1
  35. package/lib/programmers/NestiaMigrateDtoProgrammer.d.ts +1 -1
  36. package/lib/programmers/NestiaMigrateE2eFileProgrammer.d.ts +2 -1
  37. package/lib/programmers/NestiaMigrateE2eFileProgrammer.js +3 -4
  38. package/lib/programmers/NestiaMigrateE2eFileProgrammer.js.map +1 -1
  39. package/lib/programmers/NestiaMigrateImportProgrammer.js.map +1 -1
  40. package/lib/programmers/NestiaMigrateNestControllerProgrammer.d.ts +1 -1
  41. package/lib/programmers/NestiaMigrateNestMethodProgrammer.d.ts +2 -1
  42. package/lib/programmers/NestiaMigrateNestMethodProgrammer.js +10 -13
  43. package/lib/programmers/NestiaMigrateNestMethodProgrammer.js.map +1 -1
  44. package/lib/programmers/NestiaMigrateSchemaProgrammer.d.ts +1 -1
  45. package/lib/programmers/NestiaMigrateSchemaProgrammer.js +26 -28
  46. package/lib/programmers/NestiaMigrateSchemaProgrammer.js.map +1 -1
  47. package/lib/structures/INestiaMigrateContext.d.ts +1 -1
  48. package/lib/structures/INestiaMigrateController.d.ts +1 -1
  49. package/lib/structures/INestiaMigrateDto.d.ts +1 -1
  50. package/lib/structures/INestiaMigrateProgram.d.ts +1 -1
  51. package/lib/utils/StringUtil.js.map +1 -1
  52. package/package.json +32 -46
  53. package/src/NestiaMigrateApplication.ts +165 -159
  54. package/src/analyzers/NestiaMigrateControllerAnalyzer.ts +51 -51
  55. package/src/bundles/NEST_TEMPLATE.ts +48 -48
  56. package/src/bundles/SDK_TEMPLATE.ts +21 -21
  57. package/src/executable/NestiaMigrateCommander.ts +104 -98
  58. package/src/executable/NestiaMigrateInquirer.ts +106 -106
  59. package/src/executable/bundle.js +125 -125
  60. package/src/executable/migrate.ts +0 -0
  61. package/src/factories/TypeLiteralFactory.ts +57 -57
  62. package/src/module.ts +7 -2
  63. package/src/programmers/NestiaMigrateApiFileProgrammer.ts +55 -55
  64. package/src/programmers/NestiaMigrateApiFunctionProgrammer.ts +347 -344
  65. package/src/programmers/NestiaMigrateApiNamespaceProgrammer.ts +517 -514
  66. package/src/programmers/NestiaMigrateApiSimulationProgrammer.ts +308 -309
  67. package/src/programmers/NestiaMigrateApiStartProgrammer.ts +197 -198
  68. package/src/programmers/NestiaMigrateDtoProgrammer.ts +98 -98
  69. package/src/programmers/NestiaMigrateE2eFileProgrammer.ts +153 -153
  70. package/src/programmers/NestiaMigrateE2eProgrammer.ts +48 -48
  71. package/src/programmers/NestiaMigrateImportProgrammer.ts +118 -118
  72. package/src/programmers/NestiaMigrateNestControllerProgrammer.ts +69 -69
  73. package/src/programmers/NestiaMigrateNestMethodProgrammer.ts +409 -406
  74. package/src/programmers/NestiaMigrateSchemaProgrammer.ts +465 -467
  75. package/src/programmers/index.ts +15 -0
  76. package/src/structures/INestiaMigrateContext.ts +9 -9
  77. package/src/structures/INestiaMigrateController.ts +8 -8
  78. package/src/structures/INestiaMigrateDto.ts +8 -8
  79. package/src/structures/INestiaMigrateProgram.ts +11 -11
  80. package/src/structures/index.ts +4 -0
  81. package/src/utils/FilePrinter.ts +49 -49
  82. package/src/utils/StringUtil.ts +114 -113
@@ -1,344 +1,347 @@
1
- import { IHttpMigrateRoute, OpenApi } from "@samchon/openapi";
2
- import ts from "typescript";
3
- import { IdentifierFactory } from "typia/lib/factories/IdentifierFactory";
4
- import { StatementFactory } from "typia/lib/factories/StatementFactory";
5
- import { Escaper } from "typia/lib/utils/Escaper";
6
-
7
- import { INestiaMigrateConfig } from "../structures/INestiaMigrateConfig";
8
- import { FilePrinter } from "../utils/FilePrinter";
9
- import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
10
- import { NestiaMigrateSchemaProgrammer } from "./NestiaMigrateSchemaProgrammer";
11
-
12
- export namespace NestiaMigrateApiFunctionProgrammer {
13
- export interface IContext {
14
- config: INestiaMigrateConfig;
15
- components: OpenApi.IComponents;
16
- importer: NestiaMigrateImportProgrammer;
17
- route: IHttpMigrateRoute;
18
- }
19
-
20
- export const write = (ctx: IContext): ts.FunctionDeclaration =>
21
- FilePrinter.description(
22
- ts.factory.createFunctionDeclaration(
23
- [
24
- ts.factory.createModifier(ts.SyntaxKind.ExportKeyword),
25
- ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword),
26
- ],
27
- undefined,
28
- ctx.route.accessor.at(-1)!,
29
- undefined,
30
- writeParameterDeclarations(ctx),
31
- ts.factory.createTypeReferenceNode("Promise", [
32
- ts.factory.createTypeReferenceNode(
33
- ctx.route.success === null
34
- ? "void"
35
- : `${ctx.route.accessor.at(-1)!}.Response`,
36
- ),
37
- ]),
38
- ts.factory.createBlock(writeBody(ctx), true),
39
- ),
40
- writeDescription(ctx.config, ctx.route),
41
- );
42
-
43
- export const writeParameterDeclarations = (
44
- ctx: IContext,
45
- connectionName?: string,
46
- ): ts.ParameterDeclaration[] => {
47
- const connection: ts.ParameterDeclaration = IdentifierFactory.parameter(
48
- connectionName ?? "connection",
49
- ts.factory.createTypeReferenceNode(
50
- ctx.importer.external({
51
- type: "instance",
52
- library: "@nestia/fetcher",
53
- name: "IConnection",
54
- }),
55
- ctx.route.headers
56
- ? [
57
- ts.factory.createTypeReferenceNode(
58
- `${ctx.route.accessor.at(-1)!}.Headers`,
59
- ),
60
- ]
61
- : undefined,
62
- ),
63
- );
64
- if (ctx.config.keyword === true) {
65
- const isProps: boolean =
66
- ctx.route.parameters.length > 0 ||
67
- !!ctx.route.query ||
68
- !!ctx.route.body;
69
- if (isProps === false) return [connection];
70
- return [
71
- connection,
72
- ts.factory.createParameterDeclaration(
73
- undefined,
74
- undefined,
75
- "props",
76
- undefined,
77
- ts.factory.createTypeReferenceNode(
78
- `${ctx.route.accessor.at(-1)!}.Props`,
79
- ),
80
- ),
81
- ];
82
- }
83
- return [
84
- connection,
85
- ...ctx.route.parameters.map((p) =>
86
- IdentifierFactory.parameter(
87
- p.key,
88
- NestiaMigrateSchemaProgrammer.write({
89
- components: ctx.components,
90
- importer: ctx.importer,
91
- schema: p.schema,
92
- }),
93
- ),
94
- ),
95
- ...(ctx.route.query
96
- ? [
97
- IdentifierFactory.parameter(
98
- ctx.route.query.key,
99
- ts.factory.createTypeReferenceNode(
100
- `${ctx.route.accessor.at(-1)!}.Query`,
101
- ),
102
- ),
103
- ]
104
- : []),
105
- ...(ctx.route.body
106
- ? [
107
- IdentifierFactory.parameter(
108
- ctx.route.body.key,
109
- ts.factory.createTypeReferenceNode(
110
- `${ctx.route.accessor.at(-1)!}.Body`,
111
- ),
112
- (ctx.route.body.type === "application/json" ||
113
- ctx.route.body.type === "text/plain") &&
114
- ctx.route.operation().requestBody?.required === false
115
- ? ts.factory.createToken(ts.SyntaxKind.QuestionToken)
116
- : undefined,
117
- ),
118
- ]
119
- : []),
120
- ];
121
- };
122
-
123
- const writeDescription = (
124
- config: INestiaMigrateConfig,
125
- route: IHttpMigrateRoute,
126
- ): string => {
127
- const comment: string = route.comment();
128
- return [
129
- config.keyword === true
130
- ? comment.split("@param ").join("@param props.")
131
- : comment,
132
- `@path ${route.emendedPath}`,
133
- `@accessor api.functional.${route.accessor.join(".")}`,
134
- `@${config.author?.tag ?? "nestia"} ${config.author?.value ?? "Generated by Nestia - https://github.com/samchon/nestia"}`,
135
- ].join("\n");
136
- };
137
-
138
- const writeBody = (ctx: IContext): ts.Statement[] => {
139
- const encrypted: boolean = !!ctx.route.success?.["x-nestia-encrypted"];
140
- const contentType: string = ctx.route.body?.type ?? "application/json";
141
-
142
- const property = (key: string): ts.Expression =>
143
- ctx.config.keyword === true
144
- ? IdentifierFactory.access(ts.factory.createIdentifier("props"), key)
145
- : ts.factory.createIdentifier(key);
146
- const fetch = () =>
147
- ts.factory.createAwaitExpression(
148
- ts.factory.createCallExpression(
149
- IdentifierFactory.access(
150
- ts.factory.createIdentifier(
151
- ctx.importer.external({
152
- type: "instance",
153
- library: `@nestia/fetcher/lib/${encrypted ? "EncryptedFetcher" : "PlainFetcher"}`,
154
- name: encrypted ? "EncryptedFetcher" : "PlainFetcher",
155
- }),
156
- ),
157
- "fetch",
158
- ),
159
- undefined,
160
- [
161
- contentType && contentType !== "multipart/form-data"
162
- ? ts.factory.createObjectLiteralExpression(
163
- [
164
- ts.factory.createSpreadAssignment(
165
- ts.factory.createIdentifier("connection"),
166
- ),
167
- ts.factory.createPropertyAssignment(
168
- "headers",
169
- ts.factory.createObjectLiteralExpression(
170
- [
171
- ts.factory.createSpreadAssignment(
172
- IdentifierFactory.access(
173
- ts.factory.createIdentifier("connection"),
174
- "headers",
175
- ),
176
- ),
177
- ts.factory.createPropertyAssignment(
178
- ts.factory.createStringLiteral("Content-Type"),
179
- ts.factory.createStringLiteral(contentType),
180
- ),
181
- ],
182
- true,
183
- ),
184
- ),
185
- ],
186
- true,
187
- )
188
- : ts.factory.createIdentifier("connection"),
189
- ts.factory.createObjectLiteralExpression(
190
- [
191
- ts.factory.createSpreadAssignment(
192
- IdentifierFactory.access(
193
- ts.factory.createIdentifier(ctx.route.accessor.at(-1)!),
194
- "METADATA",
195
- ),
196
- ),
197
- ts.factory.createPropertyAssignment(
198
- "path",
199
- ts.factory.createCallExpression(
200
- IdentifierFactory.access(
201
- ts.factory.createIdentifier(ctx.route.accessor.at(-1)!),
202
- "path",
203
- ),
204
- undefined,
205
- getArguments(ctx, false),
206
- ),
207
- ),
208
- ts.factory.createPropertyAssignment(
209
- "status",
210
- ts.factory.createNull(),
211
- ),
212
- ],
213
- true,
214
- ),
215
- ...(ctx.route.body ? [property(ctx.route.body.key)] : []),
216
- ],
217
- ),
218
- );
219
-
220
- const value: ts.Expression =
221
- ctx.config.simulate !== true
222
- ? fetch()
223
- : ts.factory.createConditionalExpression(
224
- ts.factory.createStrictEquality(
225
- ts.factory.createTrue(),
226
- ts.factory.createIdentifier("connection.simulate"),
227
- ),
228
- undefined,
229
- ts.factory.createCallExpression(
230
- ts.factory.createIdentifier(
231
- `${ctx.route.accessor.at(-1)!}.simulate`,
232
- ),
233
- [],
234
- [
235
- ts.factory.createIdentifier("connection"),
236
- ...getArguments(ctx, true),
237
- ],
238
- ),
239
- undefined,
240
- fetch(),
241
- );
242
- const headers: Array<IAssignHeader | ISetHeader> = getHeaders(
243
- ctx.route.comment(),
244
- );
245
- if (headers.length === 0) return [ts.factory.createReturnStatement(value)];
246
- return [
247
- StatementFactory.constant({
248
- name: "output",
249
- type: ts.factory.createTypeReferenceNode(
250
- `${ctx.route.accessor.at(-1)!}.Response`,
251
- ),
252
- value,
253
- }),
254
- ts.factory.createExpressionStatement(
255
- ts.factory.createBinaryExpression(
256
- ts.factory.createIdentifier("connection.headers"),
257
- ts.factory.createToken(ts.SyntaxKind.QuestionQuestionEqualsToken),
258
- ts.factory.createObjectLiteralExpression([]),
259
- ),
260
- ),
261
- ...headers.map((h) =>
262
- ts.factory.createExpressionStatement(
263
- h.type === "assign"
264
- ? ts.factory.createCallExpression(
265
- ts.factory.createIdentifier("Object.assign"),
266
- undefined,
267
- [
268
- ts.factory.createIdentifier("connection.headers"),
269
- ts.factory.createIdentifier(`output.${h.accessor}`),
270
- ],
271
- )
272
- : ts.factory.createBinaryExpression(
273
- ts.factory.createIdentifier(
274
- `connection.headers${Escaper.variable(h.property) ? `.${h.property}` : `[${JSON.stringify(h.property)}]`}`,
275
- ),
276
- ts.factory.createToken(ts.SyntaxKind.EqualsToken),
277
- ts.factory.createIdentifier(`output.${h.accessor}`),
278
- ),
279
- ),
280
- ),
281
- ts.factory.createReturnStatement(ts.factory.createIdentifier("output")),
282
- ];
283
- };
284
-
285
- const getArguments = (ctx: IContext, body: boolean): ts.Expression[] => {
286
- if (
287
- ctx.route.parameters.length === 0 &&
288
- ctx.route.query === null &&
289
- (body === false || ctx.route.body === null)
290
- )
291
- return [];
292
- else if (ctx.config.keyword === true)
293
- return [ts.factory.createIdentifier("props")];
294
- return [
295
- ...ctx.route.parameters.map((p) => ts.factory.createIdentifier(p.key)),
296
- ...(ctx.route.query
297
- ? [ts.factory.createIdentifier(ctx.route.query.key)]
298
- : []),
299
- ...(body && ctx.route.body
300
- ? [ts.factory.createIdentifier(ctx.route.body.key)]
301
- : []),
302
- ];
303
- };
304
-
305
- const getHeaders = (
306
- description: string,
307
- ): Array<IAssignHeader | ISetHeader> => {
308
- const directives: Array<IAssignHeader | ISetHeader> = [];
309
- for (const line of description.split("\n").map((l) => l.trim())) {
310
- if (line.startsWith("@setHeader ")) {
311
- const parts: string[] = line
312
- .substring("@setHeader ".length)
313
- .trim()
314
- .split(/\s+/);
315
- if (parts.length >= 2)
316
- directives.push({
317
- type: "set",
318
- accessor: parts[0],
319
- property: parts[1],
320
- });
321
- } else if (line.startsWith("@assignHeaders ")) {
322
- const accessor: string = line
323
- .substring("@assignHeaders ".length)
324
- .trim();
325
- if (accessor.length !== 0)
326
- directives.push({
327
- type: "assign",
328
- accessor,
329
- });
330
- }
331
- }
332
- return directives;
333
- };
334
- }
335
-
336
- interface IAssignHeader {
337
- type: "assign";
338
- accessor: string;
339
- }
340
- interface ISetHeader {
341
- type: "set";
342
- accessor: string;
343
- property: string;
344
- }
1
+ import { IdentifierFactory, StatementFactory } from "@typia/core";
2
+ import { IHttpMigrateRoute, OpenApi } from "@typia/interface";
3
+ import { NamingConvention } from "@typia/utils";
4
+ import ts from "typescript";
5
+
6
+ import { INestiaMigrateConfig } from "../structures/INestiaMigrateConfig";
7
+ import { FilePrinter } from "../utils/FilePrinter";
8
+ import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
9
+ import { NestiaMigrateSchemaProgrammer } from "./NestiaMigrateSchemaProgrammer";
10
+
11
+ export namespace NestiaMigrateApiFunctionProgrammer {
12
+ export interface IContext {
13
+ config: INestiaMigrateConfig;
14
+ components: OpenApi.IComponents;
15
+ importer: NestiaMigrateImportProgrammer;
16
+ route: IHttpMigrateRoute;
17
+ }
18
+
19
+ export const write = (ctx: IContext): ts.FunctionDeclaration =>
20
+ FilePrinter.description(
21
+ ts.factory.createFunctionDeclaration(
22
+ [
23
+ ts.factory.createModifier(ts.SyntaxKind.ExportKeyword),
24
+ ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword),
25
+ ],
26
+ undefined,
27
+ ctx.route.accessor.at(-1)!,
28
+ undefined,
29
+ writeParameterDeclarations(ctx),
30
+ ts.factory.createTypeReferenceNode("Promise", [
31
+ ts.factory.createTypeReferenceNode(
32
+ ctx.route.success === null
33
+ ? "void"
34
+ : `${ctx.route.accessor.at(-1)!}.Response`,
35
+ ),
36
+ ]),
37
+ ts.factory.createBlock(writeBody(ctx), true),
38
+ ),
39
+ writeDescription(ctx.config, ctx.route),
40
+ );
41
+
42
+ export const writeParameterDeclarations = (
43
+ ctx: IContext,
44
+ connectionName?: string,
45
+ ): ts.ParameterDeclaration[] => {
46
+ const connection: ts.ParameterDeclaration = IdentifierFactory.parameter(
47
+ connectionName ?? "connection",
48
+ ts.factory.createTypeReferenceNode(
49
+ ctx.importer.external({
50
+ type: "instance",
51
+ library: "@nestia/fetcher",
52
+ name: "IConnection",
53
+ }),
54
+ ctx.route.headers
55
+ ? [
56
+ ts.factory.createTypeReferenceNode(
57
+ `${ctx.route.accessor.at(-1)!}.Headers`,
58
+ ),
59
+ ]
60
+ : undefined,
61
+ ),
62
+ );
63
+ if (ctx.config.keyword === true) {
64
+ const isProps: boolean =
65
+ ctx.route.parameters.length > 0 ||
66
+ !!ctx.route.query ||
67
+ !!ctx.route.body;
68
+ if (isProps === false) return [connection];
69
+ return [
70
+ connection,
71
+ ts.factory.createParameterDeclaration(
72
+ undefined,
73
+ undefined,
74
+ "props",
75
+ undefined,
76
+ ts.factory.createTypeReferenceNode(
77
+ `${ctx.route.accessor.at(-1)!}.Props`,
78
+ ),
79
+ ),
80
+ ];
81
+ }
82
+ return [
83
+ connection,
84
+ ...ctx.route.parameters.map((p) =>
85
+ IdentifierFactory.parameter(
86
+ p.key,
87
+ NestiaMigrateSchemaProgrammer.write({
88
+ components: ctx.components,
89
+ importer: ctx.importer,
90
+ schema: p.schema,
91
+ }),
92
+ ),
93
+ ),
94
+ ...(ctx.route.query
95
+ ? [
96
+ IdentifierFactory.parameter(
97
+ ctx.route.query.key,
98
+ ts.factory.createTypeReferenceNode(
99
+ `${ctx.route.accessor.at(-1)!}.Query`,
100
+ ),
101
+ ),
102
+ ]
103
+ : []),
104
+ ...(ctx.route.body
105
+ ? [
106
+ IdentifierFactory.parameter(
107
+ ctx.route.body.key,
108
+ ts.factory.createTypeReferenceNode(
109
+ `${ctx.route.accessor.at(-1)!}.Body`,
110
+ ),
111
+ (ctx.route.body.type === "application/json" ||
112
+ ctx.route.body.type === "text/plain") &&
113
+ ctx.route.operation().requestBody?.required === false
114
+ ? ts.factory.createToken(ts.SyntaxKind.QuestionToken)
115
+ : undefined,
116
+ ),
117
+ ]
118
+ : []),
119
+ ];
120
+ };
121
+
122
+ const writeDescription = (
123
+ config: INestiaMigrateConfig,
124
+ route: IHttpMigrateRoute,
125
+ ): string => {
126
+ const comment: string = route.comment();
127
+ return [
128
+ config.keyword === true
129
+ ? comment.split("@param ").join("@param props.")
130
+ : comment,
131
+ `@path ${route.emendedPath}`,
132
+ `@accessor api.functional.${route.accessor.join(".")}`,
133
+ `@${config.author?.tag ?? "nestia"} ${config.author?.value ?? "Generated by Nestia - https://github.com/samchon/nestia"}`,
134
+ ].join("\n");
135
+ };
136
+
137
+ const writeBody = (ctx: IContext): ts.Statement[] => {
138
+ const encrypted: boolean = !!ctx.route.success?.["x-nestia-encrypted"];
139
+ const contentType: string = ctx.route.body?.type ?? "application/json";
140
+
141
+ const property = (key: string): ts.Expression =>
142
+ ctx.config.keyword === true
143
+ ? IdentifierFactory.access(ts.factory.createIdentifier("props"), key)
144
+ : ts.factory.createIdentifier(key);
145
+ const fetch = () =>
146
+ ts.factory.createAwaitExpression(
147
+ ts.factory.createCallExpression(
148
+ IdentifierFactory.access(
149
+ ts.factory.createIdentifier(
150
+ ctx.importer.external({
151
+ type: "instance",
152
+ library: `@nestia/fetcher`,
153
+ name: encrypted ? "EncryptedFetcher" : "PlainFetcher",
154
+ }),
155
+ ),
156
+ "fetch",
157
+ ),
158
+ undefined,
159
+ [
160
+ contentType && contentType !== "multipart/form-data"
161
+ ? ts.factory.createObjectLiteralExpression(
162
+ [
163
+ ts.factory.createSpreadAssignment(
164
+ ts.factory.createIdentifier("connection"),
165
+ ),
166
+ ts.factory.createPropertyAssignment(
167
+ "headers",
168
+ ts.factory.createObjectLiteralExpression(
169
+ [
170
+ ts.factory.createSpreadAssignment(
171
+ IdentifierFactory.access(
172
+ ts.factory.createIdentifier("connection"),
173
+ "headers",
174
+ ),
175
+ ),
176
+ ts.factory.createPropertyAssignment(
177
+ ts.factory.createStringLiteral("Content-Type"),
178
+ ts.factory.createStringLiteral(contentType),
179
+ ),
180
+ ],
181
+ true,
182
+ ),
183
+ ),
184
+ ],
185
+ true,
186
+ )
187
+ : ts.factory.createIdentifier("connection"),
188
+ ts.factory.createObjectLiteralExpression(
189
+ [
190
+ ts.factory.createSpreadAssignment(
191
+ IdentifierFactory.access(
192
+ ts.factory.createIdentifier(ctx.route.accessor.at(-1)!),
193
+ "METADATA",
194
+ ),
195
+ ),
196
+ ts.factory.createPropertyAssignment(
197
+ "path",
198
+ ts.factory.createCallExpression(
199
+ IdentifierFactory.access(
200
+ ts.factory.createIdentifier(ctx.route.accessor.at(-1)!),
201
+ "path",
202
+ ),
203
+ undefined,
204
+ getArguments(ctx, false),
205
+ ),
206
+ ),
207
+ ts.factory.createPropertyAssignment(
208
+ "status",
209
+ ts.factory.createNull(),
210
+ ),
211
+ ],
212
+ true,
213
+ ),
214
+ ...(ctx.route.body ? [property(ctx.route.body.key)] : []),
215
+ ],
216
+ ),
217
+ );
218
+
219
+ const value: ts.Expression =
220
+ ctx.config.simulate !== true
221
+ ? fetch()
222
+ : ts.factory.createConditionalExpression(
223
+ ts.factory.createStrictEquality(
224
+ ts.factory.createTrue(),
225
+ ts.factory.createIdentifier("connection.simulate"),
226
+ ),
227
+ undefined,
228
+ ts.factory.createCallExpression(
229
+ ts.factory.createIdentifier(
230
+ `${ctx.route.accessor.at(-1)!}.simulate`,
231
+ ),
232
+ [],
233
+ [
234
+ ts.factory.createIdentifier("connection"),
235
+ ...getArguments(ctx, true),
236
+ ],
237
+ ),
238
+ undefined,
239
+ fetch(),
240
+ );
241
+ const headers: Array<IAssignHeader | ISetHeader> = getHeaders(
242
+ ctx.route.comment(),
243
+ );
244
+ if (headers.length === 0) return [ts.factory.createReturnStatement(value)];
245
+ return [
246
+ StatementFactory.constant({
247
+ name: "output",
248
+ type: ts.factory.createTypeReferenceNode(
249
+ `${ctx.route.accessor.at(-1)!}.Response`,
250
+ ),
251
+ value,
252
+ }),
253
+ ts.factory.createExpressionStatement(
254
+ ts.factory.createBinaryExpression(
255
+ ts.factory.createIdentifier("connection.headers"),
256
+ ts.factory.createToken(ts.SyntaxKind.QuestionQuestionEqualsToken),
257
+ ts.factory.createObjectLiteralExpression([]),
258
+ ),
259
+ ),
260
+ ...headers.map((h) =>
261
+ ts.factory.createExpressionStatement(
262
+ h.type === "assign"
263
+ ? ts.factory.createCallExpression(
264
+ ts.factory.createIdentifier("Object.assign"),
265
+ undefined,
266
+ [
267
+ ts.factory.createIdentifier("connection.headers"),
268
+ ts.factory.createIdentifier(`output.${h.accessor}`),
269
+ ],
270
+ )
271
+ : ts.factory.createBinaryExpression(
272
+ ts.factory.createIdentifier(
273
+ `connection.headers${
274
+ NamingConvention.variable(h.property)
275
+ ? `.${h.property}`
276
+ : `[${JSON.stringify(h.property)}]`
277
+ }`,
278
+ ),
279
+ ts.factory.createToken(ts.SyntaxKind.EqualsToken),
280
+ ts.factory.createIdentifier(`output.${h.accessor}`),
281
+ ),
282
+ ),
283
+ ),
284
+ ts.factory.createReturnStatement(ts.factory.createIdentifier("output")),
285
+ ];
286
+ };
287
+
288
+ const getArguments = (ctx: IContext, body: boolean): ts.Expression[] => {
289
+ if (
290
+ ctx.route.parameters.length === 0 &&
291
+ ctx.route.query === null &&
292
+ (body === false || ctx.route.body === null)
293
+ )
294
+ return [];
295
+ else if (ctx.config.keyword === true)
296
+ return [ts.factory.createIdentifier("props")];
297
+ return [
298
+ ...ctx.route.parameters.map((p) => ts.factory.createIdentifier(p.key)),
299
+ ...(ctx.route.query
300
+ ? [ts.factory.createIdentifier(ctx.route.query.key)]
301
+ : []),
302
+ ...(body && ctx.route.body
303
+ ? [ts.factory.createIdentifier(ctx.route.body.key)]
304
+ : []),
305
+ ];
306
+ };
307
+
308
+ const getHeaders = (
309
+ description: string,
310
+ ): Array<IAssignHeader | ISetHeader> => {
311
+ const directives: Array<IAssignHeader | ISetHeader> = [];
312
+ for (const line of description.split("\n").map((l) => l.trim())) {
313
+ if (line.startsWith("@setHeader ")) {
314
+ const parts: string[] = line
315
+ .substring("@setHeader ".length)
316
+ .trim()
317
+ .split(/\s+/);
318
+ if (parts.length >= 2)
319
+ directives.push({
320
+ type: "set",
321
+ accessor: parts[0]!,
322
+ property: parts[1]!,
323
+ });
324
+ } else if (line.startsWith("@assignHeaders ")) {
325
+ const accessor: string = line
326
+ .substring("@assignHeaders ".length)
327
+ .trim();
328
+ if (accessor.length !== 0)
329
+ directives.push({
330
+ type: "assign",
331
+ accessor,
332
+ });
333
+ }
334
+ }
335
+ return directives;
336
+ };
337
+ }
338
+
339
+ interface IAssignHeader {
340
+ type: "assign";
341
+ accessor: string;
342
+ }
343
+ interface ISetHeader {
344
+ type: "set";
345
+ accessor: string;
346
+ property: string;
347
+ }