@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.
Files changed (86) hide show
  1. package/lib/IMigrateConfig.d.ts +3 -0
  2. package/lib/IMigrateConfig.js +3 -0
  3. package/lib/IMigrateConfig.js.map +1 -0
  4. package/lib/MigrateApplication.d.ts +4 -2
  5. package/lib/MigrateApplication.js +49 -29
  6. package/lib/MigrateApplication.js.map +1 -1
  7. package/lib/analyzers/ControllerAnalyzer.js +11 -2
  8. package/lib/analyzers/ControllerAnalyzer.js.map +1 -1
  9. package/lib/analyzers/MethodAnalyzer.js +18 -5
  10. package/lib/analyzers/MethodAnalyzer.js.map +1 -1
  11. package/lib/analyzers/MigrateAnalyzer.d.ts +2 -1
  12. package/lib/analyzers/MigrateAnalyzer.js +2 -1
  13. package/lib/analyzers/MigrateAnalyzer.js.map +1 -1
  14. package/lib/archivers/FileArchiver.d.ts +3 -3
  15. package/lib/archivers/FileArchiver.js +16 -7
  16. package/lib/archivers/FileArchiver.js.map +1 -1
  17. package/lib/executable/migrate.js +22 -10
  18. package/lib/executable/migrate.js.map +1 -1
  19. package/lib/internal/MigrateArguments.d.ts +8 -0
  20. package/lib/internal/MigrateArguments.js +67 -0
  21. package/lib/internal/MigrateArguments.js.map +1 -0
  22. package/lib/programmers/ApiFileProgrammer.d.ts +18 -0
  23. package/lib/programmers/ApiFileProgrammer.js +28 -0
  24. package/lib/programmers/ApiFileProgrammer.js.map +1 -0
  25. package/lib/programmers/ApiFunctionProgrammer.d.ts +15 -0
  26. package/lib/programmers/ApiFunctionProgrammer.js +96 -0
  27. package/lib/programmers/ApiFunctionProgrammer.js.map +1 -0
  28. package/lib/programmers/ApiNamespaceProgrammer.d.ts +15 -0
  29. package/lib/programmers/ApiNamespaceProgrammer.js +147 -0
  30. package/lib/programmers/ApiNamespaceProgrammer.js.map +1 -0
  31. package/lib/programmers/ApiProgrammer.d.ts +5 -0
  32. package/lib/programmers/ApiProgrammer.js +62 -0
  33. package/lib/programmers/ApiProgrammer.js.map +1 -0
  34. package/lib/programmers/ApiSimulatationProgrammer.d.ts +14 -0
  35. package/lib/programmers/ApiSimulatationProgrammer.js +127 -0
  36. package/lib/programmers/ApiSimulatationProgrammer.js.map +1 -0
  37. package/lib/programmers/DtoProgrammer.js +2 -2
  38. package/lib/programmers/DtoProgrammer.js.map +1 -1
  39. package/lib/programmers/ImportProgrammer.d.ts +2 -1
  40. package/lib/programmers/ImportProgrammer.js +19 -4
  41. package/lib/programmers/ImportProgrammer.js.map +1 -1
  42. package/lib/programmers/NestControllerProgrammer.js +2 -1
  43. package/lib/programmers/NestControllerProgrammer.js.map +1 -1
  44. package/lib/programmers/NestMethodProgrammer.js +33 -18
  45. package/lib/programmers/NestMethodProgrammer.js.map +1 -1
  46. package/lib/programmers/NestProgrammer.d.ts +1 -1
  47. package/lib/programmers/NestProgrammer.js +5 -5
  48. package/lib/programmers/NestProgrammer.js.map +1 -1
  49. package/lib/programmers/SchemaProgrammer.d.ts +1 -1
  50. package/lib/programmers/SchemaProgrammer.js +17 -17
  51. package/lib/programmers/SchemaProgrammer.js.map +1 -1
  52. package/lib/structures/IMigrateProgram.d.ts +2 -0
  53. package/lib/structures/IMigrateRoute.d.ts +13 -4
  54. package/lib/utils/SetupWizard.js +0 -3
  55. package/lib/utils/SetupWizard.js.map +1 -1
  56. package/lib/utils/StringUtil.d.ts +1 -0
  57. package/lib/utils/StringUtil.js +4 -2
  58. package/lib/utils/StringUtil.js.map +1 -1
  59. package/package.json +67 -64
  60. package/src/IMigrateConfig.ts +3 -0
  61. package/src/MigrateApplication.ts +42 -33
  62. package/src/analyzers/ControllerAnalyzer.ts +19 -3
  63. package/src/analyzers/MethodAnalyzer.ts +18 -5
  64. package/src/analyzers/MigrateAnalyzer.ts +8 -4
  65. package/src/archivers/FileArchiver.ts +10 -7
  66. package/src/executable/migrate.ts +15 -9
  67. package/src/internal/MigrateArguments.ts +74 -0
  68. package/src/programmers/ApiFileProgrammer.ts +53 -0
  69. package/src/programmers/ApiFunctionProgrammer.ts +204 -0
  70. package/src/programmers/ApiNamespaceProgrammer.ts +418 -0
  71. package/src/programmers/ApiProgrammer.ts +70 -0
  72. package/src/programmers/ApiSimulatationProgrammer.ts +328 -0
  73. package/src/programmers/DtoProgrammer.ts +3 -3
  74. package/src/programmers/ImportProgrammer.ts +37 -21
  75. package/src/programmers/NestControllerProgrammer.ts +2 -1
  76. package/src/programmers/NestMethodProgrammer.ts +39 -22
  77. package/src/programmers/NestProgrammer.ts +1 -1
  78. package/src/programmers/SchemaProgrammer.ts +22 -25
  79. package/src/structures/IMigrateProgram.ts +2 -0
  80. package/src/structures/IMigrateRoute.ts +13 -5
  81. package/src/utils/SetupWizard.ts +0 -3
  82. package/src/utils/StringUtil.ts +11 -2
  83. package/lib/analyzers/RouteAnalyzer.d.ts +0 -0
  84. package/lib/analyzers/RouteAnalyzer.js +0 -2
  85. package/lib/analyzers/RouteAnalyzer.js.map +0 -1
  86. package/src/analyzers/RouteAnalyzer.ts +0 -0
