@nestia/migrate 12.0.0-dev.20260601.1 → 12.0.0-dev.20260612.2

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 (50) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +93 -93
  3. package/lib/NestiaMigrateApplication.js +19 -1
  4. package/lib/NestiaMigrateApplication.js.map +1 -1
  5. package/lib/bundles/NEST_TEMPLATE.js +47 -47
  6. package/lib/bundles/NEST_TEMPLATE.js.map +1 -1
  7. package/lib/bundles/SDK_TEMPLATE.js +20 -20
  8. package/lib/bundles/SDK_TEMPLATE.js.map +1 -1
  9. package/lib/index.mjs +94 -77
  10. package/lib/index.mjs.map +1 -1
  11. package/lib/programmers/NestiaMigrateApiFunctionProgrammer.js +6 -2
  12. package/lib/programmers/NestiaMigrateApiFunctionProgrammer.js.map +1 -1
  13. package/package.json +5 -5
  14. package/src/NestiaMigrateApplication.ts +196 -167
  15. package/src/analyzers/NestiaMigrateControllerAnalyzer.ts +51 -51
  16. package/src/archivers/NestiaMigrateFileArchiver.ts +28 -28
  17. package/src/bundles/NEST_TEMPLATE.ts +47 -47
  18. package/src/bundles/SDK_TEMPLATE.ts +20 -20
  19. package/src/executable/NestiaMigrateCommander.ts +115 -115
  20. package/src/executable/NestiaMigrateInquirer.ts +106 -106
  21. package/src/executable/bundle.js +349 -349
  22. package/src/executable/migrate.ts +7 -7
  23. package/src/factories/TypeLiteralFactory.ts +63 -63
  24. package/src/index.ts +4 -4
  25. package/src/internal/ts.ts +94 -94
  26. package/src/module.ts +6 -6
  27. package/src/programmers/NestiaMigrateApiFileProgrammer.ts +58 -58
  28. package/src/programmers/NestiaMigrateApiFunctionProgrammer.ts +373 -369
  29. package/src/programmers/NestiaMigrateApiNamespaceProgrammer.ts +528 -528
  30. package/src/programmers/NestiaMigrateApiProgrammer.ts +108 -108
  31. package/src/programmers/NestiaMigrateApiSimulationProgrammer.ts +314 -314
  32. package/src/programmers/NestiaMigrateApiStartProgrammer.ts +198 -198
  33. package/src/programmers/NestiaMigrateDtoProgrammer.ts +99 -99
  34. package/src/programmers/NestiaMigrateE2eFileProgrammer.ts +156 -156
  35. package/src/programmers/NestiaMigrateE2eProgrammer.ts +48 -48
  36. package/src/programmers/NestiaMigrateImportProgrammer.ts +119 -119
  37. package/src/programmers/NestiaMigrateNestControllerProgrammer.ts +70 -70
  38. package/src/programmers/NestiaMigrateNestMethodProgrammer.ts +414 -414
  39. package/src/programmers/NestiaMigrateNestModuleProgrammer.ts +66 -66
  40. package/src/programmers/NestiaMigrateNestProgrammer.ts +89 -89
  41. package/src/programmers/NestiaMigrateSchemaProgrammer.ts +477 -477
  42. package/src/programmers/index.ts +15 -15
  43. package/src/structures/INestiaMigrateConfig.ts +19 -19
  44. package/src/structures/INestiaMigrateContext.ts +9 -9
  45. package/src/structures/INestiaMigrateController.ts +8 -8
  46. package/src/structures/INestiaMigrateFile.ts +5 -5
  47. package/src/structures/index.ts +4 -4
  48. package/src/utils/FilePrinter.ts +44 -44
  49. package/src/utils/MapUtil.ts +13 -13
  50. package/src/utils/StringUtil.ts +109 -109
