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.
Files changed (39) hide show
  1. package/dist/index.d.ts +127 -137
  2. package/dist/index.js +2 -2
  3. package/dist/index.js.map +1 -1
  4. package/docs/.vitepress/config.mts +1 -1
  5. package/docs/.vitepress/theme/Layout.vue +16 -0
  6. package/docs/.vitepress/theme/index.ts +5 -1
  7. package/docs/.vitepress/theme/style.css +5 -1
  8. package/docs/guide/02_commands.md +1 -1
  9. package/docs/guide/03_options.md +11 -11
  10. package/docs/guide/05_input_types.md +9 -10
  11. package/docs/guide/06_run_as_cli.md +1 -1
  12. package/docs/index.md +2 -2
  13. package/docs/public/favicon.ico +0 -0
  14. package/docs/public/logo.png +0 -0
  15. package/package.json +1 -1
  16. package/src/index.ts +1 -1
  17. package/src/lib/Command.ts +45 -39
  18. package/src/lib/Operation.ts +28 -20
  19. package/src/lib/Option.ts +196 -127
  20. package/src/lib/Positional.ts +44 -23
  21. package/src/lib/Reader.ts +194 -226
  22. package/src/lib/Run.ts +19 -8
  23. package/src/lib/Suggest.ts +78 -0
  24. package/src/lib/Type.ts +36 -37
  25. package/src/lib/Typo.ts +58 -55
  26. package/src/lib/Usage.ts +12 -12
  27. package/tests/unit.Reader.commons.ts +92 -116
  28. package/tests/unit.Reader.parsings.ts +14 -26
  29. package/tests/unit.Reader.shortBig.ts +81 -96
  30. package/tests/unit.command.aliases.ts +100 -0
  31. package/tests/unit.command.execute.ts +1 -1
  32. package/tests/unit.command.usage.ts +12 -6
  33. package/tests/unit.fuzzed.alternatives.ts +35 -26
  34. package/tests/unit.runner.colors.ts +8 -33
  35. package/tests/unit.runner.cycle.ts +118 -146
  36. package/tests/unit.runner.errors.ts +25 -22
  37. package/docs/public/hero.png +0 -0
  38. package/src/lib/Similarity.ts +0 -41
  39. 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 <required1> <subcommand>",
21
+ "Usage: my-cli <req1> <subcommand>",
22
22
  "",
23
23
  "Root Description",
24
24
  "",
25
25
  "Positionals:",
26
- " <required1> Required1 positional description",
26
+ " <req1> Required1 positional description",
27
27
  "",
28
28
  "Subcommands:",