package/package.json CHANGED
@@ -1,64 +1,67 @@
1
- {
2
- "name": "@nestia/migrate",
3
- "version": "0.6.1",
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.4.0",
34
- "@nestia/fetcher": "^2.4.0",
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/node": "^20.3.3",
41
- "dotenv": "^16.3.1",
42
- "dotenv-expand": "^10.0.0",
43
- "rimraf": "^5.0.1",
44
- "serialize-error": "^4.1.0",
45
- "source-map-support": "^0.5.21",
46
- "ts-node": "^10.9.1",
47
- "ts-patch": "^3.1.0",
48
- "tstl": "^2.5.13",
49
- "typescript-transform-paths": "^3.4.6"
50
- },
51
- "dependencies": {
52
- "typia": "^5.4.1",
53
- "typescript": "^5.3.3"
54
- },
55
- "files": [
56
- "lib",
57
- "src",
58
- "!lib/test",
59
- "!src/test",
60
- "package.json",
61
- "README.md",
62
- "LICENSE"
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
+ }
@@ -0,0 +1,3 @@
1
+ export interface IMigrateConfig {
2
+ simulate: boolean;
3
+ }
@@ -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 { MigrateProgrammer } from "./programmers/NestProgrammer";
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(swagger: ISwagger) {
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
- const program: IMigrateProgram = this.analyze();
33
- this.files = MigrateProgrammer.write(program);
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
- (archiver: NestiaMigrateApplication.IArchiver) =>
40
- (output: string): void => {
41
- const program: IMigrateProgram = this.analyze();
42
- const files: IMigrateFile[] = MigrateProgrammer.write(program);
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
- cp.execSync(
46
- `git clone https://github.com/samchon/nestia-template "${output}"`,
47
- { stdio: "ignore" },
48
- );
49
- try {
50
- for (const path of [
51
- "/.git",
52
- "/src/api",
53
- "/src/controllers",
54
- "/src/providers",
55
- "/test/features",
56
- ])
57
- fs.rmSync(`${output}${path}`, {
58
- recursive: true,
59
- force: true,
60
- });
61
- } catch {}
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
- naming(controller);
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 naming = (controller: IMigrateController): void => {
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
- "x-nestia-jsDocTags": route["x-nestia-jsDocTags"],
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) return { type: "text/plain", schema: { type: "string" } };
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 = (swagger: ISwagger): IMigrateProgram => ({
6
- swagger,
7
- controllers: ControllerAnalyzer.analyze(swagger),
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([output, f.location, f.file].join("/"), f.content);
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 [input] [output]
11
+ npx @nestia/migrate <nest|sdk> --input <swagger.json> --output <directory>
12
12
 
13
- ex) npx @nestia/migrate swagger.json my-new-project
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(swagger);
51
- app.generate({
52
- mkdir: fs.mkdirSync,
53
- writeFile: (path, content) => fs.writeFileSync(path, content, "utf8"),
54
- })(output);
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
+ }