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