@nestia/migrate 0.13.9 → 0.13.10
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/bundles/NEST_TEMPLATE.js +2 -2
- package/lib/bundles/SDK_TEMPLATE.js +1 -1
- package/lib/utils/openapi-down-convert/converter.js +2 -2
- package/package.json +4 -4
- package/src/analyzers/MigrateAnalyzer.ts +9 -9
- package/src/archivers/MigrateFileArchiver.ts +38 -38
- package/src/bundles/NEST_TEMPLATE.ts +2 -2
- package/src/bundles/SDK_TEMPLATE.ts +1 -1
- package/src/executable/bundle.ts +110 -110
- package/src/executable/migrate.ts +7 -7
- package/src/index.ts +4 -4
- package/src/internal/MigrateInquirer.ts +86 -86
- package/src/programmers/MigrateNestModuleProgrammer.ts +63 -63
- package/src/structures/IMigrateController.ts +8 -8
- package/src/structures/IMigrateFile.ts +5 -5
- package/src/structures/IMigrateSchema.ts +4 -4
- package/src/utils/FilePrinter.ts +36 -36
- package/src/utils/MapUtil.ts +13 -13
- package/src/utils/SetupWizard.ts +12 -12
- package/src/utils/StringUtil.ts +60 -60
- package/src/utils/openapi-down-convert/RefVisitor.ts +139 -139
- package/src/utils/openapi-down-convert/converter.ts +527 -527
@@ -1,86 +1,86 @@
|
|
1
|
-
import commander from "commander";
|
2
|
-
import inquirer from "inquirer";
|
3
|
-
|
4
|
-
export namespace MigrateInquirer {
|
5
|
-
export interface IOutput {
|
6
|
-
mode: "nest" | "sdk";
|
7
|
-
input: string;
|
8
|
-
output: string;
|
9
|
-
simulate: boolean;
|
10
|
-
e2e: boolean;
|
11
|
-
}
|
12
|
-
|
13
|
-
export const parse = async (): Promise<IOutput> => {
|
14
|
-
// PREPARE ASSETS
|
15
|
-
commander.program.option("--mode [nest/sdk]", "migration mode");
|
16
|
-
commander.program.option(
|
17
|
-
"--input [swagger.json]",
|
18
|
-
"location of target swagger.json file",
|
19
|
-
);
|
20
|
-
commander.program.option("--output [directory]", "output directory path");
|
21
|
-
commander.program.option("--simulate", "Mockup simulator");
|
22
|
-
commander.program.option("--e2e [boolean]", "Generate E2E tests");
|
23
|
-
|
24
|
-
// INTERNAL PROCEDURES
|
25
|
-
const questioned = { value: false };
|
26
|
-
const action = (closure: (options: Partial<IOutput>) => Promise<IOutput>) =>
|
27
|
-
new Promise<IOutput>((resolve, reject) => {
|
28
|
-
commander.program.action(async (options) => {
|
29
|
-
try {
|
30
|
-
resolve(await closure(options));
|
31
|
-
} catch (exp) {
|
32
|
-
reject(exp);
|
33
|
-
}
|
34
|
-
});
|
35
|
-
commander.program.parseAsync().catch(reject);
|
36
|
-
});
|
37
|
-
const select =
|
38
|
-
(name: string) =>
|
39
|
-
(message: string) =>
|
40
|
-
async <Choice extends string>(
|
41
|
-
choices: Choice[],
|
42
|
-
filter?: (value: string) => Choice,
|
43
|
-
): Promise<Choice> => {
|
44
|
-
questioned.value = true;
|
45
|
-
return (
|
46
|
-
await inquirer.createPromptModule()({
|
47
|
-
type: "list",
|
48
|
-
name: name,
|
49
|
-
message: message,
|
50
|
-
choices: choices,
|
51
|
-
filter,
|
52
|
-
})
|
53
|
-
)[name];
|
54
|
-
};
|
55
|
-
const input = (name: string) => async (message: string) =>
|
56
|
-
(
|
57
|
-
await inquirer.createPromptModule()({
|
58
|
-
type: "input",
|
59
|
-
name,
|
60
|
-
message,
|
61
|
-
})
|
62
|
-
)[name];
|
63
|
-
|
64
|
-
// DO CONSTRUCT
|
65
|
-
return action(async (partial) => {
|
66
|
-
partial.mode ??= await select("mode")("Migration mode")(
|
67
|
-
["NestJS" as "nest", "SDK" as "sdk"],
|
68
|
-
(value) => (value === "NestJS" ? "nest" : "sdk"),
|
69
|
-
);
|
70
|
-
partial.input ??= await input("input")("Swagger file location");
|
71
|
-
partial.output ??= await input("output")("Output directory path");
|
72
|
-
if (partial.simulate)
|
73
|
-
partial.simulate = (partial.simulate as any) === "true";
|
74
|
-
else
|
75
|
-
partial.simulate =
|
76
|
-
(await select("simulate")("Mokup Simulator")(["true", "false"])) ===
|
77
|
-
"true";
|
78
|
-
if (partial.e2e) partial.e2e = (partial.e2e as any) === "true";
|
79
|
-
else
|
80
|
-
partial.e2e =
|
81
|
-
(await select("e2e")("Generate E2E tests")(["true", "false"])) ===
|
82
|
-
"true";
|
83
|
-
return partial as IOutput;
|
84
|
-
});
|
85
|
-
};
|
86
|
-
}
|
1
|
+
import commander from "commander";
|
2
|
+
import inquirer from "inquirer";
|
3
|
+
|
4
|
+
export namespace MigrateInquirer {
|
5
|
+
export interface IOutput {
|
6
|
+
mode: "nest" | "sdk";
|
7
|
+
input: string;
|
8
|
+
output: string;
|
9
|
+
simulate: boolean;
|
10
|
+
e2e: boolean;
|
11
|
+
}
|
12
|
+
|
13
|
+
export const parse = async (): Promise<IOutput> => {
|
14
|
+
// PREPARE ASSETS
|
15
|
+
commander.program.option("--mode [nest/sdk]", "migration mode");
|
16
|
+
commander.program.option(
|
17
|
+
"--input [swagger.json]",
|
18
|
+
"location of target swagger.json file",
|
19
|
+
);
|
20
|
+
commander.program.option("--output [directory]", "output directory path");
|
21
|
+
commander.program.option("--simulate", "Mockup simulator");
|
22
|
+
commander.program.option("--e2e [boolean]", "Generate E2E tests");
|
23
|
+
|
24
|
+
// INTERNAL PROCEDURES
|
25
|
+
const questioned = { value: false };
|
26
|
+
const action = (closure: (options: Partial<IOutput>) => Promise<IOutput>) =>
|
27
|
+
new Promise<IOutput>((resolve, reject) => {
|
28
|
+
commander.program.action(async (options) => {
|
29
|
+
try {
|
30
|
+
resolve(await closure(options));
|
31
|
+
} catch (exp) {
|
32
|
+
reject(exp);
|
33
|
+
}
|
34
|
+
});
|
35
|
+
commander.program.parseAsync().catch(reject);
|
36
|
+
});
|
37
|
+
const select =
|
38
|
+
(name: string) =>
|
39
|
+
(message: string) =>
|
40
|
+
async <Choice extends string>(
|
41
|
+
choices: Choice[],
|
42
|
+
filter?: (value: string) => Choice,
|
43
|
+
): Promise<Choice> => {
|
44
|
+
questioned.value = true;
|
45
|
+
return (
|
46
|
+
await inquirer.createPromptModule()({
|
47
|
+
type: "list",
|
48
|
+
name: name,
|
49
|
+
message: message,
|
50
|
+
choices: choices,
|
51
|
+
filter,
|
52
|
+
})
|
53
|
+
)[name];
|
54
|
+
};
|
55
|
+
const input = (name: string) => async (message: string) =>
|
56
|
+
(
|
57
|
+
await inquirer.createPromptModule()({
|
58
|
+
type: "input",
|
59
|
+
name,
|
60
|
+
message,
|
61
|
+
})
|
62
|
+
)[name];
|
63
|
+
|
64
|
+
// DO CONSTRUCT
|
65
|
+
return action(async (partial) => {
|
66
|
+
partial.mode ??= await select("mode")("Migration mode")(
|
67
|
+
["NestJS" as "nest", "SDK" as "sdk"],
|
68
|
+
(value) => (value === "NestJS" ? "nest" : "sdk"),
|
69
|
+
);
|
70
|
+
partial.input ??= await input("input")("Swagger file location");
|
71
|
+
partial.output ??= await input("output")("Output directory path");
|
72
|
+
if (partial.simulate)
|
73
|
+
partial.simulate = (partial.simulate as any) === "true";
|
74
|
+
else
|
75
|
+
partial.simulate =
|
76
|
+
(await select("simulate")("Mokup Simulator")(["true", "false"])) ===
|
77
|
+
"true";
|
78
|
+
if (partial.e2e) partial.e2e = (partial.e2e as any) === "true";
|
79
|
+
else
|
80
|
+
partial.e2e =
|
81
|
+
(await select("e2e")("Generate E2E tests")(["true", "false"])) ===
|
82
|
+
"true";
|
83
|
+
return partial as IOutput;
|
84
|
+
});
|
85
|
+
};
|
86
|
+
}
|
@@ -1,63 +1,63 @@
|
|
1
|
-
import ts from "typescript";
|
2
|
-
|
3
|
-
import { IMigrateController } from "../structures/IMigrateController";
|
4
|
-
import { FilePrinter } from "../utils/FilePrinter";
|
5
|
-
|
6
|
-
export namespace MigrateNestModuleProgrammer {
|
7
|
-
export const write = (controllers: IMigrateController[]): ts.Statement[] => [
|
8
|
-
$import("@nestjs/common")("Module"),
|
9
|
-
...(controllers.length ? [FilePrinter.newLine()] : []),
|
10
|
-
...controllers.map((c) =>
|
11
|
-
$import(`${c.location.replace("src/", "./")}/${c.name}`)(c.name),
|
12
|
-
),
|
13
|
-
...(controllers.length ? [FilePrinter.newLine()] : []),
|
14
|
-
ts.factory.createClassDeclaration(
|
15
|
-
[
|
16
|
-
ts.factory.createDecorator(
|
17
|
-
ts.factory.createCallExpression(
|
18
|
-
ts.factory.createIdentifier("Module"),
|
19
|
-
undefined,
|
20
|
-
[
|
21
|
-
ts.factory.createObjectLiteralExpression(
|
22
|
-
[
|
23
|
-
ts.factory.createPropertyAssignment(
|
24
|
-
ts.factory.createIdentifier("controllers"),
|
25
|
-
ts.factory.createArrayLiteralExpression(
|
26
|
-
controllers.map((c) =>
|
27
|
-
ts.factory.createIdentifier(c.name),
|
28
|
-
),
|
29
|
-
true,
|
30
|
-
),
|
31
|
-
),
|
32
|
-
],
|
33
|
-
true,
|
34
|
-
),
|
35
|
-
],
|
36
|
-
),
|
37
|
-
),
|
38
|
-
ts.factory.createToken(ts.SyntaxKind.ExportKeyword),
|
39
|
-
],
|
40
|
-
"MyModule",
|
41
|
-
undefined,
|
42
|
-
undefined,
|
43
|
-
[],
|
44
|
-
),
|
45
|
-
];
|
46
|
-
}
|
47
|
-
|
48
|
-
const $import = (file: string) => (instance: string) =>
|
49
|
-
ts.factory.createImportDeclaration(
|
50
|
-
undefined,
|
51
|
-
ts.factory.createImportClause(
|
52
|
-
false,
|
53
|
-
undefined,
|
54
|
-
ts.factory.createNamedImports([
|
55
|
-
ts.factory.createImportSpecifier(
|
56
|
-
false,
|
57
|
-
undefined,
|
58
|
-
ts.factory.createIdentifier(instance),
|
59
|
-
),
|
60
|
-
]),
|
61
|
-
),
|
62
|
-
ts.factory.createStringLiteral(file),
|
63
|
-
);
|
1
|
+
import ts from "typescript";
|
2
|
+
|
3
|
+
import { IMigrateController } from "../structures/IMigrateController";
|
4
|
+
import { FilePrinter } from "../utils/FilePrinter";
|
5
|
+
|
6
|
+
export namespace MigrateNestModuleProgrammer {
|
7
|
+
export const write = (controllers: IMigrateController[]): ts.Statement[] => [
|
8
|
+
$import("@nestjs/common")("Module"),
|
9
|
+
...(controllers.length ? [FilePrinter.newLine()] : []),
|
10
|
+
...controllers.map((c) =>
|
11
|
+
$import(`${c.location.replace("src/", "./")}/${c.name}`)(c.name),
|
12
|
+
),
|
13
|
+
...(controllers.length ? [FilePrinter.newLine()] : []),
|
14
|
+
ts.factory.createClassDeclaration(
|
15
|
+
[
|
16
|
+
ts.factory.createDecorator(
|
17
|
+
ts.factory.createCallExpression(
|
18
|
+
ts.factory.createIdentifier("Module"),
|
19
|
+
undefined,
|
20
|
+
[
|
21
|
+
ts.factory.createObjectLiteralExpression(
|
22
|
+
[
|
23
|
+
ts.factory.createPropertyAssignment(
|
24
|
+
ts.factory.createIdentifier("controllers"),
|
25
|
+
ts.factory.createArrayLiteralExpression(
|
26
|
+
controllers.map((c) =>
|
27
|
+
ts.factory.createIdentifier(c.name),
|
28
|
+
),
|
29
|
+
true,
|
30
|
+
),
|
31
|
+
),
|
32
|
+
],
|
33
|
+
true,
|
34
|
+
),
|
35
|
+
],
|
36
|
+
),
|
37
|
+
),
|
38
|
+
ts.factory.createToken(ts.SyntaxKind.ExportKeyword),
|
39
|
+
],
|
40
|
+
"MyModule",
|
41
|
+
undefined,
|
42
|
+
undefined,
|
43
|
+
[],
|
44
|
+
),
|
45
|
+
];
|
46
|
+
}
|
47
|
+
|
48
|
+
const $import = (file: string) => (instance: string) =>
|
49
|
+
ts.factory.createImportDeclaration(
|
50
|
+
undefined,
|
51
|
+
ts.factory.createImportClause(
|
52
|
+
false,
|
53
|
+
undefined,
|
54
|
+
ts.factory.createNamedImports([
|
55
|
+
ts.factory.createImportSpecifier(
|
56
|
+
false,
|
57
|
+
undefined,
|
58
|
+
ts.factory.createIdentifier(instance),
|
59
|
+
),
|
60
|
+
]),
|
61
|
+
),
|
62
|
+
ts.factory.createStringLiteral(file),
|
63
|
+
);
|
@@ -1,8 +1,8 @@
|
|
1
|
-
import { IMigrateRoute } from "./IMigrateRoute";
|
2
|
-
|
3
|
-
export interface IMigrateController {
|
4
|
-
name: string;
|
5
|
-
path: string;
|
6
|
-
location: string;
|
7
|
-
routes: IMigrateRoute[];
|
8
|
-
}
|
1
|
+
import { IMigrateRoute } from "./IMigrateRoute";
|
2
|
+
|
3
|
+
export interface IMigrateController {
|
4
|
+
name: string;
|
5
|
+
path: string;
|
6
|
+
location: string;
|
7
|
+
routes: IMigrateRoute[];
|
8
|
+
}
|
@@ -1,5 +1,5 @@
|
|
1
|
-
export interface IMigrateFile {
|
2
|
-
location: string;
|
3
|
-
file: string;
|
4
|
-
content: string;
|
5
|
-
}
|
1
|
+
export interface IMigrateFile {
|
2
|
+
location: string;
|
3
|
+
file: string;
|
4
|
+
content: string;
|
5
|
+
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
export interface IMigrateSchema {
|
2
|
-
name: string;
|
3
|
-
children: IMigrateSchema[];
|
4
|
-
}
|
1
|
+
export interface IMigrateSchema {
|
2
|
+
name: string;
|
3
|
+
children: IMigrateSchema[];
|
4
|
+
}
|
package/src/utils/FilePrinter.ts
CHANGED
@@ -1,36 +1,36 @@
|
|
1
|
-
import ts from "typescript";
|
2
|
-
|
3
|
-
export namespace FilePrinter {
|
4
|
-
export const description = <Node extends ts.Node>(
|
5
|
-
node: Node,
|
6
|
-
comment: string,
|
7
|
-
): Node => {
|
8
|
-
if (comment.length === 0) return node;
|
9
|
-
ts.addSyntheticLeadingComment(
|
10
|
-
node,
|
11
|
-
ts.SyntaxKind.MultiLineCommentTrivia,
|
12
|
-
["*", ...comment.split("\n").map((str) => ` * ${str}`), ""].join("\n"),
|
13
|
-
true,
|
14
|
-
);
|
15
|
-
return node;
|
16
|
-
};
|
17
|
-
|
18
|
-
export const newLine = () =>
|
19
|
-
ts.factory.createExpressionStatement(ts.factory.createIdentifier("\n"));
|
20
|
-
|
21
|
-
export const write = (props: {
|
22
|
-
statements: ts.Statement[];
|
23
|
-
top?: string;
|
24
|
-
}): string => {
|
25
|
-
const script: string = ts
|
26
|
-
.createPrinter()
|
27
|
-
.printFile(
|
28
|
-
ts.factory.createSourceFile(
|
29
|
-
props.statements,
|
30
|
-
ts.factory.createToken(ts.SyntaxKind.EndOfFileToken),
|
31
|
-
ts.NodeFlags.None,
|
32
|
-
),
|
33
|
-
);
|
34
|
-
return (props.top ?? "") + script;
|
35
|
-
};
|
36
|
-
}
|
1
|
+
import ts from "typescript";
|
2
|
+
|
3
|
+
export namespace FilePrinter {
|
4
|
+
export const description = <Node extends ts.Node>(
|
5
|
+
node: Node,
|
6
|
+
comment: string,
|
7
|
+
): Node => {
|
8
|
+
if (comment.length === 0) return node;
|
9
|
+
ts.addSyntheticLeadingComment(
|
10
|
+
node,
|
11
|
+
ts.SyntaxKind.MultiLineCommentTrivia,
|
12
|
+
["*", ...comment.split("\n").map((str) => ` * ${str}`), ""].join("\n"),
|
13
|
+
true,
|
14
|
+
);
|
15
|
+
return node;
|
16
|
+
};
|
17
|
+
|
18
|
+
export const newLine = () =>
|
19
|
+
ts.factory.createExpressionStatement(ts.factory.createIdentifier("\n"));
|
20
|
+
|
21
|
+
export const write = (props: {
|
22
|
+
statements: ts.Statement[];
|
23
|
+
top?: string;
|
24
|
+
}): string => {
|
25
|
+
const script: string = ts
|
26
|
+
.createPrinter()
|
27
|
+
.printFile(
|
28
|
+
ts.factory.createSourceFile(
|
29
|
+
props.statements,
|
30
|
+
ts.factory.createToken(ts.SyntaxKind.EndOfFileToken),
|
31
|
+
ts.NodeFlags.None,
|
32
|
+
),
|
33
|
+
);
|
34
|
+
return (props.top ?? "") + script;
|
35
|
+
};
|
36
|
+
}
|
package/src/utils/MapUtil.ts
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
export namespace MapUtil {
|
2
|
-
export const take =
|
3
|
-
<Key, T>(dict: Map<Key, T>) =>
|
4
|
-
(key: Key) =>
|
5
|
-
(generator: () => T): T => {
|
6
|
-
const oldbie: T | undefined = dict.get(key);
|
7
|
-
if (oldbie) return oldbie;
|
8
|
-
|
9
|
-
const value: T = generator();
|
10
|
-
dict.set(key, value);
|
11
|
-
return value;
|
12
|
-
};
|
13
|
-
}
|
1
|
+
export namespace MapUtil {
|
2
|
+
export const take =
|
3
|
+
<Key, T>(dict: Map<Key, T>) =>
|
4
|
+
(key: Key) =>
|
5
|
+
(generator: () => T): T => {
|
6
|
+
const oldbie: T | undefined = dict.get(key);
|
7
|
+
if (oldbie) return oldbie;
|
8
|
+
|
9
|
+
const value: T = generator();
|
10
|
+
dict.set(key, value);
|
11
|
+
return value;
|
12
|
+
};
|
13
|
+
}
|
package/src/utils/SetupWizard.ts
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
import cp from "child_process";
|
2
|
-
|
3
|
-
export namespace SetupWizard {
|
4
|
-
export const setup = (output: string) => {
|
5
|
-
execute(output)("npm install");
|
6
|
-
};
|
7
|
-
|
8
|
-
const execute = (cwd: string) => (command: string, fake?: string) => {
|
9
|
-
console.log(fake ?? command);
|
10
|
-
cp.execSync(command, { cwd, stdio: "inherit" });
|
11
|
-
};
|
12
|
-
}
|
1
|
+
import cp from "child_process";
|
2
|
+
|
3
|
+
export namespace SetupWizard {
|
4
|
+
export const setup = (output: string) => {
|
5
|
+
execute(output)("npm install");
|
6
|
+
};
|
7
|
+
|
8
|
+
const execute = (cwd: string) => (command: string, fake?: string) => {
|
9
|
+
console.log(fake ?? command);
|
10
|
+
cp.execSync(command, { cwd, stdio: "inherit" });
|
11
|
+
};
|
12
|
+
}
|
package/src/utils/StringUtil.ts
CHANGED
@@ -1,60 +1,60 @@
|
|
1
|
-
import { NamingConvention } from "typia/lib/utils/NamingConvention";
|
2
|
-
|
3
|
-
export namespace StringUtil {
|
4
|
-
export const capitalize = (str: string) =>
|
5
|
-
str[0].toUpperCase() + str.slice(1).toLowerCase();
|
6
|
-
|
7
|
-
export const pascal = (path: string) =>
|
8
|
-
splitWithNormalization(path)
|
9
|
-
.filter((str) => str[0] !== "{")
|
10
|
-
.map(NamingConvention.pascal)
|
11
|
-
.join("");
|
12
|
-
|
13
|
-
export const camel = (path: string) =>
|
14
|
-
splitWithNormalization(path)
|
15
|
-
.map((str, i) =>
|
16
|
-
i === 0 ? NamingConvention.camel(str) : NamingConvention.pascal(str),
|
17
|
-
)
|
18
|
-
.join("");
|
19
|
-
|
20
|
-
export const splitWithNormalization = (path: string) =>
|
21
|
-
path
|
22
|
-
.split("/")
|
23
|
-
.map((str) => normalize(str.trim()))
|
24
|
-
.filter((str) => !!str.length);
|
25
|
-
|
26
|
-
export const reJoinWithDecimalParameters = (path: string) =>
|
27
|
-
path
|
28
|
-
.split("/")
|
29
|
-
.filter((str) => !!str.length)
|
30
|
-
.map((str) =>
|
31
|
-
str[0] === "{" && str[str.length - 1] === "}"
|
32
|
-
? `:${str.substring(1, str.length - 1)}`
|
33
|
-
: str,
|
34
|
-
)
|
35
|
-
.join("/");
|
36
|
-
|
37
|
-
export const normalize = (str: string) =>
|
38
|
-
str.split(".").join("_").split("-").join("_");
|
39
|
-
|
40
|
-
export const commonPrefix = (strs: string[]): string => {
|
41
|
-
if (strs.length === 0) return "";
|
42
|
-
|
43
|
-
let prefix = strs[0];
|
44
|
-
for (let i = 1; i < strs.length; i++) {
|
45
|
-
while (strs[i].indexOf(prefix) !== 0) {
|
46
|
-
prefix = prefix.substring(0, prefix.length - 1);
|
47
|
-
if (prefix === "") return "";
|
48
|
-
}
|
49
|
-
}
|
50
|
-
return prefix
|
51
|
-
.split("/")
|
52
|
-
.filter((str) => str[0] !== "{" || str[str.length - 1] === "}")
|
53
|
-
.join("/");
|
54
|
-
};
|
55
|
-
|
56
|
-
export const escapeDuplicate =
|
57
|
-
(keep: string[]) =>
|
58
|
-
(change: string): string =>
|
59
|
-
keep.includes(change) ? escapeDuplicate(keep)(`_${change}`) : change;
|
60
|
-
}
|
1
|
+
import { NamingConvention } from "typia/lib/utils/NamingConvention";
|
2
|
+
|
3
|
+
export namespace StringUtil {
|
4
|
+
export const capitalize = (str: string) =>
|
5
|
+
str[0].toUpperCase() + str.slice(1).toLowerCase();
|
6
|
+
|
7
|
+
export const pascal = (path: string) =>
|
8
|
+
splitWithNormalization(path)
|
9
|
+
.filter((str) => str[0] !== "{")
|
10
|
+
.map(NamingConvention.pascal)
|
11
|
+
.join("");
|
12
|
+
|
13
|
+
export const camel = (path: string) =>
|
14
|
+
splitWithNormalization(path)
|
15
|
+
.map((str, i) =>
|
16
|
+
i === 0 ? NamingConvention.camel(str) : NamingConvention.pascal(str),
|
17
|
+
)
|
18
|
+
.join("");
|
19
|
+
|
20
|
+
export const splitWithNormalization = (path: string) =>
|
21
|
+
path
|
22
|
+
.split("/")
|
23
|
+
.map((str) => normalize(str.trim()))
|
24
|
+
.filter((str) => !!str.length);
|
25
|
+
|
26
|
+
export const reJoinWithDecimalParameters = (path: string) =>
|
27
|
+
path
|
28
|
+
.split("/")
|
29
|
+
.filter((str) => !!str.length)
|
30
|
+
.map((str) =>
|
31
|
+
str[0] === "{" && str[str.length - 1] === "}"
|
32
|
+
? `:${str.substring(1, str.length - 1)}`
|
33
|
+
: str,
|
34
|
+
)
|
35
|
+
.join("/");
|
36
|
+
|
37
|
+
export const normalize = (str: string) =>
|
38
|
+
str.split(".").join("_").split("-").join("_");
|
39
|
+
|
40
|
+
export const commonPrefix = (strs: string[]): string => {
|
41
|
+
if (strs.length === 0) return "";
|
42
|
+
|
43
|
+
let prefix = strs[0];
|
44
|
+
for (let i = 1; i < strs.length; i++) {
|
45
|
+
while (strs[i].indexOf(prefix) !== 0) {
|
46
|
+
prefix = prefix.substring(0, prefix.length - 1);
|
47
|
+
if (prefix === "") return "";
|
48
|
+
}
|
49
|
+
}
|
50
|
+
return prefix
|
51
|
+
.split("/")
|
52
|
+
.filter((str) => str[0] !== "{" || str[str.length - 1] === "}")
|
53
|
+
.join("/");
|
54
|
+
};
|
55
|
+
|
56
|
+
export const escapeDuplicate =
|
57
|
+
(keep: string[]) =>
|
58
|
+
(change: string): string =>
|
59
|
+
keep.includes(change) ? escapeDuplicate(keep)(`_${change}`) : change;
|
60
|
+
}
|