@nestia/migrate 0.1.11 → 0.2.1-dev.20230802
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.
- package/lib/NestiaMigrateApplication.js +76 -11
- package/lib/NestiaMigrateApplication.js.map +1 -1
- package/lib/archivers/FileArchiver.js +0 -1
- package/lib/archivers/FileArchiver.js.map +1 -1
- package/lib/bundles/TEMPLATE.js +10 -5
- package/lib/bundles/TEMPLATE.js.map +1 -1
- package/lib/programmers/ControllerProgrammer.d.ts +2 -1
- package/lib/programmers/ControllerProgrammer.js +12 -17
- package/lib/programmers/ControllerProgrammer.js.map +1 -1
- package/lib/programmers/DtoProgrammer.d.ts +2 -1
- package/lib/programmers/DtoProgrammer.js +5 -5
- package/lib/programmers/DtoProgrammer.js.map +1 -1
- package/lib/programmers/ImportProgrammer.d.ts +11 -0
- package/lib/programmers/ImportProgrammer.js +20 -0
- package/lib/programmers/ImportProgrammer.js.map +1 -0
- package/lib/programmers/MigrateProgrammer.d.ts +2 -1
- package/lib/programmers/MigrateProgrammer.js +3 -3
- package/lib/programmers/MigrateProgrammer.js.map +1 -1
- package/lib/programmers/RouteProgrammer.d.ts +2 -1
- package/lib/programmers/RouteProgrammer.js +93 -37
- package/lib/programmers/RouteProgrammer.js.map +1 -1
- package/lib/programmers/SchemaProgrammer.d.ts +2 -1
- package/lib/programmers/SchemaProgrammer.js +64 -42
- package/lib/programmers/SchemaProgrammer.js.map +1 -1
- package/lib/structures/IMigrateRoute.d.ts +3 -0
- package/lib/structures/ISwaggerRoute.d.ts +3 -1
- package/package.json +4 -4
- package/src/NestiaMigrateApplication.ts +28 -3
- package/src/archivers/FileArchiver.ts +0 -1
- package/src/bundles/TEMPLATE.ts +10 -5
- package/src/programmers/ControllerProgrammer.ts +50 -54
- package/src/programmers/DtoProgrammer.ts +29 -25
- package/src/programmers/ImportProgrammer.ts +29 -0
- package/src/programmers/MigrateProgrammer.ts +17 -14
- package/src/programmers/RouteProgrammer.ts +158 -52
- package/src/programmers/SchemaProgrammer.ts +82 -40
- package/src/structures/IMigrateRoute.ts +4 -0
- package/src/structures/ISwaggerRoute.ts +4 -1
@@ -1,6 +1,7 @@
|
|
1
1
|
import { IMigrateDto } from "../structures/IMigrateDto";
|
2
2
|
import { ISwaggerSchema } from "../structures/ISwaggeSchema";
|
3
3
|
import { ISwagger } from "../structures/ISwagger";
|
4
|
+
import { ISwaggerComponents } from "../structures/ISwaggerComponents";
|
4
5
|
import { MapUtil } from "../utils/MapUtil";
|
5
6
|
import { SchemaProgrammer } from "./SchemaProgrammer";
|
6
7
|
|
@@ -25,30 +26,33 @@ export namespace DtoProgrammer {
|
|
25
26
|
return modulo;
|
26
27
|
};
|
27
28
|
|
28
|
-
export const write =
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
29
|
+
export const write =
|
30
|
+
(components: ISwaggerComponents) =>
|
31
|
+
(dto: IMigrateDto): string => {
|
32
|
+
const references: ISwaggerSchema.IReference[] = [];
|
33
|
+
const body: string = iterate(components)(references)(dto);
|
34
|
+
const imports: string[] = [
|
35
|
+
...new Set(
|
36
|
+
references
|
37
|
+
.map(
|
38
|
+
(s) =>
|
39
|
+
s.$ref
|
40
|
+
.replace(`#/components/schemas/`, ``)
|
41
|
+
.split(".")[0],
|
42
|
+
)
|
43
|
+
.filter((str) => str !== dto.name),
|
44
|
+
),
|
45
|
+
];
|
46
|
+
const content: string[] = [
|
47
|
+
...imports.map((i) => `import { ${i} } from "./${i}";`),
|
48
|
+
...(imports.length ? [""] : []),
|
49
|
+
body,
|
50
|
+
];
|
51
|
+
return content.join("\n");
|
52
|
+
};
|
50
53
|
|
51
54
|
const iterate =
|
55
|
+
(components: ISwaggerComponents) =>
|
52
56
|
(references: ISwaggerSchema.IReference[]) =>
|
53
57
|
(dto: IMigrateDto): string => {
|
54
58
|
const content: string[] = [];
|
@@ -63,15 +67,15 @@ export namespace DtoProgrammer {
|
|
63
67
|
]
|
64
68
|
: []),
|
65
69
|
`export type ${dto.name} = ${SchemaProgrammer.write(
|
66
|
-
|
67
|
-
)(dto.schema)}`,
|
70
|
+
components,
|
71
|
+
)(references)(dto.schema)}`,
|
68
72
|
);
|
69
73
|
}
|
70
74
|
if (dto.children.length) {
|
71
75
|
content.push(
|
72
76
|
`export namespace ${dto.name} {`,
|
73
77
|
...dto.children.map((c) =>
|
74
|
-
iterate(references)(c)
|
78
|
+
iterate(components)(references)(c)
|
75
79
|
.split("\n")
|
76
80
|
.map((l) => ` ${l}`)
|
77
81
|
.join("\n"),
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { MapUtil } from "../utils/MapUtil";
|
2
|
+
|
3
|
+
export class ImportProgrammer {
|
4
|
+
private dict: Map<string, Set<string>> = new Map();
|
5
|
+
|
6
|
+
public add(props: ImportProgrammer.IProps): string {
|
7
|
+
MapUtil.take(this.dict)(props.library)(() => new Set()).add(
|
8
|
+
props.instance,
|
9
|
+
);
|
10
|
+
return props.instance;
|
11
|
+
}
|
12
|
+
|
13
|
+
public toScript(): string {
|
14
|
+
return [...this.dict.entries()]
|
15
|
+
.map(
|
16
|
+
([library, properties]) =>
|
17
|
+
`import { ${[...properties].join(
|
18
|
+
", ",
|
19
|
+
)} } from "${library}";`,
|
20
|
+
)
|
21
|
+
.join("\n");
|
22
|
+
}
|
23
|
+
}
|
24
|
+
export namespace ImportProgrammer {
|
25
|
+
export interface IProps {
|
26
|
+
library: string;
|
27
|
+
instance: string;
|
28
|
+
}
|
29
|
+
}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { IMigrateFile } from "../structures/IMigrateFile";
|
2
2
|
import { IMigrateProgram } from "../structures/IMigrateProgram";
|
3
3
|
import { ISwagger } from "../structures/ISwagger";
|
4
|
+
import { ISwaggerComponents } from "../structures/ISwaggerComponents";
|
4
5
|
import { ControllerProgrammer } from "./ControllerProgrammer";
|
5
6
|
import { DtoProgrammer } from "./DtoProgrammer";
|
6
7
|
|
@@ -14,18 +15,20 @@ export namespace MigrateProgrammer {
|
|
14
15
|
};
|
15
16
|
};
|
16
17
|
|
17
|
-
export const write =
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
18
|
+
export const write =
|
19
|
+
(components: ISwaggerComponents) =>
|
20
|
+
(program: IMigrateProgram): IMigrateFile[] => {
|
21
|
+
return [
|
22
|
+
...program.controllers.map((c) => ({
|
23
|
+
location: c.location,
|
24
|
+
file: `${c.name}.ts`,
|
25
|
+
content: ControllerProgrammer.write(components)(c),
|
26
|
+
})),
|
27
|
+
...program.structures.map((s) => ({
|
28
|
+
location: s.location,
|
29
|
+
file: `${s.name}.ts`,
|
30
|
+
content: DtoProgrammer.write(components)(s),
|
31
|
+
})),
|
32
|
+
];
|
33
|
+
};
|
31
34
|
}
|
@@ -3,6 +3,7 @@ import { Escaper } from "typia/lib/utils/Escaper";
|
|
3
3
|
import { IMigrateRoute } from "../structures/IMigrateRoute";
|
4
4
|
import { ISwaggerSchema } from "../structures/ISwaggeSchema";
|
5
5
|
import { ISwagger } from "../structures/ISwagger";
|
6
|
+
import { ISwaggerComponents } from "../structures/ISwaggerComponents";
|
6
7
|
import { ISwaggerRoute } from "../structures/ISwaggerRoute";
|
7
8
|
import { JsonTypeChecker } from "../utils/JsonTypeChecker";
|
8
9
|
import { StringUtil } from "../utils/StringUtil";
|
@@ -14,11 +15,11 @@ export namespace RouteProgrammer {
|
|
14
15
|
(props: { path: string; method: string }) =>
|
15
16
|
(route: ISwaggerRoute): IMigrateRoute | null => {
|
16
17
|
const body = emplaceBodySchema(emplaceReference(swagger)("body"))(
|
17
|
-
route.requestBody
|
18
|
+
route.requestBody,
|
18
19
|
);
|
19
20
|
const response = emplaceBodySchema(
|
20
21
|
emplaceReference(swagger)("response"),
|
21
|
-
)(
|
22
|
+
)(route.responses?.["201"] ?? route.responses?.["200"]);
|
22
23
|
if (body === false || response === false) {
|
23
24
|
console.log(
|
24
25
|
`Failed to migrate ${props.method.toUpperCase()} ${
|
@@ -26,6 +27,15 @@ export namespace RouteProgrammer {
|
|
26
27
|
}: @nestia/migrate supports only application/json or text/plain format yet.`,
|
27
28
|
);
|
28
29
|
return null;
|
30
|
+
} else if (
|
31
|
+
SUPPORTED_METHODS.has(props.method.toUpperCase()) === false
|
32
|
+
) {
|
33
|
+
console.log(
|
34
|
+
`Failed to migrate ${props.method.toUpperCase()} ${
|
35
|
+
props.path
|
36
|
+
}: @nestia/migrate does not support ${props.method.toUpperCase()} method.`,
|
37
|
+
);
|
38
|
+
return null;
|
29
39
|
}
|
30
40
|
|
31
41
|
const [headers, query] = ["header", "query"].map((type) => {
|
@@ -193,32 +203,47 @@ export namespace RouteProgrammer {
|
|
193
203
|
body,
|
194
204
|
response,
|
195
205
|
description: describe(route),
|
206
|
+
"x-nestia-jsDocTags": route["x-nestia-jsDocTags"],
|
196
207
|
};
|
197
208
|
};
|
198
209
|
|
199
210
|
const describe = (route: ISwaggerRoute): string | undefined => {
|
200
|
-
const
|
211
|
+
const commentTags: string[] = [];
|
201
212
|
const add = (text: string) => {
|
202
|
-
if (
|
203
|
-
|
213
|
+
if (commentTags.every((line) => line !== text))
|
214
|
+
commentTags.push(text);
|
204
215
|
};
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
216
|
+
|
217
|
+
let description: string | undefined = route.description;
|
218
|
+
if (route.summary) {
|
219
|
+
const emended: string = route.summary.endsWith(".")
|
220
|
+
? route.summary
|
221
|
+
: route.summary + ".";
|
222
|
+
if (
|
223
|
+
description !== undefined &&
|
224
|
+
!description?.startsWith(route.summary) &&
|
225
|
+
!route["x-nestia-jsDocTags"]?.some((t) => t.name === "summary")
|
226
|
+
)
|
227
|
+
description = `${emended}\n${description}`;
|
215
228
|
}
|
216
229
|
if (route.tags) route.tags.forEach((name) => add(`@tag ${name}`));
|
217
230
|
if (route.deprecated) add("@deprecated");
|
218
231
|
for (const security of route.security ?? [])
|
219
232
|
for (const [name, scopes] of Object.entries(security))
|
220
233
|
add(`@security ${[name, ...scopes].join("")}`);
|
221
|
-
|
234
|
+
for (const jsDocTag of route["x-nestia-jsDocTags"] ?? [])
|
235
|
+
if (jsDocTag.text?.length)
|
236
|
+
add(
|
237
|
+
`@${jsDocTag.name} ${jsDocTag.text
|
238
|
+
.map((text) => text.text)
|
239
|
+
.join("")}`,
|
240
|
+
);
|
241
|
+
else add(`@${jsDocTag.name}`);
|
242
|
+
return description?.length
|
243
|
+
? commentTags.length
|
244
|
+
? `${description}\n\n${commentTags.join("\n")}`
|
245
|
+
: description
|
246
|
+
: commentTags.join("\n");
|
222
247
|
};
|
223
248
|
|
224
249
|
const isNotObjectLiteral = (schema: ISwaggerSchema): boolean =>
|
@@ -235,14 +260,21 @@ export namespace RouteProgrammer {
|
|
235
260
|
|
236
261
|
const emplaceBodySchema =
|
237
262
|
(emplacer: (schema: ISwaggerSchema) => ISwaggerSchema.IReference) =>
|
238
|
-
(
|
239
|
-
|
240
|
-
|
241
|
-
|
263
|
+
(meta?: {
|
264
|
+
description?: string;
|
265
|
+
content?: ISwaggerRoute.IContent;
|
266
|
+
"x-nestia-encrypted"?: boolean;
|
267
|
+
}): false | null | IMigrateRoute.IBody => {
|
268
|
+
if (!meta?.content) return null;
|
242
269
|
|
243
270
|
const entries: [string, { schema: ISwaggerSchema }][] =
|
244
|
-
Object.entries(content);
|
245
|
-
const json = entries.find((e) =>
|
271
|
+
Object.entries(meta.content);
|
272
|
+
const json = entries.find((e) =>
|
273
|
+
meta["x-nestia-encrypted"] === true
|
274
|
+
? e[0].includes("text/plain") ||
|
275
|
+
e[0].includes("application/json")
|
276
|
+
: e[0].includes("application/json"),
|
277
|
+
);
|
246
278
|
|
247
279
|
if (json) {
|
248
280
|
const { schema } = json[1];
|
@@ -251,6 +283,7 @@ export namespace RouteProgrammer {
|
|
251
283
|
schema: isNotObjectLiteral(schema)
|
252
284
|
? schema
|
253
285
|
: emplacer(schema),
|
286
|
+
"x-nestia-encrypted": meta["x-nestia-encrypted"],
|
254
287
|
};
|
255
288
|
}
|
256
289
|
|
@@ -269,15 +302,47 @@ export namespace RouteProgrammer {
|
|
269
302
|
};
|
270
303
|
|
271
304
|
export const write =
|
305
|
+
(importer: (module: string) => (instance: string) => string) =>
|
306
|
+
(components: ISwaggerComponents) =>
|
272
307
|
(references: ISwaggerSchema.IReference[]) =>
|
273
308
|
(route: IMigrateRoute): string => {
|
274
309
|
const output: string = route.response
|
275
|
-
? SchemaProgrammer.write(references)(
|
310
|
+
? SchemaProgrammer.write(components)(references)(
|
311
|
+
route.response.schema,
|
312
|
+
)
|
276
313
|
: "void";
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
314
|
+
|
315
|
+
const methoder = (composer: (name: string) => string) =>
|
316
|
+
`${composer(
|
317
|
+
StringUtil.capitalize(route.method),
|
318
|
+
)}(${JSON.stringify(route.path)})`;
|
319
|
+
const decorator: string[] =
|
320
|
+
route.response?.["x-nestia-encrypted"] === true
|
321
|
+
? [
|
322
|
+
`@${importer("@nestia/core")(
|
323
|
+
"EncryptedRoute",
|
324
|
+
)}.${methoder((str) => str)}`,
|
325
|
+
]
|
326
|
+
: route.response?.type === "text/plain"
|
327
|
+
? [
|
328
|
+
`@${importer("@nestjs/common")(
|
329
|
+
"Header",
|
330
|
+
)}("Content-Type", "text/plain")`,
|
331
|
+
`@${methoder((str) =>
|
332
|
+
importer("@nestjs/common")(str),
|
333
|
+
)}`,
|
334
|
+
]
|
335
|
+
: route.method === "head"
|
336
|
+
? [
|
337
|
+
`@${importer("@nestjs/common")("Head")}${methoder(
|
338
|
+
() => "",
|
339
|
+
)}`,
|
340
|
+
]
|
341
|
+
: [
|
342
|
+
`@${importer("@nestia/core")(
|
343
|
+
"TypedRoute",
|
344
|
+
)}.${methoder((str) => str)}`,
|
345
|
+
];
|
281
346
|
const content: string[] = [
|
282
347
|
...(route.description
|
283
348
|
? [
|
@@ -288,54 +353,95 @@ export namespace RouteProgrammer {
|
|
288
353
|
" */",
|
289
354
|
]
|
290
355
|
: []),
|
291
|
-
|
292
|
-
route.path.length ? `(${JSON.stringify(route.path)})` : "()"
|
293
|
-
}`,
|
356
|
+
...decorator,
|
294
357
|
`public async ${route.name}(`,
|
295
|
-
...route.parameters.map(
|
358
|
+
...route.parameters.map(
|
359
|
+
(param) =>
|
360
|
+
` ${writeParameter(components)(importer)(param)},`,
|
361
|
+
),
|
362
|
+
...(route.headers
|
363
|
+
? [
|
364
|
+
` @${importer("@nestia/core")(
|
365
|
+
"TypedHeaders",
|
366
|
+
)}() headers: ${SchemaProgrammer.write(components)(
|
367
|
+
references,
|
368
|
+
)(route.headers)},`,
|
369
|
+
]
|
370
|
+
: []),
|
296
371
|
...(route.query
|
297
372
|
? [
|
298
|
-
` @core
|
373
|
+
` @${importer("@nestia/core")(
|
374
|
+
"TypedQuery",
|
375
|
+
)}() query: ${SchemaProgrammer.write(components)(
|
299
376
|
references,
|
300
|
-
)(route.query)}
|
377
|
+
)(route.query)},`,
|
301
378
|
]
|
302
379
|
: []),
|
303
380
|
...(route.body
|
304
|
-
? route.body
|
381
|
+
? route.body["x-nestia-encrypted"] === true
|
305
382
|
? [
|
306
|
-
` @core
|
383
|
+
` @${importer("@nestia/core")(
|
384
|
+
"EncryptedBody",
|
385
|
+
)}() body: ${SchemaProgrammer.write(components)(
|
307
386
|
references,
|
308
387
|
)(route.body.schema)},`,
|
309
388
|
]
|
310
|
-
:
|
389
|
+
: route.body.type === "application/json"
|
390
|
+
? [
|
391
|
+
` @${importer("@nestia/core")(
|
392
|
+
"TypedBody",
|
393
|
+
)}() body: ${SchemaProgrammer.write(components)(
|
394
|
+
references,
|
395
|
+
)(route.body.schema)},`,
|
396
|
+
]
|
397
|
+
: [
|
398
|
+
` @${importer("@nestia/core")(
|
399
|
+
"PlainBody",
|
400
|
+
)}() body: string,`,
|
401
|
+
]
|
311
402
|
: []),
|
312
403
|
`): Promise<${output}> {`,
|
313
404
|
...route.parameters.map(
|
314
405
|
(p) => ` ${StringUtil.normalize(p.key)};`,
|
315
406
|
),
|
316
|
-
|
407
|
+
...(route.headers ? [" headers;"] : []),
|
317
408
|
...(route.query ? [" query;"] : []),
|
318
409
|
...(route.body ? [" body;"] : []),
|
319
410
|
...(output !== "void"
|
320
|
-
? [
|
411
|
+
? [
|
412
|
+
` return ${importer("typia")(
|
413
|
+
"random",
|
414
|
+
)}<${output}>();`,
|
415
|
+
]
|
321
416
|
: []),
|
322
417
|
`}`,
|
323
418
|
];
|
324
419
|
return content.join("\n");
|
325
420
|
};
|
326
421
|
|
327
|
-
const writeParameter =
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
422
|
+
const writeParameter =
|
423
|
+
(components: ISwaggerComponents) =>
|
424
|
+
(importer: (library: string) => (instance: string) => string) =>
|
425
|
+
({ key, schema }: IMigrateRoute.IParameter): string => {
|
426
|
+
const variable = StringUtil.normalize(key);
|
427
|
+
const format =
|
428
|
+
JsonTypeChecker.isString(schema) &&
|
429
|
+
(schema.format === "uuid" || schema.format === "date")
|
430
|
+
? schema.format
|
431
|
+
: null;
|
432
|
+
return `@${importer("@nestia/core")("TypedParam")}(${JSON.stringify(
|
433
|
+
key,
|
434
|
+
)}${
|
435
|
+
format ? `, ${JSON.stringify(format)}` : ""
|
436
|
+
}) ${variable}: ${SchemaProgrammer.write(components)([])(schema)}`;
|
437
|
+
};
|
341
438
|
}
|
439
|
+
|
440
|
+
const SUPPORTED_METHODS: Set<string> = new Set([
|
441
|
+
"GET",
|
442
|
+
"POST",
|
443
|
+
"PUT",
|
444
|
+
"PATCH",
|
445
|
+
"DELETE",
|
446
|
+
"HEAD",
|
447
|
+
]);
|