29
- " subcommand Subcommand Description",
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 subcommandUsage = [
38
- "Usage: my-cli <required1> subcommand <required2> [optional] [variadic]...",
37
+ const subUsage = [
38
+ "Usage: my-cli <req1> sub <req2> [optional] [variadic]...",
39
39
  "",
40
40
  "Subcommand Description",
41
41
  "",
42
42
  "Positionals:",
43
- " <required1> Required1 positional description",
44
- " <required2> Required2 positional description",
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
- ["required1", "subcommand", "required2"],
59
- ["Has executed root command", "Has executed subcommand"],
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(["required1", "--version"], ["my-cli 1.0.0"], [], 0);
67
- await testCase(
68
- ["required1", "subcommand", "--version"],
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(["required1", "--help"], [rootUsage], [], 0);
83
- await testCase(
84
- ["required1", "subcommand", "--help"],
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", "required1", "--invalid3"],
102
+ ["--invalid1", "--invalid2", "req1", "--invalid3"],
117
103
  [],
118
104
  [
119
105
  rootUsage,
120
- 'Error: Unknown option: "--invalid1": did you mean: --single-value, --help, --version ?',
106
+ 'Error: Unknown option: "--invalid1". Did you mean: --single-value, --help, --version, ... ?',
121
107
  ],
122
108
  1,
123
109
  );
124
110
  await testCase(
125
- ["required1", "unknown", "-wut", "--flag", "--single-value"],
111
+ ["req1", "unknown", "-wut", "--flag", "--single-value"],
126
112
  [],
127
113
  [
128
114
  rootUsage,
129
- 'Error: <subcommand>: Unknown name: "unknown": did you mean: subcommand ?',
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
- [rootUsage, "Error: <required1>: Is required, but was not provided"],
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
- ["required1"],
131
+ ["req1"],
143
132
  [],
144
- [rootUsage, "Error: <subcommand>: Is required, but was not provided"],
133
+ [rootUsage, "Error: <subcommand>: Missing argument. Did you mean: sub ?"],
145
134
  1,
146
135
  );
147
136
  await testCase(
148
- ["required1", "subcommand"],
137
+ ["req1", "sub"],
149
138
  [],
150
- [subcommandUsage, "Error: <required2>: Is required, but was not provided"],
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 subcommand is known
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": did you mean: --help, -r, --version ?',
152
+ 'Error: Unknown option: "--url". Did you mean: --help, -r, --version, ... ?',
161
153
  ],
162
154
  1,
163
155
  );
164
156
  await testCase(
165
- ["required1", "--url", "https://example.com"],
157
+ ["req1", "--url", "https://example.com"],
166
158
  [],
167
159
  [
168
160
  rootUsage,
169
- 'Error: Unknown option: "--url": did you mean: --help, -r, --version ?',
161
+ 'Error: Unknown option: "--url". Did you mean: --help, -r, --version, ... ?',
170
162
  ],
171
163
  1,
172
164
  );
173
165
  await testCase(
174
- ["required1", "subcommand", "--url", "https://example.com"],
166
+ ["req1", "sub", "--url", "https://example.com"],
175
167
  [],
176
- [subcommandUsage, "Error: <required2>: Is required, but was not provided"],
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
- ["required1", "subcommand", "required2", "--url", "https://example.com"],
181
- ["Has executed root command", "Has executed subcommand"],
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", "required1", "subcommand", "required2"],
183
+ ["--flag", "--flag", "req1", "sub", "req2"],
189
184
  [],
190
- [subcommandUsage, "Error: --flag: Must not be set multiple times"],
185
+ [subUsage, "Error: --flag: Must not be set multiple times."],
191
186
  1,
192
187
  );
193
188
  await testCase(
194
- ["--flag=42", "required1", "subcommand", "required2"],
189
+ ["--flag=42", "req1", "sub", "req2"],
195
190
  [],
196
- [subcommandUsage, 'Error: --flag: value: Not a boolean: "42"'],
191
+ [subUsage, 'Error: --flag: value: Not a boolean: "42".'],
197
192
  1,
198
193
  );
199
194
  await testCase(
200
- ["--flag=no", "required1", "subcommand", "required2"],
201
- ["Has executed root command", "Has executed subcommand"],
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", "required1", "subcommand", "required2"],
207
- ["Has executed root command", "Has executed subcommand"],
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", "required1", "subcommand", "required2"],
213
- ["Has executed root command", "Has executed subcommand"],
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", "required1", "subcommand", "required2"],
215
+ ["--invalid", "req1", "sub", "req2"],
221
216
  [],
222
217
  [
223
218
  rootUsage,
224
- 'Error: Unknown option: "--invalid": did you mean: --single-value, --help, --flag ?',
219
+ 'Error: Unknown option: "--invalid". Did you mean: --single-value, --help, --flag, ... ?',
225
220
  ],
226
221
  1,
227
222
  );
228
223
  await testCase(
229
- ["required1", "subcommand", "required2", "--nope"],
224
+ ["req1", "sub", "req2", "--nope"],
230
225
  [],
231
226
  [
232
- subcommandUsage,
233
- 'Error: Unknown option: "--nope": did you mean: --help, --flag, --repeatable ?',
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
- ["required1", "subcommand", "required2", "--url"],
233
+ ["req1", "sub", "req2", "--url"],
239
234
  [],
240
- [subcommandUsage, "Error: --url: Requires a value, but got end of input"],
235
+ [subUsage, "Error: --url: Requires a value, but got end of input."],
241
236
  1,
242
237
  );
243
238
  await testCase(
244
- ["required1", "subcommand", "required2", "--url", "--", "url"],
239
+ ["req1", "sub", "req2", "--url", "--", "url"],
245
240
  [],
246
- [subcommandUsage, 'Error: --url: Requires a value before "--"'],
241
+ [subUsage, 'Error: --url: Requires a value but got: "--".'],
247
242
  1,
248
243
  );
249
244
  await testCase(
250
- ["required1", "subcommand", "required2", "--url", "--url"],
245
+ ["req1", "sub", "req2", "--url", "--url"],
251
246
  [],
252
- [subcommandUsage, 'Error: --url: Requires a value, but got: "--url"'],
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>: Is required, but was not provided"],
255
+ [rootUsage, "Error: <subcommand>: Missing argument. Did you mean: sub ?"],
261
256
  1,
262
257
  );
263
258
  await testCase(
264
- ["invalid", "subcommand"],
259
+ ["invalid", "sub"],
265
260
  [],
266
261
  [
267
- subcommandUsage,
268
- 'Error: <required1>: Unknown value: "invalid": did you mean: "required1-bis", "required1" ?',
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", "subcommand", "required2"],
268
+ ["invalid", "sub", "req2"],
274
269
  [],
275
270
  [
276
- subcommandUsage,
277
- 'Error: <required1>: Unknown value: "invalid": did you mean: "required1-bis", "required1" ?',
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
- ["required1", "subcommand", "invalid"],
277
+ ["req1", "sub", "invalid"],
283
278
  [],
284
279
  [
285
- subcommandUsage,
286
- 'Error: <required2>: Unknown value: "invalid": did you mean: "required2-bis", "required2" ?',
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", "subcommand", "invalid"],
286
+ ["invalid", "sub", "invalid"],
292
287
  [],
293
288
  [
294
- subcommandUsage,
295
- 'Error: <required1>: Unknown value: "invalid": did you mean: "required1-bis", "required1" ?',
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", "required1", "subcommand", "required2"],
297
+ ["--single-value=dodo", "req1", "sub", "req2"],
303
298
  [],
304
299
  [
305
- subcommandUsage,
306
- 'Error: --single-value: <enum(number)>: from: enum(string): Unknown value: "dodo": did you mean: "42", "43" ?',
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
- ["required1", "subcommand", "required2", "--single-value=44"],
306
+ ["req1", "sub", "req2", "--single-value=44"],
312
307
  [],
313
308
  [
314
- subcommandUsage,
315
- 'Error: --single-value: <enum(number)>: from: enum(string): Unknown value: "44": did you mean: "42", "43" ?',
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 subcommand-only option failures
315
+ // Test sub-only option failures
321
316
  await testCase(
322
- ["--url", "not-a-url", "required1", "subcommand", "required2"],
317
+ ["--url", "not-a-url", "req1", "sub", "req2"],
323
318
  [],
324
319
  [
325
320
  rootUsage,
326
- 'Error: Unknown option: "--url": did you mean: --help, -r, --version ?',
321
+ 'Error: Unknown option: "--url". Did you mean: --help, -r, --version, ... ?',
327
322
  ],
328
323
  1,
329
324
  );
330
325
  await testCase(
331
- ["required1", "subcommand", "required2", "--url", "not-a-url"],
326
+ ["req1", "sub", "req2", "--url", "not-a-url"],
332
327
  [],
333
- [subcommandUsage, 'Error: --url: <url>: Not an URL: "not-a-url"'],
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
- "required1",
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
- [subcommandUsage, "Error: --single-value: Must not be set multiple times"],
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
- ["required1", "subcommand", "required2", "-f"],
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
- ["required1", "subcommand", "required2", "-flag"],
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
- ["required1", "subcommand", "required2", "--uri"],
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
- ["required1", "subcommand", "required2", "--single-"],
366
+ ["req1", "sub", "req2", "--single-"],
395
367
  [],
396
368
  [
397
- subcommandUsage,
398
- 'Error: Unknown option: "--single-": did you mean: --single-value, --help, --flag ?',
369
+ subUsage,
370
+ 'Error: Unknown option: "--single-". Did you mean: --single-value ?',
399
371
  ],
400
372
  1,
401
373
  );
402
374
  await testCase(
403
- ["required-bis1", "subcommand", "required2"],
375
+ ["1req", "sub", "req2"],
404
376
  [],
405
377
  [
406
- subcommandUsage,
407
- 'Error: <required1>: Unknown value: "required-bis1": did you mean: "required1-bis", "required1" ?',
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
- ["required1", "subcomm"],
384
+ ["req1", "subcomm"],
413
385
  [],
414
386
  [
415
387
  rootUsage,
416
- 'Error: <subcommand>: Unknown name: "subcomm": did you mean: subcommand ?',
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
- defaultIfNotSpecified: () => 42,
434
+ fallbackValueIfAbsent: () => 42,
463
435
  }),
464
436
  },
465
437
  positionals: [
466
438
  positionalRequired({
467
- type: typeChoice("required1", ["required1", "required1-bis"]),
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
- subcommand: command(
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("required2", ["required2", "required2-bis"]),
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 subcommand`);
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}+: did you mean: {{--help}@darkCyan}+, {{--flag}@darkCyan}+, {{--repeatable}@darkCyan}+ ?',
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}+: did you mean: {{--repeatable}@darkCyan}+, {{--help}@darkCyan}+, {{--flag}@darkCyan}+ ?',
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
  },
Binary file