swagger-typescript-api 11.0.0--alpha → 11.0.0--alpha-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.
- package/cli/constants.js +10 -0
- package/cli/execute.js +136 -0
- package/cli/index.d.ts +35 -0
- package/cli/index.js +69 -0
- package/cli/operations/display-help.js +133 -0
- package/cli/operations/display-version.js +5 -0
- package/cli/parse-args.js +26 -0
- package/cli/process-option.js +69 -0
- package/package.json +2 -1
- package/src/util/file-system.js +2 -2
package/cli/constants.js
ADDED
package/cli/execute.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
const _ = require("lodash");
|
|
2
|
+
const { root_command, skip_command } = require("./constants");
|
|
3
|
+
const { parseArgs } = require("./parse-args");
|
|
4
|
+
const didyoumean = require("didyoumean");
|
|
5
|
+
|
|
6
|
+
const execute = (params, commands, instance) => {
|
|
7
|
+
const args = parseArgs(params.args, params.from);
|
|
8
|
+
|
|
9
|
+
return new Promise((resolve, reject) => {
|
|
10
|
+
const { command, usageOptions, error } = processArgs(commands, args);
|
|
11
|
+
|
|
12
|
+
if (error) {
|
|
13
|
+
reject(new Error(error));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (!usageOptions.length && command.name === root_command) {
|
|
17
|
+
usageOptions.push(command.options.find((option) => option.flags.name === "help"));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const operationOptions = usageOptions.filter((option) => option.operation);
|
|
21
|
+
if (operationOptions.length) {
|
|
22
|
+
operationOptions[0].operation();
|
|
23
|
+
resolve({
|
|
24
|
+
command: skip_command,
|
|
25
|
+
options: {},
|
|
26
|
+
});
|
|
27
|
+
return;
|
|
28
|
+
} else {
|
|
29
|
+
let error = "";
|
|
30
|
+
|
|
31
|
+
const processUserOptionData = (data, option) => {
|
|
32
|
+
if (!data.length && !option.flags.value) {
|
|
33
|
+
return !option.flags.isNoFlag;
|
|
34
|
+
}
|
|
35
|
+
if (option.flags.value) {
|
|
36
|
+
if (option.flags.value.variadic) {
|
|
37
|
+
return data.reduce((acc, d) => {
|
|
38
|
+
acc.push(...d.split(",").map(option.flags.value.formatter));
|
|
39
|
+
return acc;
|
|
40
|
+
}, []);
|
|
41
|
+
} else {
|
|
42
|
+
return option.flags.value.formatter(data[0] || option.default);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return option.default;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const parsedOptionsObject = command.options.reduce((acc, option) => {
|
|
50
|
+
if (error) return acc;
|
|
51
|
+
|
|
52
|
+
const userOption = usageOptions.find((o) => o.flags.name === option.flags.name);
|
|
53
|
+
|
|
54
|
+
if (!userOption && option.required) {
|
|
55
|
+
error = `required option '${option.flags.raw}' not specified`;
|
|
56
|
+
return acc;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (userOption) {
|
|
60
|
+
acc[option.flags.name] = processUserOptionData(userOption.$data, option);
|
|
61
|
+
} else {
|
|
62
|
+
acc[option.flags.name] = option.default;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return acc;
|
|
66
|
+
}, {});
|
|
67
|
+
|
|
68
|
+
if (error) {
|
|
69
|
+
reject(new Error(error));
|
|
70
|
+
} else {
|
|
71
|
+
resolve({
|
|
72
|
+
command: command.name === root_command ? null : command.name,
|
|
73
|
+
options: parsedOptionsObject,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const processArgs = (commands, args) => {
|
|
81
|
+
let command = null;
|
|
82
|
+
let usageOptions = [];
|
|
83
|
+
let walkingOption = null;
|
|
84
|
+
let error = "";
|
|
85
|
+
|
|
86
|
+
let allFlagKeys = [];
|
|
87
|
+
|
|
88
|
+
_.forEach(args, (arg, i) => {
|
|
89
|
+
if (error) return;
|
|
90
|
+
|
|
91
|
+
if (i === 0) {
|
|
92
|
+
command = commands[arg] || commands[root_command];
|
|
93
|
+
allFlagKeys = command.options.reduce((acc, option) => [...acc, ...option.flags.keys], []);
|
|
94
|
+
}
|
|
95
|
+
if (arg.startsWith("-")) {
|
|
96
|
+
const option = command.options.find((option) => option.flags.keys.includes(arg));
|
|
97
|
+
|
|
98
|
+
if (!option) {
|
|
99
|
+
error = `unknown option ${arg}\n(Did you mean ${didyoumean(arg, allFlagKeys)} ?)`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (option) {
|
|
103
|
+
if (walkingOption && walkingOption.flags.name === option.flags.name) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const existedOption = usageOptions.find((o) => o.flags.name === option.flags.name);
|
|
107
|
+
if (existedOption) {
|
|
108
|
+
walkingOption = existedOption;
|
|
109
|
+
} else {
|
|
110
|
+
walkingOption = {
|
|
111
|
+
...option,
|
|
112
|
+
$data: [],
|
|
113
|
+
};
|
|
114
|
+
usageOptions.push(walkingOption);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (walkingOption) {
|
|
122
|
+
walkingOption.$data.push(arg);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
command = command || commands[root_command];
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
command,
|
|
129
|
+
usageOptions,
|
|
130
|
+
error,
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
module.exports = {
|
|
135
|
+
execute,
|
|
136
|
+
};
|
package/cli/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { skip_command } from "./constants";
|
|
2
|
+
|
|
3
|
+
type CliStructOption = {
|
|
4
|
+
flags?: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
default?: unknown;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type CliStruct = {
|
|
10
|
+
inherited?: string | null;
|
|
11
|
+
name?: string;
|
|
12
|
+
alias?: string;
|
|
13
|
+
version?: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
options: CliStructOption[];
|
|
16
|
+
commands?: CliStruct[];
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
type ExecuteOptions = {
|
|
20
|
+
args: string[];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type ExecuteOutput = {
|
|
24
|
+
command: null | string;
|
|
25
|
+
options: Record<string, any>;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type CliInstance = {
|
|
29
|
+
addCommand: (struct: CliStruct) => CliInstance;
|
|
30
|
+
execute: (options: ExecuteOptions) => Promise<ExecuteOutput>;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
type Cli = <S extends Omit<CliStruct, "inherited">>(struct: S) => CliInstance;
|
|
34
|
+
|
|
35
|
+
export declare const cli: Cli;
|
package/cli/index.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const _ = require("lodash");
|
|
2
|
+
const { reservedOptions, root_command } = require("./constants");
|
|
3
|
+
const { processOption } = require("./process-option");
|
|
4
|
+
const { execute } = require("./execute");
|
|
5
|
+
const { displayHelp } = require("./operations/display-help");
|
|
6
|
+
const { displayVersion } = require("./operations/display-version");
|
|
7
|
+
|
|
8
|
+
const cli = (input) => {
|
|
9
|
+
const commands = {};
|
|
10
|
+
|
|
11
|
+
const addCommand = (command) => {
|
|
12
|
+
commands[command.name] = {
|
|
13
|
+
name: command.name,
|
|
14
|
+
description: `${command.description || ""}`,
|
|
15
|
+
options: _.compact(_.map(command.options, processOption)),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
return instance;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const instance = {
|
|
22
|
+
commands,
|
|
23
|
+
input,
|
|
24
|
+
addCommand,
|
|
25
|
+
execute: (params) => execute(params, commands, instance),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
addCommand({
|
|
29
|
+
name: root_command,
|
|
30
|
+
options: [],
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
_.forEach(input.options, (option) => {
|
|
34
|
+
const processed = processOption(option);
|
|
35
|
+
|
|
36
|
+
if (!processed) return;
|
|
37
|
+
|
|
38
|
+
if (reservedOptions.includes(processed.name)) {
|
|
39
|
+
console.warn("reserved option", processed.name);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
commands[root_command].options.push(processed);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
commands[root_command].options.unshift(
|
|
47
|
+
processOption({
|
|
48
|
+
flags: "-v, --version",
|
|
49
|
+
description: "output the current version",
|
|
50
|
+
operation: () => displayVersion(instance),
|
|
51
|
+
}),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
commands[root_command].options.push(
|
|
55
|
+
processOption({
|
|
56
|
+
flags: "-h, --help",
|
|
57
|
+
description: "display help for command",
|
|
58
|
+
operation: () => displayHelp(commands, instance),
|
|
59
|
+
}),
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
_.forEach(input.commands, addCommand);
|
|
63
|
+
|
|
64
|
+
return instance;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
module.exports = {
|
|
68
|
+
cli,
|
|
69
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
const _ = require("lodash");
|
|
2
|
+
const { root_command } = require("../constants");
|
|
3
|
+
|
|
4
|
+
const displayHelp = (commands, instance) => {
|
|
5
|
+
const generateOptionsOutput = (options) =>
|
|
6
|
+
options.reduce(
|
|
7
|
+
(acc, option) => {
|
|
8
|
+
const flags = `${option.flags.keys.join(", ")}${option.flags.value?.raw ? ` ${option.flags.value?.raw}` : ""}`;
|
|
9
|
+
const description = `${option.description || ""}${
|
|
10
|
+
option.default === undefined || (option.flags.isNoFlag && option.default === true)
|
|
11
|
+
? ""
|
|
12
|
+
: ` (default: ${typeof option.default === "string" ? `"${option.default}"` : option.default})`
|
|
13
|
+
}`;
|
|
14
|
+
|
|
15
|
+
if (flags.length > acc.maxLength) {
|
|
16
|
+
acc.maxLength = flags.length;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
acc.options.push({
|
|
20
|
+
flags,
|
|
21
|
+
description,
|
|
22
|
+
});
|
|
23
|
+
return acc;
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
options: [],
|
|
27
|
+
maxLength: 0,
|
|
28
|
+
},
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const { options, maxLength: maxOptionLength } = generateOptionsOutput(commands[root_command].options);
|
|
32
|
+
|
|
33
|
+
const { commands: commandLabels, maxLength: maxCommandLength } = _.filter(
|
|
34
|
+
commands,
|
|
35
|
+
(command) => command.name !== root_command,
|
|
36
|
+
).reduce(
|
|
37
|
+
(acc, command) => {
|
|
38
|
+
const options = generateOptionsOutput(command.options);
|
|
39
|
+
const name = `${command.name}${options.length ? " [options]" : ""}`;
|
|
40
|
+
const description = command.description;
|
|
41
|
+
|
|
42
|
+
const maxLength = Math.max(name.length, options.maxLength);
|
|
43
|
+
if (maxLength > acc.maxLength) {
|
|
44
|
+
acc.maxLength = maxLength;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
acc.commands.push({
|
|
48
|
+
description,
|
|
49
|
+
name,
|
|
50
|
+
options,
|
|
51
|
+
});
|
|
52
|
+
return acc;
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
commands: [],
|
|
56
|
+
maxLength: maxOptionLength,
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const generateOptionsTextOutput = (options, maxLength, spaces) =>
|
|
61
|
+
options
|
|
62
|
+
.map((option) => {
|
|
63
|
+
const spacesText = Array(spaces).fill(" ").join("");
|
|
64
|
+
const leftStr = `${spacesText}${option.flags.padEnd(maxLength, " ")} `;
|
|
65
|
+
const leftStrFiller = Array(leftStr.length).fill(" ").join("");
|
|
66
|
+
const descriptionLines = option.description.split("\n");
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
leftStr +
|
|
70
|
+
descriptionLines
|
|
71
|
+
.map((line, i) => {
|
|
72
|
+
if (i === 0) {
|
|
73
|
+
return line;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return `\n${leftStrFiller}${line}`;
|
|
77
|
+
})
|
|
78
|
+
.join("")
|
|
79
|
+
);
|
|
80
|
+
})
|
|
81
|
+
.join("\n");
|
|
82
|
+
|
|
83
|
+
const optionsOutput = generateOptionsTextOutput(options, maxOptionLength, 2);
|
|
84
|
+
|
|
85
|
+
const commandsOutput = commandLabels
|
|
86
|
+
.map((commandLabel) => {
|
|
87
|
+
const leftStr = ` ${commandLabel.name.padEnd(maxCommandLength, " ")} `;
|
|
88
|
+
const leftStrFiller = Array(leftStr.length).fill(" ").join("");
|
|
89
|
+
const descriptionLines = commandLabel.description.split("\n");
|
|
90
|
+
const optionsTextOutput = generateOptionsTextOutput(commandLabel.options.options, maxCommandLength, 4);
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
leftStr +
|
|
94
|
+
descriptionLines
|
|
95
|
+
.map((line, i) => {
|
|
96
|
+
if (i === 0) {
|
|
97
|
+
return line;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return `\n${leftStrFiller}${line}`;
|
|
101
|
+
})
|
|
102
|
+
.join("") +
|
|
103
|
+
(optionsTextOutput.length ? `\n${optionsTextOutput}` : "")
|
|
104
|
+
);
|
|
105
|
+
})
|
|
106
|
+
.join("\n");
|
|
107
|
+
|
|
108
|
+
const outputTest = [
|
|
109
|
+
optionsOutput &&
|
|
110
|
+
`Options:
|
|
111
|
+
${optionsOutput}`,
|
|
112
|
+
commandsOutput &&
|
|
113
|
+
`Commands:
|
|
114
|
+
${commandsOutput}`,
|
|
115
|
+
]
|
|
116
|
+
.filter(Boolean)
|
|
117
|
+
.join("\n\n");
|
|
118
|
+
|
|
119
|
+
console.log(`Usage: ${[instance.input.name, instance.input.alias].filter(Boolean).join("|")}${
|
|
120
|
+
optionsOutput ? " [options]" : ""
|
|
121
|
+
}${commandsOutput ? " [command]" : ""}
|
|
122
|
+
${
|
|
123
|
+
instance.input.description &&
|
|
124
|
+
`
|
|
125
|
+
${instance.input.description}`
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
${outputTest}`);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
module.exports = {
|
|
132
|
+
displayHelp,
|
|
133
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const parseArgs = (args, type) => {
|
|
2
|
+
if (args == null || !Array.isArray(args)) {
|
|
3
|
+
throw "args should be array";
|
|
4
|
+
}
|
|
5
|
+
const argsCopy = args.slice();
|
|
6
|
+
|
|
7
|
+
switch (type) {
|
|
8
|
+
case "electron": {
|
|
9
|
+
if (process.defaultApp) {
|
|
10
|
+
return argsCopy.slice(2);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return argsCopy.slice(1);
|
|
14
|
+
}
|
|
15
|
+
case "user": {
|
|
16
|
+
return argsCopy;
|
|
17
|
+
}
|
|
18
|
+
default: {
|
|
19
|
+
return argsCopy.slice(2);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
parseArgs,
|
|
26
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const _ = require("lodash");
|
|
2
|
+
|
|
3
|
+
const optionFormatters = {
|
|
4
|
+
number: (str) => +str,
|
|
5
|
+
numeric: (str) => +str,
|
|
6
|
+
str: (str) => `${str}`,
|
|
7
|
+
string: (str) => `${str}`,
|
|
8
|
+
bool: (str) => !!str,
|
|
9
|
+
boolean: (str) => !!str,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const processFlags = (flags) => {
|
|
13
|
+
let name = null;
|
|
14
|
+
const keys = [];
|
|
15
|
+
let value = null;
|
|
16
|
+
const isNoFlag = flags.includes("--no-");
|
|
17
|
+
|
|
18
|
+
_.compact(_.split(flags, " ").map((str) => str.replace(/\,/g, ""))).forEach((str) => {
|
|
19
|
+
if (str.startsWith("-")) {
|
|
20
|
+
keys.push(str);
|
|
21
|
+
} else if (value === null) {
|
|
22
|
+
if (str.startsWith("{") || str.startsWith("[") || str.startsWith("<")) {
|
|
23
|
+
const rawValue = str.replace(/[\{\[\<\>\}\]\.]/g, "");
|
|
24
|
+
const variadic = str.includes("...");
|
|
25
|
+
value = {
|
|
26
|
+
raw: str,
|
|
27
|
+
variadic,
|
|
28
|
+
name: rawValue,
|
|
29
|
+
formatter: optionFormatters[rawValue] || optionFormatters.string,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const longestKey = keys.slice().sort((a, b) => b.length - a.length)[0];
|
|
36
|
+
|
|
37
|
+
if (!_.isEmpty(longestKey)) {
|
|
38
|
+
name = _.camelCase((isNoFlag ? longestKey.replace("--no-", "") : longestKey).replace(/(--?)/, ""));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
isNoFlag,
|
|
43
|
+
raw: flags,
|
|
44
|
+
name,
|
|
45
|
+
keys,
|
|
46
|
+
value,
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const processOption = (option) => {
|
|
51
|
+
const processedFlags = processFlags(option.flags);
|
|
52
|
+
|
|
53
|
+
if (!processedFlags.name) {
|
|
54
|
+
console.warn("invalid option", option);
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
required: !!option.required,
|
|
60
|
+
description: `${option.description || ""}`,
|
|
61
|
+
default: option.default,
|
|
62
|
+
flags: processedFlags,
|
|
63
|
+
operation: option.operation,
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
module.exports = {
|
|
68
|
+
processOption,
|
|
69
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "swagger-typescript-api",
|
|
3
|
-
"version": "11.0.0--alpha",
|
|
3
|
+
"version": "11.0.0--alpha-2",
|
|
4
4
|
"description": "Generate typescript/javascript api from swagger schema",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"cli:json": "node index.js -r -d -p ./swagger-test-cli.json -n swagger-test-cli.ts",
|
|
@@ -108,6 +108,7 @@
|
|
|
108
108
|
"index.js",
|
|
109
109
|
"index.d.ts",
|
|
110
110
|
"templates",
|
|
111
|
+
"cli",
|
|
111
112
|
"LICENSE"
|
|
112
113
|
],
|
|
113
114
|
"bugs": {
|