cli-kiss 0.0.3 → 0.0.4
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/dist/index.d.ts +42 -30
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/Command.ts +22 -24
- package/src/lib/Execution.ts +8 -11
- package/src/lib/Grid.ts +6 -2
- package/src/lib/Run.ts +5 -6
- package/src/lib/Type.ts +27 -2
- package/src/lib/Typo.ts +16 -7
- package/src/lib/Usage.ts +63 -59
- package/tests/{unit.command.run.ts → unit.command.runArgv.ts} +14 -13
- package/tests/unit.command.usage.ts +77 -71
package/src/lib/Command.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { OptionUsage } from "./Option";
|
|
|
4
4
|
import { ReaderTokenizer } from "./Reader";
|
|
5
5
|
|
|
6
6
|
export type Command<Context, Result> = {
|
|
7
|
-
|
|
7
|
+
getDescription(): string | undefined;
|
|
8
8
|
prepareRunner(
|
|
9
9
|
readerTokenizer: ReaderTokenizer,
|
|
10
10
|
): CommandRunner<Context, Result>;
|
|
@@ -17,28 +17,26 @@ export type CommandRunner<Context, Result> = {
|
|
|
17
17
|
|
|
18
18
|
export type CommandUsage = {
|
|
19
19
|
breadcrumbs: Array<CommandUsageBreadcrumb>;
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
description: string;
|
|
21
|
+
details: Array<string> | undefined;
|
|
22
22
|
options: Array<OptionUsage>;
|
|
23
23
|
arguments: Array<ArgumentUsage>;
|
|
24
|
-
subcommands: Array<{ name: string;
|
|
24
|
+
subcommands: Array<{ name: string; description: string | undefined }>;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
export type CommandUsageBreadcrumb = {
|
|
28
|
-
kind: "command" | "argument";
|
|
29
|
-
value: string;
|
|
30
|
-
};
|
|
27
|
+
export type CommandUsageBreadcrumb = { argument: string } | { command: string };
|
|
31
28
|
|
|
32
29
|
export function command<Context, Result>(
|
|
33
30
|
metadata: {
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
description: string;
|
|
32
|
+
details?: Array<string>;
|
|
33
|
+
// TODO - examples ?
|
|
36
34
|
},
|
|
37
35
|
execution: Execution<Context, Result>,
|
|
38
36
|
): Command<Context, Result> {
|
|
39
37
|
return {
|
|
40
|
-
|
|
41
|
-
return metadata.
|
|
38
|
+
getDescription() {
|
|
39
|
+
return metadata.description;
|
|
42
40
|
},
|
|
43
41
|
prepareRunner(readerTokenizer: ReaderTokenizer) {
|
|
44
42
|
function computeUsage(): CommandUsage {
|
|
@@ -47,8 +45,8 @@ export function command<Context, Result>(
|
|
|
47
45
|
breadcrumbs: executionUsage.arguments.map((argument) =>
|
|
48
46
|
breadcrumbArgument(argument.label),
|
|
49
47
|
),
|
|
50
|
-
title: metadata.title,
|
|
51
48
|
description: metadata.description,
|
|
49
|
+
details: metadata.details,
|
|
52
50
|
options: executionUsage.options,
|
|
53
51
|
arguments: executionUsage.arguments,
|
|
54
52
|
subcommands: [],
|
|
@@ -81,15 +79,15 @@ export function command<Context, Result>(
|
|
|
81
79
|
|
|
82
80
|
export function commandWithSubcommands<Context, Payload, Result>(
|
|
83
81
|
metadata: {
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
description: string;
|
|
83
|
+
details?: Array<string>;
|
|
86
84
|
},
|
|
87
85
|
execution: Execution<Context, Payload>,
|
|
88
86
|
subcommands: { [subcommand: Lowercase<string>]: Command<Payload, Result> },
|
|
89
87
|
): Command<Context, Result> {
|
|
90
88
|
return {
|
|
91
|
-
|
|
92
|
-
return metadata.
|
|
89
|
+
getDescription() {
|
|
90
|
+
return metadata.description;
|
|
93
91
|
},
|
|
94
92
|
prepareRunner(readerTokenizer: ReaderTokenizer) {
|
|
95
93
|
try {
|
|
@@ -114,8 +112,8 @@ export function commandWithSubcommands<Context, Payload, Result>(
|
|
|
114
112
|
.map((argument) => breadcrumbArgument(argument.label))
|
|
115
113
|
.concat([breadcrumbCommand(subcommandName)])
|
|
116
114
|
.concat(subcommandUsage.breadcrumbs),
|
|
117
|
-
title: subcommandUsage.title,
|
|
118
115
|
description: subcommandUsage.description,
|
|
116
|
+
details: subcommandUsage.details,
|
|
119
117
|
options: executionUsage.options.concat(subcommandUsage.options),
|
|
120
118
|
arguments: executionUsage.arguments.concat(
|
|
121
119
|
subcommandUsage.arguments,
|
|
@@ -136,14 +134,14 @@ export function commandWithSubcommands<Context, Payload, Result>(
|
|
|
136
134
|
breadcrumbs: executionUsage.arguments
|
|
137
135
|
.map((argument) => breadcrumbArgument(argument.label))
|
|
138
136
|
.concat([breadcrumbCommand("<SUBCOMMAND>")]),
|
|
139
|
-
title: metadata.title,
|
|
140
137
|
description: metadata.description,
|
|
138
|
+
details: metadata.details,
|
|
141
139
|
options: executionUsage.options,
|
|
142
140
|
arguments: executionUsage.arguments,
|
|
143
141
|
subcommands: Object.entries(subcommands).map(
|
|
144
142
|
([name, subcommand]) => ({
|
|
145
143
|
name,
|
|
146
|
-
|
|
144
|
+
description: subcommand.getDescription(),
|
|
147
145
|
}),
|
|
148
146
|
),
|
|
149
147
|
};
|
|
@@ -157,10 +155,10 @@ export function commandWithSubcommands<Context, Payload, Result>(
|
|
|
157
155
|
};
|
|
158
156
|
}
|
|
159
157
|
|
|
160
|
-
function breadcrumbArgument(
|
|
161
|
-
return {
|
|
158
|
+
function breadcrumbArgument(value: string): CommandUsageBreadcrumb {
|
|
159
|
+
return { argument: value };
|
|
162
160
|
}
|
|
163
161
|
|
|
164
|
-
function breadcrumbCommand(
|
|
165
|
-
return {
|
|
162
|
+
function breadcrumbCommand(value: string): CommandUsageBreadcrumb {
|
|
163
|
+
return { command: value };
|
|
166
164
|
}
|
package/src/lib/Execution.ts
CHANGED
|
@@ -26,21 +26,18 @@ export type ExecutionUsage = {
|
|
|
26
26
|
export function execution<
|
|
27
27
|
Context,
|
|
28
28
|
Result,
|
|
29
|
-
Options extends { [option: string]:
|
|
30
|
-
const Arguments extends Array<
|
|
29
|
+
Options extends { [option: string]: any },
|
|
30
|
+
const Arguments extends Array<any>,
|
|
31
31
|
>(
|
|
32
|
-
inputs: {
|
|
32
|
+
inputs: {
|
|
33
|
+
options: { [K in keyof Options]: Option<Options[K]> };
|
|
34
|
+
arguments: { [K in keyof Arguments]: Argument<Arguments[K]> };
|
|
35
|
+
},
|
|
33
36
|
handler: (
|
|
34
37
|
context: Context,
|
|
35
38
|
inputs: {
|
|
36
|
-
options:
|
|
37
|
-
|
|
38
|
-
ReturnType<Options[K]["prepareConsumer"]>
|
|
39
|
-
>;
|
|
40
|
-
};
|
|
41
|
-
arguments: {
|
|
42
|
-
[K in keyof Arguments]: ReturnType<Arguments[K]["consumeValue"]>;
|
|
43
|
-
};
|
|
39
|
+
options: Options;
|
|
40
|
+
arguments: Arguments;
|
|
44
41
|
},
|
|
45
42
|
) => Promise<Result>,
|
|
46
43
|
): Execution<Context, Result> {
|
package/src/lib/Grid.ts
CHANGED
|
@@ -4,7 +4,11 @@ export type Grid = Array<GridRow>;
|
|
|
4
4
|
export type GridRow = Array<GridCell>;
|
|
5
5
|
export type GridCell = Array<TypoText>;
|
|
6
6
|
|
|
7
|
-
export function gridToPrintableLines(
|
|
7
|
+
export function gridToPrintableLines(
|
|
8
|
+
grid: Grid,
|
|
9
|
+
typoSupport: TypoSupport,
|
|
10
|
+
delimiter: string = "",
|
|
11
|
+
): Array<string> {
|
|
8
12
|
const lines = new Array<string>();
|
|
9
13
|
const gridWidths = new Array<number>();
|
|
10
14
|
for (const gridRow of grid) {
|
|
@@ -42,7 +46,7 @@ export function gridToPrintableLines(grid: Grid, typoSupport: TypoSupport) {
|
|
|
42
46
|
lineColumns.push(parts.join(""));
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
|
-
lines.push(lineColumns.join(
|
|
49
|
+
lines.push(lineColumns.join(delimiter));
|
|
46
50
|
}
|
|
47
51
|
return lines;
|
|
48
52
|
}
|
package/src/lib/Run.ts
CHANGED
|
@@ -3,18 +3,17 @@ import { ReaderTokenizer } from "./Reader";
|
|
|
3
3
|
import { typoInferSupport } from "./Typo";
|
|
4
4
|
import { usageToPrintableLines } from "./Usage";
|
|
5
5
|
|
|
6
|
-
export async function
|
|
7
|
-
|
|
6
|
+
export async function runCommand<Context, Result>(
|
|
7
|
+
cliName: Lowercase<string>,
|
|
8
|
+
cliArgs: Array<string>,
|
|
8
9
|
context: Context,
|
|
9
10
|
command: Command<Context, Result>,
|
|
10
11
|
cliInfo?: {
|
|
11
|
-
name?: Lowercase<string>;
|
|
12
12
|
version?: string;
|
|
13
13
|
helpOnError?: boolean;
|
|
14
14
|
},
|
|
15
15
|
): Promise<Result> {
|
|
16
|
-
const
|
|
17
|
-
const readerTokenizer = new ReaderTokenizer(argv.slice(2));
|
|
16
|
+
const readerTokenizer = new ReaderTokenizer(cliArgs);
|
|
18
17
|
if (cliInfo?.version) {
|
|
19
18
|
readerTokenizer.registerFlag({
|
|
20
19
|
key: "version",
|
|
@@ -65,7 +64,7 @@ export async function runWithArgv<Context, Result>(
|
|
|
65
64
|
}).join("\n"),
|
|
66
65
|
);
|
|
67
66
|
}
|
|
68
|
-
console.error(error);
|
|
67
|
+
console.error(error); // TODO - better, prettier errors
|
|
69
68
|
process.exit(1);
|
|
70
69
|
}
|
|
71
70
|
} catch (error) {
|
package/src/lib/Type.ts
CHANGED
|
@@ -48,10 +48,35 @@ export const typeBigInt: Type<bigint> = {
|
|
|
48
48
|
},
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
-
export function
|
|
51
|
+
export function typeCommaTuple<
|
|
52
|
+
const Elements extends Array<any>,
|
|
53
|
+
>(elementTypes: {
|
|
54
|
+
[K in keyof Elements]: Type<Elements[K]>;
|
|
55
|
+
}): Type<Elements> {
|
|
56
|
+
return {
|
|
57
|
+
label: elementTypes
|
|
58
|
+
.map((elementType) => elementType.label)
|
|
59
|
+
.join(",") as Uppercase<string>,
|
|
60
|
+
decoder(value: string) {
|
|
61
|
+
const parts = value.split(",", elementTypes.length);
|
|
62
|
+
if (parts.length !== elementTypes.length) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`Invalid tuple value: ${value}, expected ${elementTypes.length} parts`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return parts.map((part, index) =>
|
|
68
|
+
elementTypes[index]!.decoder(part),
|
|
69
|
+
) as Elements;
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function typeCommaList<Value>(
|
|
75
|
+
elementType: Type<Value>,
|
|
76
|
+
): Type<Array<Value>> {
|
|
52
77
|
return {
|
|
53
78
|
label:
|
|
54
|
-
`${elementType.label}[
|
|
79
|
+
`${elementType.label}[,${elementType.label}...]` as Uppercase<string>,
|
|
55
80
|
decoder(value: string) {
|
|
56
81
|
return value.split(",").map(elementType.decoder);
|
|
57
82
|
},
|
package/src/lib/Typo.ts
CHANGED
|
@@ -63,11 +63,20 @@ export function typoInferSupport(): TypoSupport {
|
|
|
63
63
|
const resetCode = "\x1b[0m";
|
|
64
64
|
const boldCode = "\x1b[1m";
|
|
65
65
|
const colorCodes = {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
darkBlack: "\x1b[30m",
|
|
67
|
+
darkRed: "\x1b[31m",
|
|
68
|
+
darkGreen: "\x1b[32m",
|
|
69
|
+
darkYellow: "\x1b[33m",
|
|
70
|
+
darkBlue: "\x1b[34m",
|
|
71
|
+
darkMagenta: "\x1b[35m",
|
|
72
|
+
darkCyan: "\x1b[36m",
|
|
73
|
+
darkWhite: "\x1b[37m",
|
|
74
|
+
brightBlack: "\x1b[90m",
|
|
75
|
+
brightRed: "\x1b[91m",
|
|
76
|
+
brightGreen: "\x1b[92m",
|
|
77
|
+
brightYellow: "\x1b[93m",
|
|
78
|
+
brightBlue: "\x1b[94m",
|
|
79
|
+
brightMagenta: "\x1b[95m",
|
|
80
|
+
brightCyan: "\x1b[96m",
|
|
81
|
+
brightWhite: "\x1b[97m",
|
|
73
82
|
};
|
package/src/lib/Usage.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { GridCell, GridRow, gridToPrintableLines } from "./Grid";
|
|
|
3
3
|
import { TypoSupport, TypoText, typoPrintableString } from "./Typo";
|
|
4
4
|
|
|
5
5
|
export function usageToPrintableLines(params: {
|
|
6
|
-
cliName: string
|
|
6
|
+
cliName: Lowercase<string>;
|
|
7
7
|
commandUsage: CommandUsage;
|
|
8
8
|
typoSupport: TypoSupport;
|
|
9
9
|
}) {
|
|
@@ -11,42 +11,61 @@ export function usageToPrintableLines(params: {
|
|
|
11
11
|
|
|
12
12
|
const lines = new Array<string>();
|
|
13
13
|
|
|
14
|
-
lines.push(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
lines.push(
|
|
15
|
+
typoPrintableString(typoSupport, textDescription(commandUsage.description)),
|
|
16
|
+
);
|
|
17
|
+
if (commandUsage.details) {
|
|
18
|
+
for (const detailLine of commandUsage.details) {
|
|
19
|
+
lines.push(typoPrintableString(typoSupport, textDetails(detailLine)));
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
typoPrintableString(typoSupport, textName(cliName)),
|
|
23
|
+
lines.push("");
|
|
24
|
+
lines.push(typoPrintableString(typoSupport, textCategory("Usage:")));
|
|
25
|
+
const breadcrumbs = [
|
|
26
|
+
" ",
|
|
27
|
+
typoPrintableString(typoSupport, textFixed(cliName)),
|
|
28
28
|
].concat(
|
|
29
29
|
commandUsage.breadcrumbs.map((breadcrumb) => {
|
|
30
|
-
if (
|
|
31
|
-
return typoPrintableString(typoSupport,
|
|
30
|
+
if ("argument" in breadcrumb) {
|
|
31
|
+
return typoPrintableString(typoSupport, textInput(breadcrumb.argument));
|
|
32
|
+
}
|
|
33
|
+
if ("command" in breadcrumb) {
|
|
34
|
+
return typoPrintableString(typoSupport, textFixed(breadcrumb.command));
|
|
32
35
|
}
|
|
33
|
-
|
|
36
|
+
throw new Error(`Unknown breadcrumb: ${JSON.stringify(breadcrumb)}`);
|
|
34
37
|
}),
|
|
35
38
|
);
|
|
36
|
-
lines.push("");
|
|
37
|
-
lines.push(`${breadcrumbPrefix} ${breadcrumbsItems.join(" ")}`);
|
|
39
|
+
lines.push(breadcrumbs.join(" "));
|
|
38
40
|
|
|
39
41
|
if (commandUsage.arguments.length > 0) {
|
|
40
42
|
lines.push("");
|
|
41
|
-
lines.push(typoPrintableString(typoSupport,
|
|
43
|
+
lines.push(typoPrintableString(typoSupport, textCategory("Arguments:")));
|
|
42
44
|
const grid = new Array<GridRow>();
|
|
43
45
|
for (const argumentUsage of commandUsage.arguments) {
|
|
44
46
|
const gridRow = new Array<GridCell>();
|
|
45
|
-
gridRow.push([]);
|
|
46
|
-
gridRow.push([
|
|
47
|
-
gridRow.push([]);
|
|
47
|
+
gridRow.push([textDelimiter()]);
|
|
48
|
+
gridRow.push([textInput(argumentUsage.label)]);
|
|
48
49
|
if (argumentUsage.description) {
|
|
49
|
-
gridRow.push([
|
|
50
|
+
gridRow.push([textDelimiter()]);
|
|
51
|
+
gridRow.push([textDescription(argumentUsage.description)]);
|
|
52
|
+
}
|
|
53
|
+
grid.push(gridRow);
|
|
54
|
+
}
|
|
55
|
+
lines.push(...gridToPrintableLines(grid, typoSupport));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (commandUsage.subcommands.length > 0) {
|
|
59
|
+
lines.push("");
|
|
60
|
+
lines.push(typoPrintableString(typoSupport, textCategory("Subcommands:")));
|
|
61
|
+
const grid = new Array<GridRow>();
|
|
62
|
+
for (const subcommand of commandUsage.subcommands) {
|
|
63
|
+
const gridRow = new Array<GridCell>();
|
|
64
|
+
gridRow.push([textDelimiter()]);
|
|
65
|
+
gridRow.push([textFixed(subcommand.name)]);
|
|
66
|
+
if (subcommand.description) {
|
|
67
|
+
gridRow.push([textDelimiter()]);
|
|
68
|
+
gridRow.push([textDescription(subcommand.description)]);
|
|
50
69
|
}
|
|
51
70
|
grid.push(gridRow);
|
|
52
71
|
}
|
|
@@ -55,72 +74,57 @@ export function usageToPrintableLines(params: {
|
|
|
55
74
|
|
|
56
75
|
if (commandUsage.options.length > 0) {
|
|
57
76
|
lines.push("");
|
|
58
|
-
lines.push(typoPrintableString(typoSupport,
|
|
77
|
+
lines.push(typoPrintableString(typoSupport, textCategory("Options:")));
|
|
59
78
|
const grid = new Array<GridRow>();
|
|
60
79
|
for (const optionUsage of commandUsage.options) {
|
|
61
80
|
const gridRow = new Array<GridCell>();
|
|
62
|
-
gridRow.push([]);
|
|
81
|
+
gridRow.push([textDelimiter()]);
|
|
63
82
|
if (optionUsage.short) {
|
|
64
|
-
gridRow.push([
|
|
83
|
+
gridRow.push([textFixed(`-${optionUsage.short}`), { value: ", " }]);
|
|
65
84
|
} else {
|
|
66
85
|
gridRow.push([]);
|
|
67
86
|
}
|
|
68
87
|
if (optionUsage.label) {
|
|
69
88
|
gridRow.push([
|
|
70
|
-
|
|
71
|
-
|
|
89
|
+
textFixed(`--${optionUsage.long} `),
|
|
90
|
+
textInput(optionUsage.label),
|
|
72
91
|
]);
|
|
73
92
|
} else {
|
|
74
|
-
gridRow.push([
|
|
75
|
-
textName(`--${optionUsage.long}`),
|
|
76
|
-
{ value: "[=yes|no]", color: "grey" },
|
|
77
|
-
]);
|
|
93
|
+
gridRow.push([textFixed(`--${optionUsage.long}`)]);
|
|
78
94
|
}
|
|
79
|
-
gridRow.push([]);
|
|
80
95
|
if (optionUsage.description) {
|
|
81
|
-
gridRow.push([
|
|
96
|
+
gridRow.push([textDelimiter()]);
|
|
97
|
+
gridRow.push([textDescription(optionUsage.description)]);
|
|
82
98
|
}
|
|
83
99
|
grid.push(gridRow);
|
|
84
100
|
}
|
|
85
101
|
lines.push(...gridToPrintableLines(grid, typoSupport));
|
|
86
102
|
}
|
|
87
103
|
|
|
88
|
-
if (commandUsage.subcommands.length > 0) {
|
|
89
|
-
lines.push("");
|
|
90
|
-
lines.push(typoPrintableString(typoSupport, textTitle("Subcommands:")));
|
|
91
|
-
const grid = new Array<GridRow>();
|
|
92
|
-
for (const subcommand of commandUsage.subcommands) {
|
|
93
|
-
const gridRow = new Array<GridCell>();
|
|
94
|
-
gridRow.push([]);
|
|
95
|
-
gridRow.push([textName(subcommand.name)]);
|
|
96
|
-
gridRow.push([]);
|
|
97
|
-
if (subcommand.title) {
|
|
98
|
-
gridRow.push([textDesc(subcommand.title)]);
|
|
99
|
-
}
|
|
100
|
-
grid.push(gridRow);
|
|
101
|
-
}
|
|
102
|
-
lines.push(...gridToPrintableLines(grid, typoSupport));
|
|
103
|
-
}
|
|
104
104
|
lines.push("");
|
|
105
105
|
return lines;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
function
|
|
109
|
-
return { value: text, color: "
|
|
108
|
+
function textCategory(text: string): TypoText {
|
|
109
|
+
return { value: text, color: "brightGreen", bold: true };
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
function
|
|
113
|
-
return { value: text,
|
|
112
|
+
function textDescription(text: string): TypoText {
|
|
113
|
+
return { value: text, bold: true };
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
function
|
|
117
|
-
return { value: text,
|
|
116
|
+
function textDetails(text: string): TypoText {
|
|
117
|
+
return { value: text, color: "brightBlack" };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function textFixed(text: string): TypoText {
|
|
121
|
+
return { value: text, color: "brightCyan", bold: true };
|
|
118
122
|
}
|
|
119
123
|
|
|
120
|
-
function
|
|
121
|
-
return { value: text, color: "
|
|
124
|
+
function textInput(text: string): TypoText {
|
|
125
|
+
return { value: text, color: "brightBlue" };
|
|
122
126
|
}
|
|
123
127
|
|
|
124
|
-
function
|
|
125
|
-
return { value:
|
|
128
|
+
function textDelimiter(): TypoText {
|
|
129
|
+
return { value: " " };
|
|
126
130
|
}
|
|
@@ -9,13 +9,14 @@ import {
|
|
|
9
9
|
optionFlag,
|
|
10
10
|
optionRepeatable,
|
|
11
11
|
optionSingleValue,
|
|
12
|
-
|
|
12
|
+
runCommand,
|
|
13
|
+
typeCommaList,
|
|
13
14
|
typeNumber,
|
|
14
15
|
typeString,
|
|
15
16
|
} from "../src";
|
|
16
17
|
|
|
17
18
|
const cmd = commandWithSubcommands<string, any, any>(
|
|
18
|
-
{
|
|
19
|
+
{ description: "Root command description" },
|
|
19
20
|
execution(
|
|
20
21
|
{
|
|
21
22
|
options: {
|
|
@@ -27,7 +28,7 @@ const cmd = commandWithSubcommands<string, any, any>(
|
|
|
27
28
|
}),
|
|
28
29
|
numberOption: optionRepeatable({
|
|
29
30
|
long: "number-option",
|
|
30
|
-
type: typeNumber,
|
|
31
|
+
type: typeCommaList(typeNumber),
|
|
31
32
|
}),
|
|
32
33
|
},
|
|
33
34
|
arguments: [
|
|
@@ -41,7 +42,7 @@ const cmd = commandWithSubcommands<string, any, any>(
|
|
|
41
42
|
),
|
|
42
43
|
{
|
|
43
44
|
sub1: command(
|
|
44
|
-
{
|
|
45
|
+
{ description: "Subcommand 1 description" },
|
|
45
46
|
execution(
|
|
46
47
|
{
|
|
47
48
|
options: {},
|
|
@@ -53,7 +54,7 @@ const cmd = commandWithSubcommands<string, any, any>(
|
|
|
53
54
|
),
|
|
54
55
|
),
|
|
55
56
|
sub2: command(
|
|
56
|
-
{
|
|
57
|
+
{ description: "Subcommand 2 description" },
|
|
57
58
|
execution(
|
|
58
59
|
{
|
|
59
60
|
options: {},
|
|
@@ -72,8 +73,9 @@ const cmd = commandWithSubcommands<string, any, any>(
|
|
|
72
73
|
);
|
|
73
74
|
|
|
74
75
|
it("run", async () => {
|
|
75
|
-
const res1 = await
|
|
76
|
-
|
|
76
|
+
const res1 = await runCommand(
|
|
77
|
+
"script",
|
|
78
|
+
["50", "51", "sub1", "final"],
|
|
77
79
|
"Run Context Input",
|
|
78
80
|
cmd,
|
|
79
81
|
);
|
|
@@ -97,18 +99,17 @@ it("run", async () => {
|
|
|
97
99
|
at: "sub1",
|
|
98
100
|
});
|
|
99
101
|
|
|
100
|
-
const res2 = await
|
|
102
|
+
const res2 = await runCommand(
|
|
103
|
+
"script",
|
|
101
104
|
[
|
|
102
|
-
"node",
|
|
103
|
-
"script",
|
|
104
105
|
"40",
|
|
105
106
|
"41",
|
|
106
107
|
"sub2",
|
|
107
108
|
"--string-option=hello",
|
|
108
109
|
"--number-option",
|
|
109
|
-
"123",
|
|
110
|
+
"123.1,123.2",
|
|
110
111
|
"--number-option",
|
|
111
|
-
"
|
|
112
|
+
"123.3",
|
|
112
113
|
"88.88",
|
|
113
114
|
"a,b",
|
|
114
115
|
"final",
|
|
@@ -124,7 +125,7 @@ it("run", async () => {
|
|
|
124
125
|
options: {
|
|
125
126
|
booleanFlag: true,
|
|
126
127
|
stringOption: "hello",
|
|
127
|
-
numberOption: [123,
|
|
128
|
+
numberOption: [[123.1, 123.2], [123.3]],
|
|
128
129
|
},
|
|
129
130
|
arguments: [40, 41],
|
|
130
131
|
},
|