@nestia/migrate 0.6.1 → 0.6.3
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/IMigrateConfig.d.ts +3 -0
- package/lib/IMigrateConfig.js +3 -0
- package/lib/IMigrateConfig.js.map +1 -0
- package/lib/MigrateApplication.d.ts +4 -2
- package/lib/MigrateApplication.js +49 -29
- package/lib/MigrateApplication.js.map +1 -1
- package/lib/analyzers/ControllerAnalyzer.js +11 -2
- package/lib/analyzers/ControllerAnalyzer.js.map +1 -1
- package/lib/analyzers/MethodAnalyzer.js +18 -5
- package/lib/analyzers/MethodAnalyzer.js.map +1 -1
- package/lib/analyzers/MigrateAnalyzer.d.ts +2 -1
- package/lib/analyzers/MigrateAnalyzer.js +2 -1
- package/lib/analyzers/MigrateAnalyzer.js.map +1 -1
- package/lib/archivers/FileArchiver.d.ts +3 -3
- package/lib/archivers/FileArchiver.js +16 -7
- package/lib/archivers/FileArchiver.js.map +1 -1
- package/lib/executable/migrate.js +22 -10
- package/lib/executable/migrate.js.map +1 -1
- package/lib/internal/MigrateArguments.d.ts +8 -0
- package/lib/internal/MigrateArguments.js +67 -0
- package/lib/internal/MigrateArguments.js.map +1 -0
- package/lib/programmers/ApiFileProgrammer.d.ts +18 -0
- package/lib/programmers/ApiFileProgrammer.js +28 -0
- package/lib/programmers/ApiFileProgrammer.js.map +1 -0
- package/lib/programmers/ApiFunctionProgrammer.d.ts +15 -0
- package/lib/programmers/ApiFunctionProgrammer.js +96 -0
- package/lib/programmers/ApiFunctionProgrammer.js.map +1 -0
- package/lib/programmers/ApiNamespaceProgrammer.d.ts +15 -0
- package/lib/programmers/ApiNamespaceProgrammer.js +147 -0
- package/lib/programmers/ApiNamespaceProgrammer.js.map +1 -0
- package/lib/programmers/ApiProgrammer.d.ts +5 -0
- package/lib/programmers/ApiProgrammer.js +62 -0
- package/lib/programmers/ApiProgrammer.js.map +1 -0
- package/lib/programmers/ApiSimulatationProgrammer.d.ts +14 -0
- package/lib/programmers/ApiSimulatationProgrammer.js +127 -0
- package/lib/programmers/ApiSimulatationProgrammer.js.map +1 -0
- package/lib/programmers/DtoProgrammer.js +2 -2
- package/lib/programmers/DtoProgrammer.js.map +1 -1
- package/lib/programmers/ImportProgrammer.d.ts +2 -1
- package/lib/programmers/ImportProgrammer.js +19 -4
- package/lib/programmers/ImportProgrammer.js.map +1 -1
- package/lib/programmers/NestControllerProgrammer.js +2 -1
- package/lib/programmers/NestControllerProgrammer.js.map +1 -1
- package/lib/programmers/NestMethodProgrammer.js +33 -18
- package/lib/programmers/NestMethodProgrammer.js.map +1 -1
- package/lib/programmers/NestProgrammer.d.ts +1 -1
- package/lib/programmers/NestProgrammer.js +5 -5
- package/lib/programmers/NestProgrammer.js.map +1 -1
- package/lib/programmers/SchemaProgrammer.d.ts +1 -1
- package/lib/programmers/SchemaProgrammer.js +17 -17
- package/lib/programmers/SchemaProgrammer.js.map +1 -1
- package/lib/structures/IMigrateProgram.d.ts +2 -0
- package/lib/structures/IMigrateRoute.d.ts +13 -4
- package/lib/utils/SetupWizard.js +0 -3
- package/lib/utils/SetupWizard.js.map +1 -1
- package/lib/utils/StringUtil.d.ts +1 -0
- package/lib/utils/StringUtil.js +4 -2
- package/lib/utils/StringUtil.js.map +1 -1
- package/package.json +67 -64
- package/src/IMigrateConfig.ts +3 -0
- package/src/MigrateApplication.ts +42 -33
- package/src/analyzers/ControllerAnalyzer.ts +19 -3
- package/src/analyzers/MethodAnalyzer.ts +18 -5
- package/src/analyzers/MigrateAnalyzer.ts +8 -4
- package/src/archivers/FileArchiver.ts +10 -7
- package/src/executable/migrate.ts +15 -9
- package/src/internal/MigrateArguments.ts +74 -0
- package/src/programmers/ApiFileProgrammer.ts +53 -0
- package/src/programmers/ApiFunctionProgrammer.ts +204 -0
- package/src/programmers/ApiNamespaceProgrammer.ts +418 -0
- package/src/programmers/ApiProgrammer.ts +70 -0
- package/src/programmers/ApiSimulatationProgrammer.ts +328 -0
- package/src/programmers/DtoProgrammer.ts +3 -3
- package/src/programmers/ImportProgrammer.ts +37 -21
- package/src/programmers/NestControllerProgrammer.ts +2 -1
- package/src/programmers/NestMethodProgrammer.ts +39 -22
- package/src/programmers/NestProgrammer.ts +1 -1
- package/src/programmers/SchemaProgrammer.ts +22 -25
- package/src/structures/IMigrateProgram.ts +2 -0
- package/src/structures/IMigrateRoute.ts +13 -5
- package/src/utils/SetupWizard.ts +0 -3
- package/src/utils/StringUtil.ts +11 -2
- package/lib/analyzers/RouteAnalyzer.d.ts +0 -0
- package/lib/analyzers/RouteAnalyzer.js +0 -2
- package/lib/analyzers/RouteAnalyzer.js.map +0 -1
- package/src/analyzers/RouteAnalyzer.ts +0 -0
package/package.json
CHANGED
@@ -1,64 +1,67 @@
|
|
1
|
-
{
|
2
|
-
"name": "@nestia/migrate",
|
3
|
-
"version": "0.6.
|
4
|
-
"description": "Migration program from swagger to NestJS",
|
5
|
-
"main": "lib/index.js",
|
6
|
-
"typings": "lib/index.d.ts",
|
7
|
-
"bin": {
|
8
|
-
"@nestia/migrate": "lib/executable/migrate.js"
|
9
|
-
},
|
10
|
-
"scripts": {
|
11
|
-
"build": "rimraf lib && tsc",
|
12
|
-
"dev": "npm run build -- --watch",
|
13
|
-
"prepare": "ts-patch install && typia patch && ts-node src/executable/bundle.ts",
|
14
|
-
"test": "node lib/test"
|
15
|
-
},
|
16
|
-
"repository": {
|
17
|
-
"type": "git",
|
18
|
-
"url": "https://github.com/samchon/nestia"
|
19
|
-
},
|
20
|
-
"keywords": [
|
21
|
-
"migration",
|
22
|
-
"swagger",
|
23
|
-
"NestJS",
|
24
|
-
"nestia"
|
25
|
-
],
|
26
|
-
"author": "Jeongho Nam",
|
27
|
-
"license": "MIT",
|
28
|
-
"bugs": {
|
29
|
-
"url": "https://github.com/samchon/nestia/issues"
|
30
|
-
},
|
31
|
-
"homepage": "https://github.com/samchon/nestia#readme",
|
32
|
-
"devDependencies": {
|
33
|
-
"@nestia/core": "
|
34
|
-
"@nestia/fetcher": "
|
35
|
-
"@nestjs/common": "^10.3.1",
|
36
|
-
"@nestjs/core": "^10.3.1",
|
37
|
-
"@nestjs/platform-express": "^10.3.1",
|
38
|
-
"@nestjs/platform-fastify": "^10.3.1",
|
39
|
-
"@types/express": "^4.17.21",
|
40
|
-
"@types/
|
41
|
-
"
|
42
|
-
"dotenv
|
43
|
-
"
|
44
|
-
"
|
45
|
-
"
|
46
|
-
"
|
47
|
-
"ts-
|
48
|
-
"
|
49
|
-
"
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
"
|
54
|
-
|
55
|
-
|
56
|
-
"
|
57
|
-
|
58
|
-
|
59
|
-
"
|
60
|
-
"
|
61
|
-
"
|
62
|
-
"
|
63
|
-
|
64
|
-
|
1
|
+
{
|
2
|
+
"name": "@nestia/migrate",
|
3
|
+
"version": "0.6.3",
|
4
|
+
"description": "Migration program from swagger to NestJS",
|
5
|
+
"main": "lib/index.js",
|
6
|
+
"typings": "lib/index.d.ts",
|
7
|
+
"bin": {
|
8
|
+
"@nestia/migrate": "lib/executable/migrate.js"
|
9
|
+
},
|
10
|
+
"scripts": {
|
11
|
+
"build": "rimraf lib && tsc",
|
12
|
+
"dev": "npm run build -- --watch",
|
13
|
+
"prepare": "ts-patch install && typia patch && ts-node src/executable/bundle.ts",
|
14
|
+
"test": "node lib/test"
|
15
|
+
},
|
16
|
+
"repository": {
|
17
|
+
"type": "git",
|
18
|
+
"url": "https://github.com/samchon/nestia"
|
19
|
+
},
|
20
|
+
"keywords": [
|
21
|
+
"migration",
|
22
|
+
"swagger",
|
23
|
+
"NestJS",
|
24
|
+
"nestia"
|
25
|
+
],
|
26
|
+
"author": "Jeongho Nam",
|
27
|
+
"license": "MIT",
|
28
|
+
"bugs": {
|
29
|
+
"url": "https://github.com/samchon/nestia/issues"
|
30
|
+
},
|
31
|
+
"homepage": "https://github.com/samchon/nestia#readme",
|
32
|
+
"devDependencies": {
|
33
|
+
"@nestia/core": "2.5.0-dev.20240201",
|
34
|
+
"@nestia/fetcher": "2.5.0-dev.20240201",
|
35
|
+
"@nestjs/common": "^10.3.1",
|
36
|
+
"@nestjs/core": "^10.3.1",
|
37
|
+
"@nestjs/platform-express": "^10.3.1",
|
38
|
+
"@nestjs/platform-fastify": "^10.3.1",
|
39
|
+
"@types/express": "^4.17.21",
|
40
|
+
"@types/inquirer": "^9.0.7",
|
41
|
+
"@types/node": "^20.3.3",
|
42
|
+
"dotenv": "^16.3.1",
|
43
|
+
"dotenv-expand": "^10.0.0",
|
44
|
+
"rimraf": "^5.0.1",
|
45
|
+
"serialize-error": "^4.1.0",
|
46
|
+
"source-map-support": "^0.5.21",
|
47
|
+
"ts-node": "^10.9.1",
|
48
|
+
"ts-patch": "^3.1.0",
|
49
|
+
"tstl": "^2.5.13",
|
50
|
+
"typescript-transform-paths": "^3.4.6"
|
51
|
+
},
|
52
|
+
"dependencies": {
|
53
|
+
"commander": "10.0.0",
|
54
|
+
"inquirer": "8.2.5",
|
55
|
+
"typescript": "^5.3.3",
|
56
|
+
"typia": "^5.4.1"
|
57
|
+
},
|
58
|
+
"files": [
|
59
|
+
"lib",
|
60
|
+
"src",
|
61
|
+
"!lib/test",
|
62
|
+
"!src/test",
|
63
|
+
"package.json",
|
64
|
+
"README.md",
|
65
|
+
"LICENSE"
|
66
|
+
]
|
67
|
+
}
|
@@ -2,10 +2,12 @@ import cp from "child_process";
|
|
2
2
|
import fs from "fs";
|
3
3
|
import typia from "typia";
|
4
4
|
|
5
|
+
import { IMigrateConfig } from "./IMigrateConfig";
|
5
6
|
import { MigrateAnalyzer } from "./analyzers/MigrateAnalyzer";
|
6
7
|
import { FileArchiver } from "./archivers/FileArchiver";
|
7
8
|
import { TEMPLATE } from "./bundles/TEMPLATE";
|
8
|
-
import {
|
9
|
+
import { ApiProgrammer } from "./programmers/ApiProgrammer";
|
10
|
+
import { NestProgrammer } from "./programmers/NestProgrammer";
|
9
11
|
import { IMigrateFile } from "./structures/IMigrateFile";
|
10
12
|
import { IMigrateProgram } from "./structures/IMigrateProgram";
|
11
13
|
import { ISwagger } from "./structures/ISwagger";
|
@@ -15,7 +17,10 @@ export class MigrateApplication {
|
|
15
17
|
private program: IMigrateProgram | null;
|
16
18
|
private files: IMigrateFile[] | null;
|
17
19
|
|
18
|
-
public constructor(
|
20
|
+
public constructor(
|
21
|
+
public readonly config: IMigrateConfig,
|
22
|
+
swagger: ISwagger,
|
23
|
+
) {
|
19
24
|
this.swagger = typia.assert(swagger);
|
20
25
|
this.program = null;
|
21
26
|
this.files = null;
|
@@ -23,47 +28,51 @@ export class MigrateApplication {
|
|
23
28
|
|
24
29
|
public analyze(): IMigrateProgram {
|
25
30
|
if (this.program === null)
|
26
|
-
this.program = MigrateAnalyzer.analyze(this.swagger);
|
31
|
+
this.program = MigrateAnalyzer.analyze(this.config)(this.swagger);
|
27
32
|
return this.program;
|
28
33
|
}
|
29
34
|
|
30
35
|
public write(): IMigrateFile[] {
|
31
36
|
if (this.files === null) {
|
32
|
-
|
33
|
-
this.files =
|
37
|
+
this.program ??= this.analyze();
|
38
|
+
this.files = [
|
39
|
+
...ApiProgrammer.write(this.program),
|
40
|
+
...NestProgrammer.write(this.program),
|
41
|
+
];
|
34
42
|
}
|
35
43
|
return this.files;
|
36
44
|
}
|
37
45
|
|
38
|
-
public generate
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
46
|
+
public async generate(output: string): Promise<void> {
|
47
|
+
const files: IMigrateFile[] = this.write();
|
48
|
+
const archiver = FileArchiver.archive({
|
49
|
+
mkdir: fs.promises.mkdir,
|
50
|
+
writeFile: (file, content) =>
|
51
|
+
fs.promises.writeFile(file, content, "utf8"),
|
52
|
+
})(output);
|
53
|
+
try {
|
54
|
+
cp.execSync(
|
55
|
+
`git clone https://github.com/samchon/nestia-template "${output}"`,
|
56
|
+
{ stdio: "ignore" },
|
57
|
+
);
|
44
58
|
try {
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
} catch {
|
63
|
-
FileArchiver.archive(archiver)(output)(TEMPLATE);
|
64
|
-
}
|
65
|
-
FileArchiver.archive(archiver)(output)(files);
|
66
|
-
};
|
59
|
+
for (const path of [
|
60
|
+
"/.git",
|
61
|
+
"/src/api",
|
62
|
+
"/src/controllers",
|
63
|
+
"/src/providers",
|
64
|
+
"/test/features",
|
65
|
+
])
|
66
|
+
fs.rmSync(`${output}${path}`, {
|
67
|
+
recursive: true,
|
68
|
+
force: true,
|
69
|
+
});
|
70
|
+
} catch {}
|
71
|
+
} catch (exp) {
|
72
|
+
await archiver(TEMPLATE);
|
73
|
+
}
|
74
|
+
await archiver(files);
|
75
|
+
}
|
67
76
|
}
|
68
77
|
export namespace NestiaMigrateApplication {
|
69
78
|
export interface IArchiver {
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import { Escaper } from "typia/lib/utils/Escaper";
|
2
|
+
|
1
3
|
import { ISwagger } from "../module";
|
2
4
|
import { IMigrateController } from "../structures/IMigrateController";
|
3
5
|
import { IMigrateRoute } from "../structures/IMigrateRoute";
|
@@ -62,7 +64,7 @@ export namespace ControllerAnalyzer {
|
|
62
64
|
routes,
|
63
65
|
};
|
64
66
|
if (controller.name === "Controller") controller.name = "__Controller";
|
65
|
-
|
67
|
+
emend(controller);
|
66
68
|
return controller;
|
67
69
|
});
|
68
70
|
};
|
@@ -73,7 +75,7 @@ export namespace ControllerAnalyzer {
|
|
73
75
|
.slice(0, -1)
|
74
76
|
.reverse();
|
75
77
|
|
76
|
-
const
|
78
|
+
const emend = (controller: IMigrateController): void => {
|
77
79
|
interface IRouteCapsule {
|
78
80
|
variables: string[];
|
79
81
|
route: IMigrateRoute;
|
@@ -93,7 +95,6 @@ export namespace ControllerAnalyzer {
|
|
93
95
|
route,
|
94
96
|
});
|
95
97
|
}
|
96
|
-
|
97
98
|
for (const [method, capsules] of dict) {
|
98
99
|
const emended: string = method === "delete" ? "erase" : method;
|
99
100
|
for (const c of capsules) {
|
@@ -103,5 +104,20 @@ export namespace ControllerAnalyzer {
|
|
103
104
|
: StringUtil.camel(`${emended}By/${c.variables.join("/and/")}`);
|
104
105
|
}
|
105
106
|
}
|
107
|
+
for (const method of controller.routes) {
|
108
|
+
if (Escaper.variable(method.name) === false)
|
109
|
+
method.name = "_" + method.name;
|
110
|
+
for (const spec of [method.headers, method.query, method.body])
|
111
|
+
if (spec)
|
112
|
+
spec.key = StringUtil.escapeDuplicate(
|
113
|
+
method.parameters.map((p) => p.key),
|
114
|
+
)(spec.key);
|
115
|
+
}
|
116
|
+
controller.routes.forEach(
|
117
|
+
(r, i) =>
|
118
|
+
(r.name = StringUtil.escapeDuplicate(
|
119
|
+
controller.routes.filter((_r, j) => i !== j).map((x) => x.name),
|
120
|
+
)(r.name)),
|
121
|
+
);
|
106
122
|
};
|
107
123
|
}
|
@@ -161,14 +161,18 @@ export namespace MethodAnalzyer {
|
|
161
161
|
name: "@lazy",
|
162
162
|
path: props.path,
|
163
163
|
method: props.method,
|
164
|
-
headers
|
164
|
+
headers: headers
|
165
|
+
? {
|
166
|
+
key: "headers",
|
167
|
+
schema: headers,
|
168
|
+
}
|
169
|
+
: null,
|
165
170
|
parameters: (route.parameters ?? [])
|
166
171
|
.filter((p) => p.in === "path")
|
167
172
|
.map((p, i) => ({
|
168
173
|
key: (() => {
|
169
174
|
let key: string = StringUtil.normalize(parameterNames[i]);
|
170
175
|
if (Escaper.variable(key)) return key;
|
171
|
-
|
172
176
|
while (true) {
|
173
177
|
key = "_" + key;
|
174
178
|
if (!parameterNames.some((s) => s === key)) return key;
|
@@ -179,7 +183,12 @@ export namespace MethodAnalzyer {
|
|
179
183
|
description: p.schema.description ?? p.description,
|
180
184
|
},
|
181
185
|
})),
|
182
|
-
query
|
186
|
+
query: query
|
187
|
+
? {
|
188
|
+
key: "query",
|
189
|
+
schema: query,
|
190
|
+
}
|
191
|
+
: null,
|
183
192
|
body,
|
184
193
|
success,
|
185
194
|
exceptions: Object.fromEntries(
|
@@ -198,8 +207,9 @@ export namespace MethodAnalzyer {
|
|
198
207
|
},
|
199
208
|
]),
|
200
209
|
),
|
210
|
+
deprecated: route.deprecated ?? false,
|
201
211
|
description: describe(route),
|
202
|
-
|
212
|
+
tags: route.tags ?? [],
|
203
213
|
};
|
204
214
|
};
|
205
215
|
|
@@ -274,6 +284,7 @@ export namespace MethodAnalzyer {
|
|
274
284
|
const { schema } = json[1];
|
275
285
|
return {
|
276
286
|
type: "application/json",
|
287
|
+
key: "body",
|
277
288
|
schema: isNotObjectLiteral(schema) ? schema : emplacer(schema),
|
278
289
|
"x-nestia-encrypted": meta["x-nestia-encrypted"],
|
279
290
|
};
|
@@ -286,12 +297,14 @@ export namespace MethodAnalzyer {
|
|
286
297
|
const { schema } = query[1];
|
287
298
|
return {
|
288
299
|
type: "application/x-www-form-urlencoded",
|
300
|
+
key: "body",
|
289
301
|
schema: isNotObjectLiteral(schema) ? schema : emplacer(schema),
|
290
302
|
};
|
291
303
|
}
|
292
304
|
|
293
305
|
const text = entries.find((e) => e[0].includes("text/plain"));
|
294
|
-
if (text)
|
306
|
+
if (text)
|
307
|
+
return { type: "text/plain", key: "body", schema: { type: "string" } };
|
295
308
|
return false;
|
296
309
|
};
|
297
310
|
|
@@ -1,9 +1,13 @@
|
|
1
|
+
import { IMigrateConfig } from "../IMigrateConfig";
|
1
2
|
import { IMigrateProgram, ISwagger } from "../module";
|
2
3
|
import { ControllerAnalyzer } from "./ControllerAnalyzer";
|
3
4
|
|
4
5
|
export namespace MigrateAnalyzer {
|
5
|
-
export const analyze =
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
export const analyze =
|
7
|
+
(config: IMigrateConfig) =>
|
8
|
+
(swagger: ISwagger): IMigrateProgram => ({
|
9
|
+
config,
|
10
|
+
swagger,
|
11
|
+
controllers: ControllerAnalyzer.analyze(swagger),
|
12
|
+
});
|
9
13
|
}
|
@@ -2,18 +2,21 @@ import { IMigrateFile } from "../structures/IMigrateFile";
|
|
2
2
|
|
3
3
|
export namespace FileArchiver {
|
4
4
|
export interface IOperator {
|
5
|
-
mkdir(path: string): void
|
6
|
-
writeFile(path: string, content: string): void
|
5
|
+
mkdir(path: string): Promise<void>;
|
6
|
+
writeFile(path: string, content: string): Promise<void>;
|
7
7
|
}
|
8
8
|
|
9
9
|
export const archive =
|
10
10
|
(operator: IOperator) =>
|
11
11
|
(output: string) =>
|
12
|
-
(files: IMigrateFile[]): void => {
|
12
|
+
async (files: IMigrateFile[]): Promise<void> => {
|
13
13
|
const visited: Set<string> = new Set();
|
14
14
|
for (const f of files) {
|
15
|
-
mkdir(operator.mkdir)(output)(visited)(f.location);
|
16
|
-
operator.writeFile(
|
15
|
+
await mkdir(operator.mkdir)(output)(visited)(f.location);
|
16
|
+
await operator.writeFile(
|
17
|
+
[output, f.location, f.file].join("/"),
|
18
|
+
f.content,
|
19
|
+
);
|
17
20
|
}
|
18
21
|
};
|
19
22
|
|
@@ -21,14 +24,14 @@ export namespace FileArchiver {
|
|
21
24
|
(creator: (path: string) => void) =>
|
22
25
|
(output: string) =>
|
23
26
|
(visited: Set<string>) =>
|
24
|
-
(path: string): void => {
|
27
|
+
async (path: string): Promise<void> => {
|
25
28
|
const sequence: string[] = path
|
26
29
|
.split("/")
|
27
30
|
.map((_str, i, entire) => entire.slice(0, i + 1).join("/"));
|
28
31
|
for (const s of sequence)
|
29
32
|
if (visited.has(s) === false)
|
30
33
|
try {
|
31
|
-
creator([output, s].join("/"));
|
34
|
+
await creator([output, s].join("/"));
|
32
35
|
visited.add(s);
|
33
36
|
} catch {}
|
34
37
|
};
|
@@ -8,9 +8,10 @@ import { SetupWizard } from "../utils/SetupWizard";
|
|
8
8
|
|
9
9
|
const USAGE = `Wrong command has been detected. Use like below:
|
10
10
|
|
11
|
-
npx @nestia/migrate
|
11
|
+
npx @nestia/migrate <nest|sdk> --input <swagger.json> --output <directory>
|
12
12
|
|
13
|
-
ex) npx @nestia/migrate swagger.json my-
|
13
|
+
ex) npx @nestia/migrate nest --input swagger.json --output my-nest-project
|
14
|
+
ex) npx @nestia/migrate sdk --input swagger.json --output my-sdk-library
|
14
15
|
`;
|
15
16
|
|
16
17
|
function halt(desc: string): never {
|
@@ -18,7 +19,7 @@ function halt(desc: string): never {
|
|
18
19
|
process.exit(-1);
|
19
20
|
}
|
20
21
|
|
21
|
-
const main = (argv: string[]) => {
|
22
|
+
const main = async (argv: string[]): Promise<void> => {
|
22
23
|
const resolve = (str: string | undefined) =>
|
23
24
|
str ? path.resolve(str).split("\\").join("/") : undefined;
|
24
25
|
const input: string | undefined = resolve(argv[0]);
|
@@ -47,13 +48,18 @@ const main = (argv: string[]) => {
|
|
47
48
|
})();
|
48
49
|
|
49
50
|
// DO GENERATE
|
50
|
-
const app = new MigrateApplication(
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
const app: MigrateApplication = new MigrateApplication(
|
52
|
+
{
|
53
|
+
simulate: false,
|
54
|
+
},
|
55
|
+
swagger,
|
56
|
+
);
|
57
|
+
await app.generate(output);
|
55
58
|
|
56
59
|
// RUN SCRIPTS
|
57
60
|
SetupWizard.setup(output);
|
58
61
|
};
|
59
|
-
main(process.argv.slice(2))
|
62
|
+
main(process.argv.slice(2)).catch((exp) => {
|
63
|
+
console.error(exp);
|
64
|
+
process.exit(-1);
|
65
|
+
});
|
@@ -0,0 +1,74 @@
|
|
1
|
+
import commander from "commander";
|
2
|
+
import inquirer from "inquirer";
|
3
|
+
|
4
|
+
export namespace MigrateArguments {
|
5
|
+
export interface IOutput {
|
6
|
+
mode: "nest" | "sdk";
|
7
|
+
input: string;
|
8
|
+
output: string;
|
9
|
+
}
|
10
|
+
|
11
|
+
export const parse = async (): Promise<IOutput> => {
|
12
|
+
// PREPARE ASSETS
|
13
|
+
commander.program.option("--node [nest/sdk]", "migration mode");
|
14
|
+
commander.program.option(
|
15
|
+
"--input [swagger.json]",
|
16
|
+
"location of target swagger.json file",
|
17
|
+
);
|
18
|
+
commander.program.option("--output [directory]", "output directory path");
|
19
|
+
|
20
|
+
// INTERNAL PROCEDURES
|
21
|
+
const questioned = { value: false };
|
22
|
+
const action = (
|
23
|
+
closure: (options: Partial<IOutput>) => Promise<IOutput>,
|
24
|
+
) => {
|
25
|
+
return new Promise<IOutput>((resolve, reject) => {
|
26
|
+
commander.program.action(async (options) => {
|
27
|
+
try {
|
28
|
+
resolve(await closure(options));
|
29
|
+
} catch (exp) {
|
30
|
+
reject(exp);
|
31
|
+
}
|
32
|
+
});
|
33
|
+
commander.program.parseAsync().catch(reject);
|
34
|
+
});
|
35
|
+
};
|
36
|
+
const select =
|
37
|
+
(name: string) =>
|
38
|
+
(message: string) =>
|
39
|
+
async <Choice extends string>(
|
40
|
+
choices: Choice[],
|
41
|
+
filter?: (value: string) => Choice,
|
42
|
+
): Promise<Choice> => {
|
43
|
+
questioned.value = true;
|
44
|
+
return (
|
45
|
+
await inquirer.createPromptModule()({
|
46
|
+
type: "list",
|
47
|
+
name: name,
|
48
|
+
message: message,
|
49
|
+
choices: choices,
|
50
|
+
filter,
|
51
|
+
})
|
52
|
+
)[name];
|
53
|
+
};
|
54
|
+
const input = (name: string) => async (message: string) =>
|
55
|
+
(
|
56
|
+
await inquirer.createPromptModule()({
|
57
|
+
type: "input",
|
58
|
+
name,
|
59
|
+
message,
|
60
|
+
})
|
61
|
+
)[name];
|
62
|
+
|
63
|
+
// DO CONSTRUCT
|
64
|
+
return action(async (partial) => {
|
65
|
+
partial.mode ??= await select("mode")("Migration mode")(
|
66
|
+
["NestJS" as "nest", "SDK" as "sdk"],
|
67
|
+
(value) => (value === "NestJS" ? "nest" : "sdk"),
|
68
|
+
);
|
69
|
+
partial.input ??= await input("input")("Swagger file location");
|
70
|
+
partial.output ??= await input("output")("Output directory path");
|
71
|
+
return partial as IOutput;
|
72
|
+
});
|
73
|
+
};
|
74
|
+
}
|
@@ -0,0 +1,53 @@
|
|
1
|
+
import ts from "typescript";
|
2
|
+
|
3
|
+
import { IMigrateConfig } from "../IMigrateConfig";
|
4
|
+
import { IMigrateController } from "../structures/IMigrateController";
|
5
|
+
import { IMigrateRoute } from "../structures/IMigrateRoute";
|
6
|
+
import { ISwaggerComponents } from "../structures/ISwaggerComponents";
|
7
|
+
import { ApiFunctionProgrammer } from "./ApiFunctionProgrammer";
|
8
|
+
import { ApiNamespaceProgrammer } from "./ApiNamespaceProgrammer";
|
9
|
+
import { ImportProgrammer } from "./ImportProgrammer";
|
10
|
+
|
11
|
+
export namespace ApiFileProgrammer {
|
12
|
+
export interface IProps {
|
13
|
+
namespace: string[];
|
14
|
+
entries: IEntry[];
|
15
|
+
children: Set<string>;
|
16
|
+
}
|
17
|
+
export interface IEntry {
|
18
|
+
controller: IMigrateController;
|
19
|
+
route: IMigrateRoute;
|
20
|
+
alias: string;
|
21
|
+
}
|
22
|
+
|
23
|
+
export const write =
|
24
|
+
(config: IMigrateConfig) =>
|
25
|
+
(components: ISwaggerComponents) =>
|
26
|
+
(props: IProps): ts.Statement[] => {
|
27
|
+
const importer: ImportProgrammer = new ImportProgrammer();
|
28
|
+
const statements: ts.Statement[] = props.entries
|
29
|
+
.map((p) => [
|
30
|
+
ApiFunctionProgrammer.write(config)(components)(importer)(p),
|
31
|
+
ApiNamespaceProgrammer.write(config)(components)(importer)(p),
|
32
|
+
])
|
33
|
+
.flat();
|
34
|
+
return [
|
35
|
+
...importer.toStatements(
|
36
|
+
(ref) =>
|
37
|
+
`../${"../".repeat(props.namespace.length)}structures/${ref}`,
|
38
|
+
),
|
39
|
+
...[...props.children].map((child) =>
|
40
|
+
ts.factory.createExportDeclaration(
|
41
|
+
undefined,
|
42
|
+
false,
|
43
|
+
ts.factory.createNamespaceExport(
|
44
|
+
ts.factory.createIdentifier(child),
|
45
|
+
),
|
46
|
+
ts.factory.createStringLiteral(`./${child}`),
|
47
|
+
undefined,
|
48
|
+
),
|
49
|
+
),
|
50
|
+
...statements,
|
51
|
+
];
|
52
|
+
};
|
53
|
+
}
|