cli-kiss 0.2.7 → 0.2.9
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/README.md +8 -3
- package/dist/index.d.ts +200 -190
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/docs/.vitepress/config.mts +1 -1
- package/docs/.vitepress/theme/Layout.vue +16 -0
- package/docs/.vitepress/theme/index.ts +5 -1
- package/docs/.vitepress/theme/style.css +5 -1
- package/docs/guide/01_getting_started.md +2 -2
- package/docs/guide/02_commands.md +3 -3
- package/docs/guide/03_options.md +11 -11
- package/docs/guide/04_positionals.md +9 -9
- package/docs/guide/05_input_types.md +17 -16
- package/docs/guide/06_run_as_cli.md +1 -1
- package/docs/index.md +2 -2
- package/docs/public/favicon.ico +0 -0
- package/docs/public/logo.png +0 -0
- package/package.json +1 -1
- package/src/index.ts +1 -1
- package/src/lib/Command.ts +51 -40
- package/src/lib/Operation.ts +41 -25
- package/src/lib/Option.ts +198 -127
- package/src/lib/Positional.ts +51 -25
- package/src/lib/Reader.ts +188 -226
- package/src/lib/Run.ts +20 -9
- package/src/lib/Suggest.ts +78 -0
- package/src/lib/Type.ts +178 -154
- package/src/lib/Typo.ts +58 -55
- package/src/lib/Usage.ts +12 -12
- package/tests/unit.Reader.commons.ts +86 -123
- package/tests/unit.Reader.parsings.ts +14 -26
- package/tests/unit.Reader.shortBig.ts +75 -101
- package/tests/unit.command.aliases.ts +88 -0
- package/tests/unit.command.execute.ts +6 -6
- package/tests/unit.command.usage.ts +19 -13
- package/tests/unit.fuzzed.alternatives.ts +35 -26
- package/tests/unit.runner.colors.ts +8 -33
- package/tests/unit.runner.cycle.ts +141 -156
- package/tests/unit.runner.errors.ts +25 -22
- package/docs/public/hero.png +0 -0
- package/src/lib/Similarity.ts +0 -41
- package/tests/unit.Reader.aliases.ts +0 -62
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { it } from "@jest/globals";
|
|
1
|
+
import { expect, it } from "@jest/globals";
|
|
2
2
|
import {
|
|
3
3
|
command,
|
|
4
4
|
commandWithSubcommands,
|
|
@@ -10,23 +10,25 @@ import {
|
|
|
10
10
|
positionalRequired,
|
|
11
11
|
positionalVariadics,
|
|
12
12
|
runAndExit,
|
|
13
|
-
type,
|
|
14
13
|
typeChoice,
|
|
15
|
-
|
|
14
|
+
typeMapped,
|
|
15
|
+
typeString,
|
|
16
16
|
typeUrl,
|
|
17
17
|
} from "../src";
|
|
18
18
|
|
|
19
19
|
it("run", async function () {
|
|
20
20
|
const rootUsage = [
|
|
21
|
-
"Usage: my-cli <
|
|
21
|
+
"Usage: my-cli <req1> <subcommand>",
|
|
22
22
|
"",
|
|
23
|
-
"Root Description",
|
|
23
|
+
"Root Description (Hint for root)",
|
|
24
|
+
"Root details1",
|
|
25
|
+
"Root details2",
|
|
24
26
|
"",
|
|
25
27
|
"Positionals:",
|
|
26
|
-
" <
|
|
28
|
+
" <req1> Required1 positional description (Hint for req1)",
|
|
27
29
|
"",
|
|
28
30
|
"Subcommands:",
|
|
29
|
-
"
|
|
31
|
+
" sub Subcommand Description (Hint for sub)",
|
|
30
32
|
"",
|
|
31
33
|
"Options:",
|
|
32
34
|
" -ff, --flag[=no] Option flag description",
|
|
@@ -34,14 +36,16 @@ it("run", async function () {
|
|
|
34
36
|
" -s, --single-value <enum(number)> Option single value description",
|
|
35
37
|
"",
|
|
36
38
|
].join("\n");
|
|
37
|
-
const
|
|
38
|
-
"Usage: my-cli <
|
|
39
|
+
const subUsage = [
|
|
40
|
+
"Usage: my-cli <req1> sub <req2> [optional] [variadic]...",
|
|
39
41
|
"",
|
|
40
|
-
"Subcommand Description",
|
|
42
|
+
"Subcommand Description (Hint for sub)",
|
|
43
|
+
"Sub details1",
|
|
44
|
+
"Sub details2",
|
|
41
45
|
"",
|
|
42
46
|
"Positionals:",
|
|
43
|
-
" <
|
|
44
|
-
" <
|
|
47
|
+
" <req1> Required1 positional description (Hint for req1)",
|
|
48
|
+
" <req2> Required2 positional description",
|
|
45
49
|
" [optional] Optional positional description",
|
|
46
50
|
" [variadic]... Variadics positional description",
|
|
47
51
|
"",
|
|
@@ -55,78 +59,64 @@ it("run", async function () {
|
|
|
55
59
|
|
|
56
60
|
// Test that everything could work normally
|
|
57
61
|
await testCase(
|
|
58
|
-
["
|
|
59
|
-
["Has executed root command", "Has executed
|
|
62
|
+
["req1", "sub", "req2"],
|
|
63
|
+
["Has executed root command", "Has executed sub"],
|
|
60
64
|
[],
|
|
61
65
|
0,
|
|
62
66
|
);
|
|
63
67
|
|
|
64
68
|
// Check that version flag takes precedence over execution
|
|
65
69
|
await testCase(["--version"], ["my-cli 1.0.0"], [], 0);
|
|
66
|
-
await testCase(["
|
|
67
|
-
await testCase(
|
|
68
|
-
|
|
69
|
-
["my-cli 1.0.0"],
|
|
70
|
-
[],
|
|
71
|
-
0,
|
|
72
|
-
);
|
|
73
|
-
await testCase(
|
|
74
|
-
["required1", "subcommand", "required2", "--version"],
|
|
75
|
-
["my-cli 1.0.0"],
|
|
76
|
-
[],
|
|
77
|
-
0,
|
|
78
|
-
);
|
|
70
|
+
await testCase(["req1", "--version"], ["my-cli 1.0.0"], [], 0);
|
|
71
|
+
await testCase(["req1", "sub", "--version"], ["my-cli 1.0.0"], [], 0);
|
|
72
|
+
await testCase(["req1", "sub", "req2", "--version"], ["my-cli 1.0.0"], [], 0);
|
|
79
73
|
|
|
80
74
|
// Check that help flag takes precedence over execution
|
|
81
75
|
await testCase(["--help"], [rootUsage], [], 0);
|
|
82
|
-
await testCase(["
|
|
83
|
-
await testCase(
|
|
84
|
-
|
|
85
|
-
[subcommandUsage],
|
|
86
|
-
[],
|
|
87
|
-
0,
|
|
88
|
-
);
|
|
89
|
-
await testCase(
|
|
90
|
-
["required1", "subcommand", "required2", "--help"],
|
|
91
|
-
[subcommandUsage],
|
|
92
|
-
[],
|
|
93
|
-
0,
|
|
94
|
-
);
|
|
76
|
+
await testCase(["req1", "--help"], [rootUsage], [], 0);
|
|
77
|
+
await testCase(["req1", "sub", "--help"], [subUsage], [], 0);
|
|
78
|
+
await testCase(["req1", "sub", "req2", "--help"], [subUsage], [], 0);
|
|
95
79
|
|
|
96
80
|
// Help takes precedence over version
|
|
97
81
|
await testCase(["--version", "--help"], [rootUsage], [], 0);
|
|
98
82
|
await testCase(["--help", "--version"], [rootUsage], [], 0);
|
|
99
83
|
|
|
84
|
+
// Help still works after failed parsing (should show usage for the right command)
|
|
85
|
+
await testCase(["--invalid", "--help"], [rootUsage], [], 0);
|
|
86
|
+
await testCase(["invalid", "--help"], [rootUsage], [], 0);
|
|
87
|
+
await testCase(["req1", "sub", "--invalid", "--help"], [subUsage], [], 0);
|
|
88
|
+
await testCase(["req1", "sub", "invalid", "--help"], [subUsage], [], 0);
|
|
89
|
+
|
|
100
90
|
// Weird help/version values inputs
|
|
101
91
|
await testCase(
|
|
102
92
|
["--help=invalid"],
|
|
103
93
|
[],
|
|
104
|
-
[rootUsage, `Error: --help: value: Not a boolean: "invalid"
|
|
94
|
+
[rootUsage, `Error: --help: value: Not a boolean: "invalid".`],
|
|
105
95
|
1,
|
|
106
96
|
);
|
|
107
97
|
await testCase(
|
|
108
98
|
["--version=invalid"],
|
|
109
99
|
[],
|
|
110
|
-
[rootUsage, `Error: --version: value: Not a boolean: "invalid"
|
|
100
|
+
[rootUsage, `Error: --version: value: Not a boolean: "invalid".`],
|
|
111
101
|
1,
|
|
112
102
|
);
|
|
113
103
|
|
|
114
104
|
// Test multiple errors at once (first one should show only)
|
|
115
105
|
await testCase(
|
|
116
|
-
["--invalid1", "--invalid2", "
|
|
106
|
+
["--invalid1", "--invalid2", "req1", "--invalid3"],
|
|
117
107
|
[],
|
|
118
108
|
[
|
|
119
109
|
rootUsage,
|
|
120
|
-
'Error: Unknown option: "--invalid1"
|
|
110
|
+
'Error: Unknown option: "--invalid1". Did you mean: --single-value, --help, --version, ... ?',
|
|
121
111
|
],
|
|
122
112
|
1,
|
|
123
113
|
);
|
|
124
114
|
await testCase(
|
|
125
|
-
["
|
|
115
|
+
["req1", "unknown", "-wut", "--flag", "--single-value"],
|
|
126
116
|
[],
|
|
127
117
|
[
|
|
128
118
|
rootUsage,
|
|
129
|
-
'Error: <subcommand>: Unknown name: "unknown"
|
|
119
|
+
'Error: <subcommand>: Unknown name: "unknown". Did you mean: sub ?',
|
|
130
120
|
],
|
|
131
121
|
1,
|
|
132
122
|
);
|
|
@@ -135,121 +125,130 @@ it("run", async function () {
|
|
|
135
125
|
await testCase(
|
|
136
126
|
[],
|
|
137
127
|
[],
|
|
138
|
-
[
|
|
128
|
+
[
|
|
129
|
+
rootUsage,
|
|
130
|
+
"Error: Missing argument: <req1>: Required1 positional description (Hint for req1)",
|
|
131
|
+
],
|
|
139
132
|
1,
|
|
140
133
|
);
|
|
141
134
|
await testCase(
|
|
142
|
-
["
|
|
135
|
+
["req1"],
|
|
143
136
|
[],
|
|
144
|
-
[rootUsage, "Error: <subcommand
|
|
137
|
+
[rootUsage, "Error: Missing argument: <subcommand>. Did you mean: sub ?"],
|
|
145
138
|
1,
|
|
146
139
|
);
|
|
147
140
|
await testCase(
|
|
148
|
-
["
|
|
141
|
+
["req1", "sub"],
|
|
149
142
|
[],
|
|
150
|
-
[
|
|
143
|
+
[
|
|
144
|
+
subUsage,
|
|
145
|
+
"Error: Missing argument: <req2>: Required2 positional description",
|
|
146
|
+
],
|
|
151
147
|
1,
|
|
152
148
|
);
|
|
153
149
|
|
|
154
|
-
// Test that flags become available when
|
|
150
|
+
// Test that flags become available when sub is known
|
|
155
151
|
await testCase(
|
|
156
152
|
["--url", "https://example.com"],
|
|
157
153
|
[],
|
|
158
154
|
[
|
|
159
155
|
rootUsage,
|
|
160
|
-
'Error: Unknown option: "--url"
|
|
156
|
+
'Error: Unknown option: "--url". Did you mean: --help, -r, --version, ... ?',
|
|
161
157
|
],
|
|
162
158
|
1,
|
|
163
159
|
);
|
|
164
160
|
await testCase(
|
|
165
|
-
["
|
|
161
|
+
["req1", "--url", "https://example.com"],
|
|
166
162
|
[],
|
|
167
163
|
[
|
|
168
164
|
rootUsage,
|
|
169
|
-
'Error: Unknown option: "--url"
|
|
165
|
+
'Error: Unknown option: "--url". Did you mean: --help, -r, --version, ... ?',
|
|
170
166
|
],
|
|
171
167
|
1,
|
|
172
168
|
);
|
|
173
169
|
await testCase(
|
|
174
|
-
["
|
|
170
|
+
["req1", "sub", "--url", "https://example.com"],
|
|
175
171
|
[],
|
|
176
|
-
[
|
|
172
|
+
[
|
|
173
|
+
subUsage,
|
|
174
|
+
"Error: Missing argument: <req2>: Required2 positional description",
|
|
175
|
+
],
|
|
177
176
|
1,
|
|
178
177
|
);
|
|
179
178
|
await testCase(
|
|
180
|
-
["
|
|
181
|
-
["Has executed root command", "Has executed
|
|
179
|
+
["req1", "sub", "req2", "--url", "https://example.com"],
|
|
180
|
+
["Has executed root command", "Has executed sub"],
|
|
182
181
|
[],
|
|
183
182
|
0,
|
|
184
183
|
);
|
|
185
184
|
|
|
186
185
|
// Test option as flag parsing cases
|
|
187
186
|
await testCase(
|
|
188
|
-
["--flag", "--flag", "
|
|
187
|
+
["--flag", "--flag", "req1", "sub", "req2"],
|
|
189
188
|
[],
|
|
190
|
-
[
|
|
189
|
+
[subUsage, "Error: --flag: Must not be set multiple times."],
|
|
191
190
|
1,
|
|
192
191
|
);
|
|
193
192
|
await testCase(
|
|
194
|
-
["--flag=42", "
|
|
193
|
+
["--flag=42", "req1", "sub", "req2"],
|
|
195
194
|
[],
|
|
196
|
-
[
|
|
195
|
+
[subUsage, 'Error: --flag: value: Not a boolean: "42".'],
|
|
197
196
|
1,
|
|
198
197
|
);
|
|
199
198
|
await testCase(
|
|
200
|
-
["--flag=no", "
|
|
201
|
-
["Has executed root command", "Has executed
|
|
199
|
+
["--flag=no", "req1", "sub", "req2"],
|
|
200
|
+
["Has executed root command", "Has executed sub"],
|
|
202
201
|
[],
|
|
203
202
|
0,
|
|
204
203
|
);
|
|
205
204
|
await testCase(
|
|
206
|
-
["--flag=yes", "
|
|
207
|
-
["Has executed root command", "Has executed
|
|
205
|
+
["--flag=yes", "req1", "sub", "req2"],
|
|
206
|
+
["Has executed root command", "Has executed sub"],
|
|
208
207
|
[],
|
|
209
208
|
0,
|
|
210
209
|
);
|
|
211
210
|
await testCase(
|
|
212
|
-
["--flag", "
|
|
213
|
-
["Has executed root command", "Has executed
|
|
211
|
+
["--flag", "req1", "sub", "req2"],
|
|
212
|
+
["Has executed root command", "Has executed sub"],
|
|
214
213
|
[],
|
|
215
214
|
0,
|
|
216
215
|
);
|
|
217
216
|
|
|
218
217
|
// Test option parsing errors
|
|
219
218
|
await testCase(
|
|
220
|
-
["--invalid", "
|
|
219
|
+
["--invalid", "req1", "sub", "req2"],
|
|
221
220
|
[],
|
|
222
221
|
[
|
|
223
222
|
rootUsage,
|
|
224
|
-
'Error: Unknown option: "--invalid"
|
|
223
|
+
'Error: Unknown option: "--invalid". Did you mean: --single-value, --help, --flag, ... ?',
|
|
225
224
|
],
|
|
226
225
|
1,
|
|
227
226
|
);
|
|
228
227
|
await testCase(
|
|
229
|
-
["
|
|
228
|
+
["req1", "sub", "req2", "--nope"],
|
|
230
229
|
[],
|
|
231
230
|
[
|
|
232
|
-
|
|
233
|
-
'Error: Unknown option: "--nope"
|
|
231
|
+
subUsage,
|
|
232
|
+
'Error: Unknown option: "--nope". Did you mean: --help, --flag, --repeatable, ... ?',
|
|
234
233
|
],
|
|
235
234
|
1,
|
|
236
235
|
);
|
|
237
236
|
await testCase(
|
|
238
|
-
["
|
|
237
|
+
["req1", "sub", "req2", "--url"],
|
|
239
238
|
[],
|
|
240
|
-
[
|
|
239
|
+
[subUsage, "Error: --url: Requires a value, but got end of input."],
|
|
241
240
|
1,
|
|
242
241
|
);
|
|
243
242
|
await testCase(
|
|
244
|
-
["
|
|
243
|
+
["req1", "sub", "req2", "--url", "--", "url"],
|
|
245
244
|
[],
|
|
246
|
-
[
|
|
245
|
+
[subUsage, 'Error: --url: Requires a value but got: "--".'],
|
|
247
246
|
1,
|
|
248
247
|
);
|
|
249
248
|
await testCase(
|
|
250
|
-
["
|
|
249
|
+
["req1", "sub", "req2", "--url", "--url"],
|
|
251
250
|
[],
|
|
252
|
-
[
|
|
251
|
+
[subUsage, 'Error: --url: Requires a value, but got: "--url".'],
|
|
253
252
|
1,
|
|
254
253
|
);
|
|
255
254
|
|
|
@@ -257,163 +256,140 @@ it("run", async function () {
|
|
|
257
256
|
await testCase(
|
|
258
257
|
["invalid"],
|
|
259
258
|
[],
|
|
260
|
-
[rootUsage, "Error: <subcommand
|
|
259
|
+
[rootUsage, "Error: Missing argument: <subcommand>. Did you mean: sub ?"],
|
|
261
260
|
1,
|
|
262
261
|
);
|
|
263
262
|
await testCase(
|
|
264
|
-
["invalid", "
|
|
263
|
+
["invalid", "sub"],
|
|
265
264
|
[],
|
|
266
265
|
[
|
|
267
|
-
|
|
268
|
-
'Error: <
|
|
266
|
+
subUsage,
|
|
267
|
+
'Error: <req1>: Unknown value: "invalid". Did you mean: "req1-bis", "req1" ?',
|
|
269
268
|
],
|
|
270
269
|
1,
|
|
271
270
|
);
|
|
272
271
|
await testCase(
|
|
273
|
-
["invalid", "
|
|
272
|
+
["invalid", "sub", "req2"],
|
|
274
273
|
[],
|
|
275
274
|
[
|
|
276
|
-
|
|
277
|
-
'Error: <
|
|
275
|
+
subUsage,
|
|
276
|
+
'Error: <req1>: Unknown value: "invalid". Did you mean: "req1-bis", "req1" ?',
|
|
278
277
|
],
|
|
279
278
|
1,
|
|
280
279
|
);
|
|
281
280
|
await testCase(
|
|
282
|
-
["
|
|
281
|
+
["req1", "sub", "invalid"],
|
|
283
282
|
[],
|
|
284
283
|
[
|
|
285
|
-
|
|
286
|
-
'Error: <
|
|
284
|
+
subUsage,
|
|
285
|
+
'Error: <req2>: Unknown value: "invalid". Did you mean: "req2-bis", "req2" ?',
|
|
287
286
|
],
|
|
288
287
|
1,
|
|
289
288
|
);
|
|
290
289
|
await testCase(
|
|
291
|
-
["invalid", "
|
|
290
|
+
["invalid", "sub", "invalid"],
|
|
292
291
|
[],
|
|
293
292
|
[
|
|
294
|
-
|
|
295
|
-
'Error: <
|
|
293
|
+
subUsage,
|
|
294
|
+
'Error: <req1>: Unknown value: "invalid". Did you mean: "req1-bis", "req1" ?',
|
|
296
295
|
],
|
|
297
296
|
1,
|
|
298
297
|
);
|
|
299
298
|
|
|
300
299
|
// Test root command option invalid values (must not block parsing)
|
|
301
300
|
await testCase(
|
|
302
|
-
["--single-value=dodo", "
|
|
301
|
+
["--single-value=dodo", "req1", "sub", "req2"],
|
|
303
302
|
[],
|
|
304
303
|
[
|
|
305
|
-
|
|
306
|
-
'Error: --single-value: <enum(number)>: from: enum(string): Unknown value: "dodo"
|
|
304
|
+
subUsage,
|
|
305
|
+
'Error: --single-value: <enum(number)>: from: enum(string): Unknown value: "dodo". Did you mean: "42", "43" ?',
|
|
307
306
|
],
|
|
308
307
|
1,
|
|
309
308
|
);
|
|
310
309
|
await testCase(
|
|
311
|
-
["
|
|
310
|
+
["req1", "sub", "req2", "--single-value=44"],
|
|
312
311
|
[],
|
|
313
312
|
[
|
|
314
|
-
|
|
315
|
-
'Error: --single-value: <enum(number)>: from: enum(string): Unknown value: "44"
|
|
313
|
+
subUsage,
|
|
314
|
+
'Error: --single-value: <enum(number)>: from: enum(string): Unknown value: "44". Did you mean: "42", "43" ?',
|
|
316
315
|
],
|
|
317
316
|
1,
|
|
318
317
|
);
|
|
319
318
|
|
|
320
|
-
// Test
|
|
319
|
+
// Test sub-only option failures
|
|
321
320
|
await testCase(
|
|
322
|
-
["--url", "not-a-url", "
|
|
321
|
+
["--url", "not-a-url", "req1", "sub", "req2"],
|
|
323
322
|
[],
|
|
324
323
|
[
|
|
325
324
|
rootUsage,
|
|
326
|
-
'Error: Unknown option: "--url"
|
|
325
|
+
'Error: Unknown option: "--url". Did you mean: --help, -r, --version, ... ?',
|
|
327
326
|
],
|
|
328
327
|
1,
|
|
329
328
|
);
|
|
330
329
|
await testCase(
|
|
331
|
-
["
|
|
330
|
+
["req1", "sub", "req2", "--url", "not-a-url"],
|
|
332
331
|
[],
|
|
333
|
-
[
|
|
332
|
+
[subUsage, 'Error: --url: <url>: Not an URL: "not-a-url".'],
|
|
334
333
|
1,
|
|
335
334
|
);
|
|
336
335
|
|
|
337
336
|
// Test option multiple value parsing cases
|
|
338
337
|
await testCase(
|
|
339
|
-
[
|
|
340
|
-
|
|
341
|
-
"subcommand",
|
|
342
|
-
"required2",
|
|
343
|
-
"--repeatable=42",
|
|
344
|
-
"--repeatable",
|
|
345
|
-
"43",
|
|
346
|
-
],
|
|
347
|
-
["Has executed root command", "Has executed subcommand"],
|
|
338
|
+
["req1", "sub", "req2", "--repeatable=42", "--repeatable", "43"],
|
|
339
|
+
["Has executed root command", "Has executed sub"],
|
|
348
340
|
[],
|
|
349
341
|
0,
|
|
350
342
|
);
|
|
351
343
|
await testCase(
|
|
352
|
-
[
|
|
353
|
-
"required1",
|
|
354
|
-
"subcommand",
|
|
355
|
-
"required2",
|
|
356
|
-
"--single-value=42",
|
|
357
|
-
"--single-value",
|
|
358
|
-
"43",
|
|
359
|
-
],
|
|
344
|
+
["req1", "sub", "req2", "--single-value=42", "--single-value", "43"],
|
|
360
345
|
[],
|
|
361
|
-
[
|
|
346
|
+
[subUsage, "Error: --single-value: Must not be set multiple times."],
|
|
362
347
|
1,
|
|
363
348
|
);
|
|
364
349
|
|
|
365
350
|
// Test suggestions
|
|
366
351
|
await testCase(
|
|
367
|
-
["
|
|
352
|
+
["req1", "sub", "req2", "-f"],
|
|
368
353
|
[],
|
|
369
|
-
[
|
|
370
|
-
subcommandUsage,
|
|
371
|
-
'Error: Unknown option: "-f": did you mean: -ff, -r, -s ?',
|
|
372
|
-
],
|
|
354
|
+
[subUsage, 'Error: Unknown option: "-f". Did you mean: -ff, -r, -s, ... ?'],
|
|
373
355
|
1,
|
|
374
356
|
);
|
|
375
357
|
await testCase(
|
|
376
|
-
["
|
|
358
|
+
["req1", "sub", "req2", "-flag"],
|
|
377
359
|
[],
|
|
378
|
-
[
|
|
379
|
-
subcommandUsage,
|
|
380
|
-
'Error: Unknown option: "-flag": did you mean: --flag, -ff, --single-value ?',
|
|
381
|
-
],
|
|
360
|
+
[subUsage, 'Error: Unknown option: "-flag". Did you mean: --flag ?'],
|
|
382
361
|
1,
|
|
383
362
|
);
|
|
384
363
|
await testCase(
|
|
385
|
-
["
|
|
364
|
+
["req1", "sub", "req2", "--uri"],
|
|
386
365
|
[],
|
|
387
|
-
[
|
|
388
|
-
subcommandUsage,
|
|
389
|
-
'Error: Unknown option: "--uri": did you mean: --url, --version, -r ?',
|
|
390
|
-
],
|
|
366
|
+
[subUsage, 'Error: Unknown option: "--uri". Did you mean: --url ?'],
|
|
391
367
|
1,
|
|
392
368
|
);
|
|
393
369
|
await testCase(
|
|
394
|
-
["
|
|
370
|
+
["req1", "sub", "req2", "--single-"],
|
|
395
371
|
[],
|
|
396
372
|
[
|
|
397
|
-
|
|
398
|
-
'Error: Unknown option: "--single-"
|
|
373
|
+
subUsage,
|
|
374
|
+
'Error: Unknown option: "--single-". Did you mean: --single-value ?',
|
|
399
375
|
],
|
|
400
376
|
1,
|
|
401
377
|
);
|
|
402
378
|
await testCase(
|
|
403
|
-
["
|
|
379
|
+
["1req", "sub", "req2"],
|
|
404
380
|
[],
|
|
405
381
|
[
|
|
406
|
-
|
|
407
|
-
'Error: <
|
|
382
|
+
subUsage,
|
|
383
|
+
'Error: <req1>: Unknown value: "1req". Did you mean: "req1", "req1-bis" ?',
|
|
408
384
|
],
|
|
409
385
|
1,
|
|
410
386
|
);
|
|
411
387
|
await testCase(
|
|
412
|
-
["
|
|
388
|
+
["req1", "subcomm"],
|
|
413
389
|
[],
|
|
414
390
|
[
|
|
415
391
|
rootUsage,
|
|
416
|
-
'Error: <subcommand>: Unknown name: "subcomm"
|
|
392
|
+
'Error: <subcommand>: Unknown name: "subcomm". Did you mean: sub ?',
|
|
417
393
|
],
|
|
418
394
|
1,
|
|
419
395
|
);
|
|
@@ -435,7 +411,11 @@ async function testCase(
|
|
|
435
411
|
]);
|
|
436
412
|
const onExit = makeMocked<number, never>([null as never]);
|
|
437
413
|
const cmd = commandWithSubcommands<null, void, void>(
|
|
438
|
-
{
|
|
414
|
+
{
|
|
415
|
+
description: "Root Description",
|
|
416
|
+
hint: "Hint for root",
|
|
417
|
+
details: ["Root details1", "Root details2"],
|
|
418
|
+
},
|
|
439
419
|
operation(
|
|
440
420
|
{
|
|
441
421
|
options: {
|
|
@@ -447,25 +427,26 @@ async function testCase(
|
|
|
447
427
|
optionRepeatable: optionRepeatable({
|
|
448
428
|
long: "repeatable",
|
|
449
429
|
short: "r",
|
|
450
|
-
type:
|
|
430
|
+
type: typeString(),
|
|
451
431
|
description: "Option repeatable description",
|
|
452
432
|
}),
|
|
453
433
|
optionSingleValue: optionSingleValue({
|
|
454
434
|
long: "single-value",
|
|
455
435
|
short: "s",
|
|
456
|
-
type:
|
|
436
|
+
type: typeMapped(
|
|
457
437
|
"enum(number)",
|
|
458
438
|
typeChoice("enum(string)", ["42", "43"]),
|
|
459
439
|
(value) => Number(value),
|
|
460
440
|
),
|
|
461
441
|
description: "Option single value description",
|
|
462
|
-
|
|
442
|
+
fallbackValueIfAbsent: () => 42,
|
|
463
443
|
}),
|
|
464
444
|
},
|
|
465
445
|
positionals: [
|
|
466
446
|
positionalRequired({
|
|
467
|
-
type: typeChoice("
|
|
447
|
+
type: typeChoice("req1", ["req1", "req1-bis"]),
|
|
468
448
|
description: "Required1 positional description",
|
|
449
|
+
hint: "Hint for req1",
|
|
469
450
|
}),
|
|
470
451
|
],
|
|
471
452
|
},
|
|
@@ -474,8 +455,12 @@ async function testCase(
|
|
|
474
455
|
},
|
|
475
456
|
),
|
|
476
457
|
{
|
|
477
|
-
|
|
478
|
-
{
|
|
458
|
+
sub: command(
|
|
459
|
+
{
|
|
460
|
+
description: "Subcommand Description",
|
|
461
|
+
hint: "Hint for sub",
|
|
462
|
+
details: ["Sub details1", "Sub details2"],
|
|
463
|
+
},
|
|
479
464
|
operation(
|
|
480
465
|
{
|
|
481
466
|
options: {
|
|
@@ -488,22 +473,22 @@ async function testCase(
|
|
|
488
473
|
},
|
|
489
474
|
positionals: [
|
|
490
475
|
positionalRequired({
|
|
491
|
-
type: typeChoice("
|
|
476
|
+
type: typeChoice("req2", ["req2", "req2-bis"]),
|
|
492
477
|
description: "Required2 positional description",
|
|
493
478
|
}),
|
|
494
479
|
positionalOptional({
|
|
495
|
-
type:
|
|
480
|
+
type: typeString("optional"),
|
|
496
481
|
description: "Optional positional description",
|
|
497
482
|
default: () => "world !",
|
|
498
483
|
}),
|
|
499
484
|
positionalVariadics({
|
|
500
|
-
type:
|
|
485
|
+
type: typeString("variadic"),
|
|
501
486
|
description: "Variadics positional description",
|
|
502
487
|
}),
|
|
503
488
|
],
|
|
504
489
|
},
|
|
505
490
|
async function (_, _inputs) {
|
|
506
|
-
console.log(`Has executed
|
|
491
|
+
console.log(`Has executed sub`);
|
|
507
492
|
},
|
|
508
493
|
),
|
|
509
494
|
),
|