@@ -1,167 +1,196 @@
1
- import {
2
- IHttpMigrateApplication,
3
- OpenApi,
4
- OpenApiV3,
5
- OpenApiV3_1,
6
- OpenApiV3_2,
7
- SwaggerV2,
8
- } from "@typia/interface";
9
- import type { IValidation } from "@typia/interface";
10
- import * as typiaUtils from "@typia/utils";
11
-
12
- import { NEST_TEMPLATE } from "./bundles/NEST_TEMPLATE";
13
- import { SDK_TEMPLATE } from "./bundles/SDK_TEMPLATE";
14
- import { NestiaMigrateApiProgrammer } from "./programmers/NestiaMigrateApiProgrammer";
15
- import { NestiaMigrateApiStartProgrammer } from "./programmers/NestiaMigrateApiStartProgrammer";
16
- import { NestiaMigrateE2eProgrammer } from "./programmers/NestiaMigrateE2eProgrammer";
17
- import { NestiaMigrateNestProgrammer } from "./programmers/NestiaMigrateNestProgrammer";
18
- import { INestiaMigrateConfig } from "./structures/INestiaMigrateConfig";
19
- import { INestiaMigrateContext } from "./structures/INestiaMigrateContext";
20
-
21
- const { HttpMigration, OpenApiConverter } =
22
- (typiaUtils as { default?: typeof typiaUtils }).default ?? typiaUtils;
23
-
24
- export class NestiaMigrateApplication {
25
- private readonly data_: IHttpMigrateApplication;
26
-
27
- /* -----------------------------------------------------------
28
- CONSTRUCTORS
29
- ----------------------------------------------------------- */
30
- public constructor(public readonly document: OpenApi.IDocument) {
31
- this.data_ = HttpMigration.application(document);
32
- }
33
-
34
- public static assert(
35
- document:
36
- | SwaggerV2.IDocument
37
- | OpenApiV3.IDocument
38
- | OpenApiV3_1.IDocument
39
- | OpenApiV3_2.IDocument
40
- | OpenApi.IDocument,
41
- ): NestiaMigrateApplication {
42
- return new NestiaMigrateApplication(
43
- OpenApiConverter.upgradeDocument(document),
44
- );
45
- }
46
-
47
- public static validate(
48
- document:
49
- | SwaggerV2.IDocument
50
- | OpenApiV3.IDocument
51
- | OpenApiV3_1.IDocument
52
- | OpenApiV3_2.IDocument
53
- | OpenApi.IDocument,
54
- ): IValidation<NestiaMigrateApplication> {
55
- try {
56
- return {
57
- success: true,
58
- data: new NestiaMigrateApplication(
59
- OpenApiConverter.upgradeDocument(document),
60
- ),
61
- };
62
- } catch (exp) {
63
- const message: string =
64
- exp instanceof Error ? exp.message : String(exp);
65
- return {
66
- success: false,
67
- data: document,
68
- errors: [
69
- {
70
- path: "$input",
71
- expected:
72
- "SwaggerV2.IDocument | OpenApiV3.IDocument | OpenApiV3_1.IDocument | OpenApiV3_2.IDocument | OpenApi.IDocument",
73
- value: message,
74
- },
75
- ],
76
- };
77
- }
78
- }
79
-
80
- /* -----------------------------------------------------------
81
- ACCESSORS
82
- ----------------------------------------------------------- */
83
- public getData(): IHttpMigrateApplication {
84
- return this.data_;
85
- }
86
-
87
- public nest(config: INestiaMigrateConfig): Record<string, string> {
88
- const context: INestiaMigrateContext = createContext(
89
- "nest",
90
- this.data_,
91
- config,
92
- );
93
- const files: Record<string, string> = {
94
- ...Object.fromEntries(
95
- Object.entries(NEST_TEMPLATE).filter(
96
- ([key]) =>
97
- key.startsWith("src/api/structures") === false &&
98
- key.startsWith("src/api/functional") === false &&
99
- key.startsWith("src/api/controllers") === false &&
100
- key.startsWith("test/features") === false,
101
- ),
102
- ),
103
- ...NestiaMigrateNestProgrammer.write(context),
104
- ...NestiaMigrateApiProgrammer.write(context),
105
- ...(config.e2e ? NestiaMigrateE2eProgrammer.write(context) : {}),
106
- ...(config.keyword === false
107
- ? {
108
- "nestia.config.ts": NEST_TEMPLATE["nestia.config.ts"]!.replace(
109
- "keyword: true",
110
- "keyword: false",
111
- ),
112
- }
113
- : {}),
114
- };
115
- return config.package ? renameSlug(config.package, files) : files;
116
- }
117
-
118
- public sdk(config: INestiaMigrateConfig): Record<string, string> {
119
- const context: INestiaMigrateContext = createContext(
120
- "sdk",
121
- this.data_,
122
- config,
123
- );
124
- const files: Record<string, string> = {
125
- ...Object.fromEntries(
126
- Object.entries(SDK_TEMPLATE).filter(
127
- ([key]) =>
128
- key.startsWith("src/structures") === false &&
129
- key.startsWith("src/functional") === false &&
130
- key.startsWith("test/features") === false,
131
- ),
132
- ),
133
- ...NestiaMigrateApiProgrammer.write(context),
134
- ...NestiaMigrateApiStartProgrammer.write(context),
135
- ...(config.e2e ? NestiaMigrateE2eProgrammer.write(context) : {}),
136
- "swagger.json": JSON.stringify(this.document, null, 2),
137
- };
138
- return config.package ? renameSlug(config.package, files) : files;
139
- }
140
- }
141
-
142
- const createContext = (
143
- mode: "nest" | "sdk",
144
- application: IHttpMigrateApplication,
145
- config: INestiaMigrateConfig,
146
- ): INestiaMigrateContext => {
147
- return {
148
- mode,
149
- application: {
150
- ...application,
151
- routes: application.routes.filter((r) => r.method !== "query"),
152
- },
153
- config,
154
- };
155
- };
156
-
157
- const renameSlug = (
158
- slug: string,
159
- files: Record<string, string>,
160
- ): Record<string, string> => {
161
- return Object.fromEntries(
162
- Object.entries(files).map(([key, value]) => [
163
- key,
164
- value.split(`@ORGANIZATION/PROJECT`).join(slug),
165
- ]),
166
- );
167
- };
1
+ import {
2
+ IHttpMigrateApplication,
3
+ IHttpMigrateRoute,
4
+ OpenApi,
5
+ OpenApiV3,
6
+ OpenApiV3_1,
7
+ OpenApiV3_2,
8
+ SwaggerV2,
9
+ } from "@typia/interface";
10
+ import type { IValidation } from "@typia/interface";
11
+ import * as typiaUtils from "@typia/utils";
12
+
13
+ import { NEST_TEMPLATE } from "./bundles/NEST_TEMPLATE";
14
+ import { SDK_TEMPLATE } from "./bundles/SDK_TEMPLATE";
15
+ import { NestiaMigrateApiProgrammer } from "./programmers/NestiaMigrateApiProgrammer";
16
+ import { NestiaMigrateApiStartProgrammer } from "./programmers/NestiaMigrateApiStartProgrammer";
17
+ import { NestiaMigrateE2eProgrammer } from "./programmers/NestiaMigrateE2eProgrammer";
18
+ import { NestiaMigrateNestProgrammer } from "./programmers/NestiaMigrateNestProgrammer";
19
+ import { INestiaMigrateConfig } from "./structures/INestiaMigrateConfig";
20
+ import { INestiaMigrateContext } from "./structures/INestiaMigrateContext";
21
+
22
+ const { HttpMigration, OpenApiConverter } =
23
+ (typiaUtils as { default?: typeof typiaUtils }).default ?? typiaUtils;
24
+
25
+ export class NestiaMigrateApplication {
26
+ private readonly data_: IHttpMigrateApplication;
27
+
28
+ /* -----------------------------------------------------------
29
+ CONSTRUCTORS
30
+ ----------------------------------------------------------- */
31
+ public constructor(public readonly document: OpenApi.IDocument) {
32
+ this.data_ = HttpMigration.application(document);
33
+ }
34
+
35
+ public static assert(
36
+ document:
37
+ | SwaggerV2.IDocument
38
+ | OpenApiV3.IDocument
39
+ | OpenApiV3_1.IDocument
40
+ | OpenApiV3_2.IDocument
41
+ | OpenApi.IDocument,
42
+ ): NestiaMigrateApplication {
43
+ return new NestiaMigrateApplication(
44
+ OpenApiConverter.upgradeDocument(document),
45
+ );
46
+ }
47
+
48
+ public static validate(
49
+ document:
50
+ | SwaggerV2.IDocument
51
+ | OpenApiV3.IDocument
52
+ | OpenApiV3_1.IDocument
53
+ | OpenApiV3_2.IDocument
54
+ | OpenApi.IDocument,
55
+ ): IValidation<NestiaMigrateApplication> {
56
+ try {
57
+ return {
58
+ success: true,
59
+ data: new NestiaMigrateApplication(
60
+ OpenApiConverter.upgradeDocument(document),
61
+ ),
62
+ };
63
+ } catch (exp) {
64
+ const message: string = exp instanceof Error ? exp.message : String(exp);
65
+ return {
66
+ success: false,
67
+ data: document,
68
+ errors: [
69
+ {
70
+ path: "$input",
71
+ expected:
72
+ "SwaggerV2.IDocument | OpenApiV3.IDocument | OpenApiV3_1.IDocument | OpenApiV3_2.IDocument | OpenApi.IDocument",
73
+ value: message,
74
+ },
75
+ ],
76
+ };
77
+ }
78
+ }
79
+
80
+ /* -----------------------------------------------------------
81
+ ACCESSORS
82
+ ----------------------------------------------------------- */
83
+ public getData(): IHttpMigrateApplication {
84
+ return this.data_;
85
+ }
86
+
87
+ public nest(config: INestiaMigrateConfig): Record<string, string> {
88
+ const context: INestiaMigrateContext = createContext(
89
+ "nest",
90
+ this.data_,
91
+ config,
92
+ );
93
+ const files: Record<string, string> = {
94
+ ...Object.fromEntries(
95
+ Object.entries(NEST_TEMPLATE).filter(
96
+ ([key]) =>
97
+ key.startsWith("src/api/structures") === false &&
98
+ key.startsWith("src/api/functional") === false &&
99
+ key.startsWith("src/api/controllers") === false &&
100
+ key.startsWith("test/features") === false,
101
+ ),
102
+ ),
103
+ ...NestiaMigrateNestProgrammer.write(context),
104
+ ...NestiaMigrateApiProgrammer.write(context),
105
+ ...(config.e2e ? NestiaMigrateE2eProgrammer.write(context) : {}),
106
+ ...(config.keyword === false
107
+ ? {
108
+ "nestia.config.ts": NEST_TEMPLATE["nestia.config.ts"]!.replace(
109
+ "keyword: true",
110
+ "keyword: false",
111
+ ),
112
+ }
113
+ : {}),
114
+ };
115
+ return config.package ? renameSlug(config.package, files) : files;
116
+ }
117
+
118
+ public sdk(config: INestiaMigrateConfig): Record<string, string> {
119
+ const context: INestiaMigrateContext = createContext(
120
+ "sdk",
121
+ this.data_,
122
+ config,
123
+ );
124
+ const files: Record<string, string> = {
125
+ ...Object.fromEntries(
126
+ Object.entries(SDK_TEMPLATE).filter(
127
+ ([key]) =>
128
+ key.startsWith("src/structures") === false &&
129
+ key.startsWith("src/functional") === false &&
130
+ key.startsWith("test/features") === false,
131
+ ),
132
+ ),
133
+ ...NestiaMigrateApiProgrammer.write(context),
134
+ ...NestiaMigrateApiStartProgrammer.write(context),
135
+ ...(config.e2e ? NestiaMigrateE2eProgrammer.write(context) : {}),
136
+ "swagger.json": JSON.stringify(this.document, null, 2),
137
+ };
138
+ return config.package ? renameSlug(config.package, files) : files;
139
+ }
140
+ }
141
+
142
+ const createContext = (
143
+ mode: "nest" | "sdk",
144
+ application: IHttpMigrateApplication,
145
+ config: INestiaMigrateConfig,
146
+ ): INestiaMigrateContext => {
147
+ const routes: IHttpMigrateRoute[] = escapeConflictingAccessors(
148
+ application.routes
149
+ .filter((r) => r.method !== "query")
150
+ .map((r) => ({
151
+ ...r,
152
+ accessor: [...r.accessor],
153
+ })),
154
+ );
155
+ return {
156
+ mode,
157
+ application: {
158
+ ...application,
159
+ routes,
160
+ },
161
+ config,
162
+ };
163
+ };
164
+
165
+ const escapeConflictingAccessors = (
166
+ routes: IHttpMigrateRoute[],
167
+ ): IHttpMigrateRoute[] => {
168
+ for (const route of routes)
169
+ while (true) {
170
+ const neighbor: IHttpMigrateRoute | undefined = routes.find(
171
+ (candidate) =>
172
+ candidate !== route &&
173
+ candidate.accessor.length < route.accessor.length &&
174
+ route.accessor
175
+ .slice(0, candidate.accessor.length)
176
+ .every((value, index) => value === candidate.accessor[index]),
177
+ );
178
+ if (neighbor === undefined) break;
179
+
180
+ const index: number = neighbor.accessor.length - 1;
181
+ route.accessor[index] = `_${route.accessor[index]}`;
182
+ }
183
+ return routes;
184
+ };
185
+
186
+ const renameSlug = (
187
+ slug: string,
188
+ files: Record<string, string>,
189
+ ): Record<string, string> => {
190
+ return Object.fromEntries(
191
+ Object.entries(files).map(([key, value]) => [
192
+ key,
193
+ value.split(`@ORGANIZATION/PROJECT`).join(slug),
194
+ ]),
195
+ );
196
+ };
@@ -1,51 +1,51 @@
1
- import { IHttpMigrateRoute } from "@typia/interface";
2
-
3
- import { INestiaMigrateController } from "../structures/INestiaMigrateController";
4
- import { MapUtil } from "../utils/MapUtil";
5
- import { StringUtil } from "../utils/StringUtil";
6
-
7
- export namespace NestiaMigrateControllerAnalyzer {
8
- export const analyze = (
9
- routes: IHttpMigrateRoute[],
10
- ): INestiaMigrateController[] => {
11
- const collection: Map<string, INestiaMigrateController> = new Map();
12
- for (const r of routes) {
13
- const name: string =
14
- r.operation()["x-samchon-controller"] ??
15
- (r.accessor.length <= 1
16
- ? "__App"
17
- : r.accessor.slice(0, -1).map(StringUtil.capitalize).join("")) +
18
- "Controller";
19
- MapUtil.take(collection)(name)(() => ({
20
- name,
21
- path: "@lazy",
22
- location: "@lazy",
23
- routes: [],
24
- })).routes.push(r);
25
- }
26
-
27
- const controllers: INestiaMigrateController[] = [...collection.values()];
28
- for (const col of controllers) {
29
- const splitPath = (r: IHttpMigrateRoute): string[] =>
30
- r.emendedPath.split("/");
31
- const splitLocation = (r: IHttpMigrateRoute): string[] =>
32
- splitPath(r).filter((s) => s.length !== 0 && s[0] !== ":");
33
-
34
- const minPath: string[] = splitPath(col.routes[0]!);
35
- const minLocation: string[] = splitLocation(col.routes[0]!);
36
- for (const r of col.routes.slice(1)) {
37
- minPath.splice(getSplitIndex(minPath, splitPath(r)));
38
- minLocation.splice(getSplitIndex(minLocation, splitLocation(r)));
39
- }
40
- col.path = minPath.join("/");
41
- col.location = ["src", "controllers", ...minLocation].join("/");
42
- }
43
- return controllers;
44
- };
45
- }
46
-
47
- const getSplitIndex = (x: string[], y: string[]) => {
48
- const n: number = Math.min(x.length, y.length);
49
- for (let i: number = 0; i < n; ++i) if (x[i] !== y[i]) return i;
50
- return n;
51
- };
1
+ import { IHttpMigrateRoute } from "@typia/interface";
2
+
3
+ import { INestiaMigrateController } from "../structures/INestiaMigrateController";
4
+ import { MapUtil } from "../utils/MapUtil";
5
+ import { StringUtil } from "../utils/StringUtil";
6
+
7
+ export namespace NestiaMigrateControllerAnalyzer {
8
+ export const analyze = (
9
+ routes: IHttpMigrateRoute[],
10
+ ): INestiaMigrateController[] => {
11
+ const collection: Map<string, INestiaMigrateController> = new Map();
12
+ for (const r of routes) {
13
+ const name: string =
14
+ r.operation()["x-samchon-controller"] ??
15
+ (r.accessor.length <= 1
16
+ ? "__App"
17
+ : r.accessor.slice(0, -1).map(StringUtil.capitalize).join("")) +
18
+ "Controller";
19
+ MapUtil.take(collection)(name)(() => ({
20
+ name,
21
+ path: "@lazy",
22
+ location: "@lazy",
23
+ routes: [],
24
+ })).routes.push(r);
25
+ }
26
+
27
+ const controllers: INestiaMigrateController[] = [...collection.values()];
28
+ for (const col of controllers) {
29
+ const splitPath = (r: IHttpMigrateRoute): string[] =>
30
+ r.emendedPath.split("/");
31
+ const splitLocation = (r: IHttpMigrateRoute): string[] =>
32
+ splitPath(r).filter((s) => s.length !== 0 && s[0] !== ":");
33
+
34
+ const minPath: string[] = splitPath(col.routes[0]!);
35
+ const minLocation: string[] = splitLocation(col.routes[0]!);
36
+ for (const r of col.routes.slice(1)) {
37
+ minPath.splice(getSplitIndex(minPath, splitPath(r)));
38
+ minLocation.splice(getSplitIndex(minLocation, splitLocation(r)));
39
+ }
40
+ col.path = minPath.join("/");
41
+ col.location = ["src", "controllers", ...minLocation].join("/");
42
+ }
43
+ return controllers;
44
+ };
45
+ }
46
+
47
+ const getSplitIndex = (x: string[], y: string[]) => {
48
+ const n: number = Math.min(x.length, y.length);
49
+ for (let i: number = 0; i < n; ++i) if (x[i] !== y[i]) return i;
50
+ return n;
51
+ };
@@ -1,28 +1,28 @@
1
- import { VariadicSingleton } from "tstl";
2
-
3
- export namespace NestiaMigrateFileArchiver {
4
- export const archive = async (props: {
5
- mkdir: (path: string) => Promise<void>;
6
- writeFile: (path: string, content: string) => Promise<void>;
7
- root: string;
8
- files: Record<string, string>;
9
- }): Promise<void> => {
10
- const mkdir = new VariadicSingleton(
11
- async (location: string): Promise<void> => {
12
- try {
13
- await props.mkdir(`${props.root}/${location}`);
14
- } catch {}
15
- },
16
- );
17
- const iterate = async (location: string): Promise<void> => {
18
- const sequence: string[] = location
19
- .split("/")
20
- .map((_str, i, entire) => entire.slice(0, i + 1).join("/"));
21
- for (const s of sequence) await mkdir.get(s);
22
- };
23
- for (const [key, value] of Object.entries(props.files)) {
24
- await iterate(key.split("/").slice(0, -1).join("/"));
25
- await props.writeFile(`${props.root}/${key}`, value);
26
- }
27
- };
28
- }
1
+ import { VariadicSingleton } from "tstl";
2
+
3
+ export namespace NestiaMigrateFileArchiver {
4
+ export const archive = async (props: {
5
+ mkdir: (path: string) => Promise<void>;
6
+ writeFile: (path: string, content: string) => Promise<void>;
7
+ root: string;
8
+ files: Record<string, string>;
9
+ }): Promise<void> => {
10
+ const mkdir = new VariadicSingleton(
11
+ async (location: string): Promise<void> => {
12
+ try {
13
+ await props.mkdir(`${props.root}/${location}`);
14
+ } catch {}
15
+ },
16
+ );
17
+ const iterate = async (location: string): Promise<void> => {
18
+ const sequence: string[] = location
19
+ .split("/")
20
+ .map((_str, i, entire) => entire.slice(0, i + 1).join("/"));
21
+ for (const s of sequence) await mkdir.get(s);
22
+ };
23
+ for (const [key, value] of Object.entries(props.files)) {
24
+ await iterate(key.split("/").slice(0, -1).join("/"));
25
+ await props.writeFile(`${props.root}/${key}`, value);
26
+ }
27
+ };
28
+ }