cli-kiss 0.2.4 → 0.2.6
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 +159 -167
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/docs/.vitepress/config.mts +3 -2
- package/docs/.vitepress/theme/style.css +6 -2
- package/docs/guide/01_getting_started.md +12 -13
- package/docs/guide/02_commands.md +12 -29
- package/docs/guide/03_options.md +16 -25
- package/docs/guide/04_positionals.md +45 -55
- package/docs/guide/05_input_types.md +134 -0
- package/docs/guide/06_run_as_cli.md +143 -0
- package/docs/index.md +3 -2
- package/docs/public/favicon.ico +0 -0
- package/docs/public/hero.png +0 -0
- package/package.json +1 -1
- package/src/index.ts +0 -2
- package/src/lib/Command.ts +14 -35
- package/src/lib/Operation.ts +13 -4
- package/src/lib/Option.ts +118 -162
- package/src/lib/Positional.ts +37 -62
- package/src/lib/Reader.ts +3 -3
- package/src/lib/Run.ts +76 -49
- package/src/lib/Type.ts +227 -143
- package/src/lib/Typo.ts +55 -23
- package/src/lib/Usage.ts +30 -45
- package/tests/unit.Reader.parsings.ts +50 -0
- package/tests/unit.command.execute.ts +13 -13
- package/tests/unit.command.usage.ts +60 -54
- package/tests/unit.runner.colors.ts +199 -0
- package/tests/unit.runner.cycle.ts +69 -55
- package/tests/unit.runner.errors.ts +12 -20
- package/docs/guide/05_types.md +0 -132
- package/docs/guide/06_run.md +0 -160
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ type ReaderOptionKey = (string | {
|
|
|
11
11
|
*/
|
|
12
12
|
type ReaderOptionParsing = {
|
|
13
13
|
consumeShortGroup: boolean;
|
|
14
|
-
consumeNextArg: (inlined: string | null, separated: Array<string>,
|
|
14
|
+
consumeNextArg: (inlined: string | null, separated: Array<string>, nextArg: string | undefined) => boolean;
|
|
15
15
|
};
|
|
16
16
|
/**
|
|
17
17
|
* Result of parsing an option, including its inlined value and any following separated values.
|
|
@@ -105,17 +105,17 @@ declare class ReaderArgs {
|
|
|
105
105
|
|
|
106
106
|
/**
|
|
107
107
|
* Decodes a raw CLI string into a typed value.
|
|
108
|
-
* A pair of a human-readable `content` name
|
|
108
|
+
* A pair of a human-readable `content` name and a `decoder` function.
|
|
109
109
|
*
|
|
110
|
-
* Built-in: {@link
|
|
111
|
-
* {@link typeInteger}, {@link
|
|
112
|
-
* Composite: {@link
|
|
110
|
+
* Built-in: {@link type}, {@link typeBoolean}, {@link typeNumber},
|
|
111
|
+
* {@link typeInteger}, {@link typeDatetime}, {@link typeUrl}.
|
|
112
|
+
* Composite: {@link typeChoice}, {@link typeConverted}, {@link typeTuple}, {@link typeList}.
|
|
113
113
|
*
|
|
114
114
|
* @typeParam Value - Type produced by the decoder.
|
|
115
115
|
*/
|
|
116
116
|
type Type<Value> = {
|
|
117
117
|
/**
|
|
118
|
-
* Human-readable name shown in help and errors (e.g. `"
|
|
118
|
+
* Human-readable name shown in help and errors (e.g. `"name"`, `"number"`).
|
|
119
119
|
*/
|
|
120
120
|
content: string;
|
|
121
121
|
/**
|
|
@@ -133,71 +133,73 @@ type Type<Value> = {
|
|
|
133
133
|
*
|
|
134
134
|
* @example
|
|
135
135
|
* ```ts
|
|
136
|
-
* typeBoolean.decoder("true") // → true
|
|
137
|
-
* typeBoolean.decoder("yes") // → true
|
|
138
|
-
* typeBoolean.decoder("y") // → true
|
|
139
|
-
* typeBoolean.decoder("false") // → false
|
|
140
|
-
* typeBoolean.decoder("no") // → false
|
|
141
|
-
* typeBoolean.decoder("n") // → false
|
|
136
|
+
* typeBoolean("flag").decoder("true") // → true
|
|
137
|
+
* typeBoolean("flag").decoder("yes") // → true
|
|
138
|
+
* typeBoolean("flag").decoder("y") // → true
|
|
139
|
+
* typeBoolean("flag").decoder("false") // → false
|
|
140
|
+
* typeBoolean("flag").decoder("no") // → false
|
|
141
|
+
* typeBoolean("flag").decoder("n") // → false
|
|
142
142
|
* ```
|
|
143
143
|
*/
|
|
144
|
-
declare
|
|
144
|
+
declare function typeBoolean(name?: string): Type<boolean>;
|
|
145
|
+
declare const typeBooleanValuesTrue: Set<string>;
|
|
146
|
+
declare const typeBooleanValuesFalse: Set<string>;
|
|
145
147
|
/**
|
|
146
148
|
* Parses a date/time string via `Date.parse`.
|
|
147
149
|
* Accepts any format supported by `Date.parse`, including ISO 8601.
|
|
148
150
|
*
|
|
149
151
|
* @example
|
|
150
152
|
* ```ts
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
153
|
+
* typeDatetime("my-datetime").decoder("2024-01-15") // → Date object for 2024-01-15
|
|
154
|
+
* typeDatetime("my-datetime").decoder("2024-01-15T13:45:30Z") // → Date object for 2024-01-15 13:45:30 UTC
|
|
155
|
+
* typeDatetime("my-datetime").decoder("not a date") // throws TypoError
|
|
154
156
|
* ```
|
|
155
157
|
*/
|
|
156
|
-
declare
|
|
158
|
+
declare function typeDatetime(name?: string): Type<Date>;
|
|
157
159
|
/**
|
|
158
160
|
* Parses a string to `number` via `Number()`; `NaN` throws {@link TypoError}.
|
|
159
161
|
*
|
|
160
162
|
* @example
|
|
161
163
|
* ```ts
|
|
162
|
-
* typeNumber.decoder("3.14") // → 3.14
|
|
163
|
-
* typeNumber.decoder("-1") // → -1
|
|
164
|
-
* typeNumber.decoder("hello") // throws
|
|
164
|
+
* typeNumber("my-number").decoder("3.14") // → 3.14
|
|
165
|
+
* typeNumber("my-number").decoder("-1") // → -1
|
|
166
|
+
* typeNumber("my-number").decoder("hello") // throws
|
|
165
167
|
* ```
|
|
166
168
|
*/
|
|
167
|
-
declare
|
|
169
|
+
declare function typeNumber(name?: string): Type<number>;
|
|
168
170
|
/**
|
|
169
171
|
* Parses an integer string to `bigint` via `BigInt()`.
|
|
170
172
|
* Floats and non-numeric strings throw {@link TypoError}.
|
|
171
173
|
*
|
|
172
174
|
* @example
|
|
173
175
|
* ```ts
|
|
174
|
-
* typeInteger.decoder("42") // → 42n
|
|
175
|
-
* typeInteger.decoder("3.14") // throws
|
|
176
|
-
* typeInteger.decoder("abc") // throws
|
|
176
|
+
* typeInteger("my-integer").decoder("42") // → 42n
|
|
177
|
+
* typeInteger("my-integer").decoder("3.14") // throws
|
|
178
|
+
* typeInteger("my-integer").decoder("abc") // throws
|
|
177
179
|
* ```
|
|
178
180
|
*/
|
|
179
|
-
declare
|
|
181
|
+
declare function typeInteger(name?: string): Type<bigint>;
|
|
180
182
|
/**
|
|
181
183
|
* Parses an absolute URL string to a `URL` object.
|
|
182
184
|
* Relative or malformed URLs throw {@link TypoError}.
|
|
183
185
|
*
|
|
184
186
|
* @example
|
|
185
187
|
* ```ts
|
|
186
|
-
* typeUrl.decoder("https://example.com") // → URL { href: "https://example.com/", ... }
|
|
187
|
-
* typeUrl.decoder("not-a-url") // throws
|
|
188
|
+
* typeUrl("my-url").decoder("https://example.com") // → URL { href: "https://example.com/", ... }
|
|
189
|
+
* typeUrl("my-url").decoder("not-a-url") // throws
|
|
188
190
|
* ```
|
|
189
191
|
*/
|
|
190
|
-
declare
|
|
192
|
+
declare function typeUrl(name?: string): Type<URL>;
|
|
191
193
|
/**
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
+
* A named type that accepts any string as input.
|
|
195
|
+
* @param name - Name shown in help and errors (e.g. `"my-value"`).
|
|
194
196
|
* @example
|
|
195
197
|
* ```ts
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
+
* type("greeting").decoder("hello") // → "hello"
|
|
199
|
+
* type("greeting").decoder("") // → ""
|
|
198
200
|
* ```
|
|
199
201
|
*/
|
|
200
|
-
declare
|
|
202
|
+
declare function type(name?: string): Type<string>;
|
|
201
203
|
/**
|
|
202
204
|
* Chains `before`'s decoder with an `after` transformation.
|
|
203
205
|
* `before` errors are prefixed with `"from: <content>"` for traceability.
|
|
@@ -205,45 +207,54 @@ declare const typeString: Type<string>;
|
|
|
205
207
|
* @typeParam Before - Intermediate type from `before.decoder`.
|
|
206
208
|
* @typeParam After - Final type from `after.decoder`.
|
|
207
209
|
*
|
|
208
|
-
* @param
|
|
209
|
-
* @param
|
|
210
|
-
* @param
|
|
211
|
-
* @param after.decoder - Converts a `Before` value to `After`.
|
|
210
|
+
* @param name - Name shown in help and errors (e.g. `"my-value"`).
|
|
211
|
+
* @param before - Base type to decode the raw string.
|
|
212
|
+
* @param mapper - Transforms `before`'s output to the final value; errors are wrapped with context.
|
|
212
213
|
* @returns A {@link Type}`<After>`.
|
|
213
214
|
*
|
|
214
215
|
* @example
|
|
215
216
|
* ```ts
|
|
216
|
-
* const typePort =
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
* if (n < 1 || n > 65535) throw new Error("Out of range");
|
|
220
|
-
* return n;
|
|
221
|
-
* },
|
|
217
|
+
* const typePort = typeConverted("port", typeNumber(), (n) => {
|
|
218
|
+
* if (n < 1 || n > 65535) throw new Error("Out of range");
|
|
219
|
+
* return n;
|
|
222
220
|
* });
|
|
223
221
|
* // "--port 8080" → 8080
|
|
224
222
|
* // "--port 99999" → TypoError: --port: <PORT>: Port: Out of range
|
|
225
223
|
* ```
|
|
226
224
|
*/
|
|
227
|
-
declare function
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
225
|
+
declare function typeConverted<Before, After>(name: string, before: Type<Before>, mapper: (value: Before) => After): Type<After>;
|
|
226
|
+
/**
|
|
227
|
+
* Adds a name to a {@link Type} for clearer error messages and help text.
|
|
228
|
+
*
|
|
229
|
+
* @param name - Name to use for the type.
|
|
230
|
+
* @param type - Base type to name.
|
|
231
|
+
* @returns A {@link Type} with the given name.
|
|
232
|
+
*/
|
|
233
|
+
declare function typeRenamed<Value>(type: Type<Value>, name: string): Type<Value>;
|
|
234
|
+
/**
|
|
235
|
+
* Creates a {@link Type} for filesystem paths with optional existence checks.
|
|
236
|
+
* @param checks - Optional checks for path existence and type (file/directory).
|
|
237
|
+
* @returns A {@link Type}`<string>` representing the path.
|
|
238
|
+
*/
|
|
239
|
+
declare function typePath(name?: string, checks?: {
|
|
240
|
+
checkSyncExistAs?: "file" | "directory" | "anything";
|
|
241
|
+
}): Type<string>;
|
|
231
242
|
/**
|
|
232
243
|
* Creates a {@link Type}`<string>` that only accepts a fixed set of values.
|
|
233
244
|
* Out-of-set inputs throw {@link TypoError} listing up to 5 valid options.
|
|
234
245
|
*
|
|
235
|
-
* @param
|
|
246
|
+
* @param name - Name shown in help and errors.
|
|
236
247
|
* @param values - Ordered list of accepted values.
|
|
237
248
|
* @returns A {@link Type}`<string>`.
|
|
238
249
|
*
|
|
239
250
|
* @example
|
|
240
251
|
* ```ts
|
|
241
|
-
* const typeEnv =
|
|
252
|
+
* const typeEnv = typeChoice("environment", ["dev", "staging", "prod"]);
|
|
242
253
|
* typeEnv.decoder("prod") // → "prod"
|
|
243
254
|
* typeEnv.decoder("unknown") // throws TypoError: Invalid value: "unknown" (expected one of: "dev" | "staging" | "prod")
|
|
244
255
|
* ```
|
|
245
256
|
*/
|
|
246
|
-
declare function
|
|
257
|
+
declare function typeChoice<const Value extends string>(name: string, values: Array<Value>, caseSensitive?: boolean): Type<Value>;
|
|
247
258
|
/**
|
|
248
259
|
* Splits a delimited string into a typed tuple.
|
|
249
260
|
* Each part is decoded by the corresponding element type; wrong count or decode failure throws {@link TypoError}.
|
|
@@ -256,7 +267,7 @@ declare function typeOneOf<const Value extends string>(content: string, values:
|
|
|
256
267
|
*
|
|
257
268
|
* @example
|
|
258
269
|
* ```ts
|
|
259
|
-
* const typePoint = typeTuple([typeNumber, typeNumber]);
|
|
270
|
+
* const typePoint = typeTuple([typeNumber("x"), typeNumber("y")]);
|
|
260
271
|
* typePoint.decoder("3.14,2.71") // → [3.14, 2.71]
|
|
261
272
|
* typePoint.decoder("1,2,3") // → [1, 2]
|
|
262
273
|
* typePoint.decoder("x,2") // throws TypoError: at 0: Number: Unable to parse: "x"
|
|
@@ -282,7 +293,7 @@ declare function typeTuple<const Elements extends Array<any>>(elementTypes: {
|
|
|
282
293
|
* typeNumbers.decoder("1,2,3") // → [1, 2, 3]
|
|
283
294
|
* typeNumbers.decoder("1,x,3") // throws TypoError: at 1: Number: Unable to parse: "x"
|
|
284
295
|
*
|
|
285
|
-
* const typePaths = typeList(
|
|
296
|
+
* const typePaths = typeList(typePath(), ":");
|
|
286
297
|
* typePaths.decoder("/usr/bin:/usr/local/bin") // → ["/usr/bin", "/usr/local/bin"]
|
|
287
298
|
* ```
|
|
288
299
|
*/
|
|
@@ -298,6 +309,10 @@ type TypoColor = "darkBlack" | "darkRed" | "darkGreen" | "darkYellow" | "darkBlu
|
|
|
298
309
|
* All fields are optional; ignored entirely in `"none"` mode.
|
|
299
310
|
*/
|
|
300
311
|
type TypoStyle = {
|
|
312
|
+
/**
|
|
313
|
+
* Letter case.
|
|
314
|
+
*/
|
|
315
|
+
case?: "upper" | "lower";
|
|
301
316
|
/**
|
|
302
317
|
* Foreground (text) color.
|
|
303
318
|
*/
|
|
@@ -428,7 +443,7 @@ declare class TypoGrid {
|
|
|
428
443
|
* Renders as an array of styled, column-padded strings.
|
|
429
444
|
*
|
|
430
445
|
* @param typoSupport - Rendering mode.
|
|
431
|
-
* @returns
|
|
446
|
+
* @returns Array of styled strings.
|
|
432
447
|
*/
|
|
433
448
|
computeStyledLines(typoSupport: TypoSupport): Array<string>;
|
|
434
449
|
}
|
|
@@ -477,16 +492,12 @@ declare class TypoSupport {
|
|
|
477
492
|
static tty(): TypoSupport;
|
|
478
493
|
/**
|
|
479
494
|
* Deterministic textual styling for snapshot tests.
|
|
480
|
-
* Style flags appear as suffixes: `{text}@color`, `{text}+` (bold), `{text}-` (dim),
|
|
481
|
-
* `{text}*` (italic), `{text}_` (underline), `{text}~` (strikethrough).
|
|
482
495
|
*/
|
|
483
496
|
static mock(): TypoSupport;
|
|
484
497
|
/**
|
|
485
|
-
* Auto-detects styling mode from the process environment.
|
|
486
|
-
* `FORCE_COLOR=0` / `NO_COLOR` → none; `FORCE_COLOR` (truthy) / `isTTY` → tty; else → none.
|
|
487
|
-
* Falls back to none if `process` is unavailable.
|
|
498
|
+
* Auto-detects styling mode from the process environment on best-effort basis.
|
|
488
499
|
*/
|
|
489
|
-
static
|
|
500
|
+
static inferFromEnv(): TypoSupport;
|
|
490
501
|
/**
|
|
491
502
|
* Applies `typoStyle` to `value` according to the current mode.
|
|
492
503
|
*
|
|
@@ -510,9 +521,12 @@ declare class TypoSupport {
|
|
|
510
521
|
type UsageCommand = {
|
|
511
522
|
/**
|
|
512
523
|
* Segments of the usage line
|
|
513
|
-
* (e.g. `my-cli <POSITIONAL> subcommand <ANOTHER_POSITIONAL>`).
|
|
514
524
|
*/
|
|
515
|
-
segments: Array<
|
|
525
|
+
segments: Array<{
|
|
526
|
+
positional: string;
|
|
527
|
+
} | {
|
|
528
|
+
subcommand: string;
|
|
529
|
+
}>;
|
|
516
530
|
/**
|
|
517
531
|
* Command metadata.
|
|
518
532
|
*/
|
|
@@ -530,27 +544,6 @@ type UsageCommand = {
|
|
|
530
544
|
*/
|
|
531
545
|
options: Array<UsageOption>;
|
|
532
546
|
};
|
|
533
|
-
/**
|
|
534
|
-
* One segment of the usage line.
|
|
535
|
-
*/
|
|
536
|
-
type UsageSegment = {
|
|
537
|
-
positional: string;
|
|
538
|
-
} | {
|
|
539
|
-
subcommand: string;
|
|
540
|
-
};
|
|
541
|
-
/**
|
|
542
|
-
* Usage metadata. Produced by {@link Operation.generateUsage}, consumed when building {@link UsageCommand}.
|
|
543
|
-
*/
|
|
544
|
-
type UsageOperation = {
|
|
545
|
-
/**
|
|
546
|
-
* Registered options.
|
|
547
|
-
*/
|
|
548
|
-
options: Array<UsageOption>;
|
|
549
|
-
/**
|
|
550
|
-
* Declared positionals, in order.
|
|
551
|
-
*/
|
|
552
|
-
positionals: Array<UsagePositional>;
|
|
553
|
-
};
|
|
554
547
|
/**
|
|
555
548
|
* Positional metadata for the `Positionals:` section of help.
|
|
556
549
|
*/
|
|
@@ -558,16 +551,15 @@ type UsagePositional = {
|
|
|
558
551
|
/**
|
|
559
552
|
* Help text.
|
|
560
553
|
*/
|
|
561
|
-
description
|
|
554
|
+
description?: string | undefined;
|
|
562
555
|
/**
|
|
563
556
|
* Short note shown in parentheses.
|
|
564
557
|
*/
|
|
565
|
-
hint
|
|
558
|
+
hint?: string | undefined;
|
|
566
559
|
/**
|
|
567
560
|
* Placeholder label shown in the usage line and the `Positionals:` section.
|
|
568
|
-
* Required: `<NAME>`, optional: `[NAME]`, variadic: `[NAME]...`.
|
|
569
561
|
*/
|
|
570
|
-
label:
|
|
562
|
+
label: string;
|
|
571
563
|
};
|
|
572
564
|
/**
|
|
573
565
|
* Entry in the `Subcommands:` section.
|
|
@@ -580,11 +572,11 @@ type UsageSubcommand = {
|
|
|
580
572
|
/**
|
|
581
573
|
* From {@link CommandInformation.description}.
|
|
582
574
|
*/
|
|
583
|
-
description
|
|
575
|
+
description?: string | undefined;
|
|
584
576
|
/**
|
|
585
577
|
* From {@link CommandInformation.hint}.
|
|
586
578
|
*/
|
|
587
|
-
hint
|
|
579
|
+
hint?: string | undefined;
|
|
588
580
|
};
|
|
589
581
|
/**
|
|
590
582
|
* Option metadata for the `Options:` section of help.
|
|
@@ -593,27 +585,27 @@ type UsageOption = {
|
|
|
593
585
|
/**
|
|
594
586
|
* Short-form name without `-` (e.g. `"v"`).
|
|
595
587
|
*/
|
|
596
|
-
short
|
|
588
|
+
short?: string | undefined;
|
|
597
589
|
/**
|
|
598
590
|
* Long-form name without `--` (e.g. `"verbose"`).
|
|
599
591
|
*/
|
|
600
|
-
long:
|
|
592
|
+
long: string;
|
|
601
593
|
/**
|
|
602
|
-
*
|
|
594
|
+
* Value placeholder in help (e.g. `"<FILE>"`).
|
|
603
595
|
*/
|
|
604
|
-
|
|
596
|
+
label?: string | undefined;
|
|
605
597
|
/**
|
|
606
|
-
*
|
|
598
|
+
* Extra annotation appended to the option label in help.
|
|
607
599
|
*/
|
|
608
|
-
|
|
600
|
+
annotation?: string | undefined;
|
|
609
601
|
/**
|
|
610
|
-
*
|
|
602
|
+
* Help text.
|
|
611
603
|
*/
|
|
612
|
-
|
|
604
|
+
description?: string | undefined;
|
|
613
605
|
/**
|
|
614
|
-
*
|
|
606
|
+
* Short note shown in parentheses.
|
|
615
607
|
*/
|
|
616
|
-
|
|
608
|
+
hint?: string | undefined;
|
|
617
609
|
};
|
|
618
610
|
/**
|
|
619
611
|
* Converts a {@link UsageCommand} model into an array of styled lines ready to be
|
|
@@ -627,16 +619,16 @@ type UsageOption = {
|
|
|
627
619
|
* <detail lines...>
|
|
628
620
|
*
|
|
629
621
|
* Positionals:
|
|
630
|
-
* <
|
|
622
|
+
* <label> <description> (<hint>)
|
|
631
623
|
*
|
|
632
624
|
* Subcommands:
|
|
633
625
|
* <name> <description> (<hint>)
|
|
634
626
|
*
|
|
635
627
|
* Options:
|
|
636
|
-
* -s, --long <
|
|
628
|
+
* -s, --long <label><annotation> <description> (<hint>)
|
|
637
629
|
*
|
|
638
630
|
* Examples:
|
|
639
|
-
* <
|
|
631
|
+
* <explanation>
|
|
640
632
|
* <command line>
|
|
641
633
|
*
|
|
642
634
|
* ```
|
|
@@ -660,7 +652,7 @@ type UsageOption = {
|
|
|
660
652
|
* ```
|
|
661
653
|
*/
|
|
662
654
|
declare function usageToStyledLines(params: {
|
|
663
|
-
cliName:
|
|
655
|
+
cliName: string;
|
|
664
656
|
usage: UsageCommand;
|
|
665
657
|
typoSupport: TypoSupport;
|
|
666
658
|
}): string[];
|
|
@@ -697,15 +689,15 @@ type OptionDecoder<Value> = {
|
|
|
697
689
|
/**
|
|
698
690
|
* Creates a boolean flag option (`--verbose`, optionally `--flag=no`).
|
|
699
691
|
*
|
|
700
|
-
* Parsing: absent →
|
|
701
|
-
* specified more than once → {@link TypoError}.
|
|
692
|
+
* Parsing: absent → default value; `--flag` / `--flag=yes` → `true`; `--flag=no` → `false`;
|
|
693
|
+
* specified more than once → throws {@link TypoError}.
|
|
702
694
|
*
|
|
703
695
|
* @param definition.long - Long-form name (without `--`).
|
|
704
696
|
* @param definition.short - Short-form name (without `-`).
|
|
705
697
|
* @param definition.description - Help text.
|
|
706
698
|
* @param definition.hint - Short note shown in parentheses.
|
|
707
699
|
* @param definition.aliases - Additional names.
|
|
708
|
-
* @param definition.default - Default when absent.
|
|
700
|
+
* @param definition.default - Default value when absent.
|
|
709
701
|
* @returns An {@link Option}`<boolean>`.
|
|
710
702
|
*
|
|
711
703
|
* @example
|
|
@@ -715,15 +707,20 @@ type OptionDecoder<Value> = {
|
|
|
715
707
|
* short: "v",
|
|
716
708
|
* description: "Enable verbose output",
|
|
717
709
|
* });
|
|
710
|
+
* // Usage:
|
|
711
|
+
* // my-cli → false
|
|
712
|
+
* // my-cli --verbose → true
|
|
713
|
+
* // my-cli --verbose=yes → true
|
|
714
|
+
* // my-cli -v=no → false
|
|
718
715
|
* ```
|
|
719
716
|
*/
|
|
720
717
|
declare function optionFlag(definition: {
|
|
721
|
-
long:
|
|
718
|
+
long: string;
|
|
722
719
|
short?: string;
|
|
723
720
|
description?: string;
|
|
724
721
|
hint?: string;
|
|
725
722
|
aliases?: {
|
|
726
|
-
longs?: Array<
|
|
723
|
+
longs?: Array<string>;
|
|
727
724
|
shorts?: Array<string>;
|
|
728
725
|
};
|
|
729
726
|
default?: boolean;
|
|
@@ -731,7 +728,7 @@ declare function optionFlag(definition: {
|
|
|
731
728
|
/**
|
|
732
729
|
* Creates an option that accepts exactly one value (e.g. `--output dist/`).
|
|
733
730
|
*
|
|
734
|
-
* Parsing: absent → `
|
|
731
|
+
* Parsing: absent → `defaultValue()`; once → decoded with `type`; more than once → {@link TypoError}.
|
|
735
732
|
* Value syntax: `--long value`, `--long=value`, `-s value`, `-s=value`, `-svalue`.
|
|
736
733
|
*
|
|
737
734
|
* @typeParam Value - Type produced by the decoder.
|
|
@@ -741,9 +738,9 @@ declare function optionFlag(definition: {
|
|
|
741
738
|
* @param definition.description - Help text.
|
|
742
739
|
* @param definition.hint - Short note shown in parentheses.
|
|
743
740
|
* @param definition.aliases - Additional names.
|
|
744
|
-
* @param definition.label - Value placeholder in help. Defaults to uppercased `type.content`.
|
|
745
741
|
* @param definition.type - Decoder for the raw string value.
|
|
746
|
-
* @param definition.
|
|
742
|
+
* @param definition.valueWhenNotDefined - Default value when the option is not specified at all.
|
|
743
|
+
* @param definition.valueWhenNotInlined - Default value when the option is specified without an inline value (e.g. `--option` or `-o`).
|
|
747
744
|
* @returns An {@link Option}`<Value>`.
|
|
748
745
|
*
|
|
749
746
|
* @example
|
|
@@ -751,25 +748,28 @@ declare function optionFlag(definition: {
|
|
|
751
748
|
* const outputOption = optionSingleValue({
|
|
752
749
|
* long: "output",
|
|
753
750
|
* short: "o",
|
|
754
|
-
* type:
|
|
755
|
-
* label: "PATH",
|
|
751
|
+
* type: typePath(),
|
|
756
752
|
* description: "Output directory",
|
|
757
|
-
*
|
|
753
|
+
* valueWhenNotDefined: () => "dist",
|
|
758
754
|
* });
|
|
755
|
+
* // Usage:
|
|
756
|
+
* // my-cli → "dist"
|
|
757
|
+
* // my-cli --output folder → "folder"
|
|
758
|
+
* // my-cli -o folder → "folder"
|
|
759
759
|
* ```
|
|
760
760
|
*/
|
|
761
761
|
declare function optionSingleValue<Value>(definition: {
|
|
762
|
-
long:
|
|
762
|
+
long: string;
|
|
763
763
|
short?: string;
|
|
764
764
|
description?: string;
|
|
765
765
|
hint?: string;
|
|
766
766
|
aliases?: {
|
|
767
|
-
longs?: Array<
|
|
767
|
+
longs?: Array<string>;
|
|
768
768
|
shorts?: Array<string>;
|
|
769
769
|
};
|
|
770
|
-
label?: Uppercase<string>;
|
|
771
770
|
type: Type<Value>;
|
|
772
|
-
|
|
771
|
+
defaultWhenNotDefined: () => Value;
|
|
772
|
+
defaultWhenNotInlined?: () => Value;
|
|
773
773
|
}): Option<Value>;
|
|
774
774
|
/**
|
|
775
775
|
* Creates an option that collects every occurrence into an array (e.g. `--file a.ts --file b.ts`).
|
|
@@ -784,7 +784,6 @@ declare function optionSingleValue<Value>(definition: {
|
|
|
784
784
|
* @param definition.description - Help text.
|
|
785
785
|
* @param definition.hint - Short note shown in parentheses.
|
|
786
786
|
* @param definition.aliases - Additional names.
|
|
787
|
-
* @param definition.label - Value placeholder in help. Defaults to uppercased `type.content`.
|
|
788
787
|
* @param definition.type - Decoder applied to each raw string value.
|
|
789
788
|
* @returns An {@link Option}`<Array<Value>>`.
|
|
790
789
|
*
|
|
@@ -801,15 +800,14 @@ declare function optionSingleValue<Value>(definition: {
|
|
|
801
800
|
* ```
|
|
802
801
|
*/
|
|
803
802
|
declare function optionRepeatable<Value>(definition: {
|
|
804
|
-
long:
|
|
803
|
+
long: string;
|
|
805
804
|
short?: string;
|
|
806
805
|
description?: string;
|
|
807
806
|
hint?: string;
|
|
808
807
|
aliases?: {
|
|
809
|
-
longs?: Array<
|
|
808
|
+
longs?: Array<string>;
|
|
810
809
|
shorts?: Array<string>;
|
|
811
810
|
};
|
|
812
|
-
label?: Uppercase<string>;
|
|
813
811
|
type: Type<Value>;
|
|
814
812
|
}): Option<Array<Value>>;
|
|
815
813
|
|
|
@@ -845,41 +843,36 @@ type PositionalDecoder<Value> = {
|
|
|
845
843
|
};
|
|
846
844
|
/**
|
|
847
845
|
* Creates a required positional — missing token throws {@link TypoError}.
|
|
848
|
-
* Label defaults to uppercased `type.content` in angle brackets (e.g. `<STRING>`).
|
|
849
846
|
*
|
|
850
847
|
* @typeParam Value - Type produced by the decoder.
|
|
851
848
|
*
|
|
852
849
|
* @param definition.description - Help text.
|
|
853
850
|
* @param definition.hint - Short note shown in parentheses.
|
|
854
|
-
* @param definition.label - Label without brackets; defaults to uppercased `type.content`.
|
|
855
851
|
* @param definition.type - Decoder for the raw token.
|
|
856
852
|
* @returns A {@link Positional}`<Value>`.
|
|
857
853
|
*
|
|
858
854
|
* @example
|
|
859
855
|
* ```ts
|
|
860
856
|
* const namePositional = positionalRequired({
|
|
861
|
-
* type:
|
|
862
|
-
* label: "NAME",
|
|
857
|
+
* type: type("name"),
|
|
863
858
|
* description: "The name to greet",
|
|
864
859
|
* });
|
|
865
|
-
* //
|
|
860
|
+
* // Usage:
|
|
861
|
+
* // my-cli Alice → "Alice"
|
|
866
862
|
* ```
|
|
867
863
|
*/
|
|
868
864
|
declare function positionalRequired<Value>(definition: {
|
|
869
865
|
description?: string;
|
|
870
866
|
hint?: string;
|
|
871
|
-
label?: Uppercase<string>;
|
|
872
867
|
type: Type<Value>;
|
|
873
868
|
}): Positional<Value>;
|
|
874
869
|
/**
|
|
875
870
|
* Creates an optional positional — absent token falls back to `default()`.
|
|
876
|
-
* Label defaults to uppercased `type.content` in square brackets (e.g. `[STRING]`).
|
|
877
871
|
*
|
|
878
872
|
* @typeParam Value - Type produced by the decoder (or the default).
|
|
879
873
|
*
|
|
880
874
|
* @param definition.description - Help text.
|
|
881
875
|
* @param definition.hint - Short note shown in parentheses.
|
|
882
|
-
* @param definition.label - Label without brackets; defaults to uppercased `type.content`.
|
|
883
876
|
* @param definition.type - Decoder for the raw token.
|
|
884
877
|
* @param definition.default - Value when absent. Throw to make it required.
|
|
885
878
|
* @returns A {@link Positional}`<Value>`.
|
|
@@ -887,51 +880,48 @@ declare function positionalRequired<Value>(definition: {
|
|
|
887
880
|
* @example
|
|
888
881
|
* ```ts
|
|
889
882
|
* const greeteePositional = positionalOptional({
|
|
890
|
-
* type:
|
|
891
|
-
* label: "NAME",
|
|
883
|
+
* type: type("name"),
|
|
892
884
|
* description: "Name to greet (default: world)",
|
|
893
885
|
* default: () => "world",
|
|
894
886
|
* });
|
|
895
|
-
* //
|
|
896
|
-
* //
|
|
887
|
+
* // Usage:
|
|
888
|
+
* // my-cli → "world"
|
|
889
|
+
* // my-cli Alice → "Alice"
|
|
897
890
|
* ```
|
|
898
891
|
*/
|
|
899
892
|
declare function positionalOptional<Value>(definition: {
|
|
900
893
|
description?: string;
|
|
901
894
|
hint?: string;
|
|
902
|
-
label?: Uppercase<string>;
|
|
903
895
|
type: Type<Value>;
|
|
904
896
|
default: () => Value;
|
|
905
897
|
}): Positional<Value>;
|
|
906
898
|
/**
|
|
907
899
|
* Creates a variadic positional that collects zero or more remaining tokens into an array.
|
|
908
|
-
*
|
|
900
|
+
* Optionally stops at `endDelimiter` (consumed, not included).
|
|
909
901
|
*
|
|
910
902
|
* @typeParam Value - Type produced by the decoder for each token.
|
|
911
903
|
*
|
|
912
904
|
* @param definition.endDelimiter - Sentinel token that stops collection (consumed, not included).
|
|
913
905
|
* @param definition.description - Help text.
|
|
914
906
|
* @param definition.hint - Short note shown in parentheses.
|
|
915
|
-
* @param definition.label - Label without brackets; defaults to uppercased `type.content`.
|
|
916
907
|
* @param definition.type - Decoder applied to each token.
|
|
917
908
|
* @returns A {@link Positional}`<Array<Value>>`.
|
|
918
909
|
*
|
|
919
910
|
* @example
|
|
920
911
|
* ```ts
|
|
921
912
|
* const filesPositional = positionalVariadics({
|
|
922
|
-
* type:
|
|
923
|
-
* label: "FILE",
|
|
913
|
+
* type: typePath(),
|
|
924
914
|
* description: "Files to process",
|
|
925
915
|
* });
|
|
926
|
-
* //
|
|
927
|
-
* //
|
|
916
|
+
* // Usage:
|
|
917
|
+
* // my-cli → []
|
|
918
|
+
* // my-cli a.ts b.ts c.ts → ["a.ts", "b.ts", "c.ts"]
|
|
928
919
|
* ```
|
|
929
920
|
*/
|
|
930
921
|
declare function positionalVariadics<Value>(definition: {
|
|
931
922
|
endDelimiter?: string;
|
|
932
923
|
description?: string;
|
|
933
924
|
hint?: string;
|
|
934
|
-
label?: Uppercase<string>;
|
|
935
925
|
type: Type<Value>;
|
|
936
926
|
}): Positional<Array<Value>>;
|
|
937
927
|
|
|
@@ -948,7 +938,16 @@ type Operation<Context, Result> = {
|
|
|
948
938
|
/**
|
|
949
939
|
* Returns usage metadata without consuming any arguments.
|
|
950
940
|
*/
|
|
951
|
-
generateUsage():
|
|
941
|
+
generateUsage(): {
|
|
942
|
+
/**
|
|
943
|
+
* Registered options.
|
|
944
|
+
*/
|
|
945
|
+
options: Array<UsageOption>;
|
|
946
|
+
/**
|
|
947
|
+
* Declared positionals, in order.
|
|
948
|
+
*/
|
|
949
|
+
positionals: Array<UsagePositional>;
|
|
950
|
+
};
|
|
952
951
|
/**
|
|
953
952
|
* Consumes args from `readerArgs` and returns an {@link OperationDecoder}.
|
|
954
953
|
*/
|
|
@@ -1001,10 +1000,10 @@ type OperationInterpreter<Context, Result> = {
|
|
|
1001
1000
|
* const greetOperation = operation(
|
|
1002
1001
|
* {
|
|
1003
1002
|
* options: {
|
|
1004
|
-
* loud: optionFlag({ long: "loud", description: "Print in uppercase" }),
|
|
1003
|
+
* loud: optionFlag({ long: "loud", description: "Print in uppercase", default: false }),
|
|
1005
1004
|
* },
|
|
1006
1005
|
* positionals: [
|
|
1007
|
-
* positionalRequired({ type:
|
|
1006
|
+
* positionalRequired({ type: type("name"), description: "Name to greet" }),
|
|
1008
1007
|
* ],
|
|
1009
1008
|
* },
|
|
1010
1009
|
* async function (_ctx, { options: { loud }, positionals: [name] }) {
|
|
@@ -1108,10 +1107,12 @@ type CommandInformation = {
|
|
|
1108
1107
|
} | {
|
|
1109
1108
|
option: {
|
|
1110
1109
|
long: string;
|
|
1111
|
-
|
|
1110
|
+
inlined?: string;
|
|
1111
|
+
separated?: Array<string>;
|
|
1112
1112
|
} | {
|
|
1113
1113
|
short: string;
|
|
1114
|
-
|
|
1114
|
+
inlined?: string;
|
|
1115
|
+
separated?: Array<string>;
|
|
1115
1116
|
};
|
|
1116
1117
|
}>;
|
|
1117
1118
|
}>;
|
|
@@ -1131,7 +1132,7 @@ type CommandInformation = {
|
|
|
1131
1132
|
* const greet = command(
|
|
1132
1133
|
* { description: "Greet a user" },
|
|
1133
1134
|
* operation(
|
|
1134
|
-
* { options: {}, positionals: [positionalRequired({ type:
|
|
1135
|
+
* { options: {}, positionals: [positionalRequired({ type: type("name") })] },
|
|
1135
1136
|
* async (_ctx, { positionals: [name] }) => console.log(`Hello, ${name}!`),
|
|
1136
1137
|
* ),
|
|
1137
1138
|
* );
|
|
@@ -1163,7 +1164,7 @@ declare function command<Context, Result>(information: CommandInformation, opera
|
|
|
1163
1164
|
* ```
|
|
1164
1165
|
*/
|
|
1165
1166
|
declare function commandWithSubcommands<Context, Payload, Result>(information: CommandInformation, operation: Operation<Context, Payload>, subcommands: {
|
|
1166
|
-
[subcommand:
|
|
1167
|
+
[subcommand: string]: Command<Payload, Result>;
|
|
1167
1168
|
}): Command<Context, Result>;
|
|
1168
1169
|
/**
|
|
1169
1170
|
* Chains an {@link Operation} and a {@link Command}: `operation` runs first, its
|
|
@@ -1177,21 +1178,13 @@ declare function commandWithSubcommands<Context, Payload, Result>(information: C
|
|
|
1177
1178
|
* @param operation - Runs first; output becomes `subcommand`'s context.
|
|
1178
1179
|
* @param subcommand - Runs after `operation`.
|
|
1179
1180
|
* @returns A {@link Command} composing both stages.
|
|
1180
|
-
*
|
|
1181
|
-
* @example
|
|
1182
|
-
* ```ts
|
|
1183
|
-
* const authenticatedDeploy = commandChained(
|
|
1184
|
-
* { description: "Authenticate then deploy" },
|
|
1185
|
-
* operation(
|
|
1186
|
-
* { options: { token: optionSingleValue({ long: "token", type: typeString, default: () => "" }) }, positionals: [] },
|
|
1187
|
-
* async (_ctx, { options: { token } }) => ({ token }),
|
|
1188
|
-
* ),
|
|
1189
|
-
* command({ description: "Deploy" }, deployOperation),
|
|
1190
|
-
* );
|
|
1191
|
-
* ```
|
|
1192
1181
|
*/
|
|
1193
1182
|
declare function commandChained<Context, Payload, Result>(information: CommandInformation, operation: Operation<Context, Payload>, subcommand: Command<Payload, Result>): Command<Context, Result>;
|
|
1194
1183
|
|
|
1184
|
+
/**
|
|
1185
|
+
* Color selection modes availables
|
|
1186
|
+
*/
|
|
1187
|
+
type RunColorMode = "env" | "always" | "never" | "mock";
|
|
1195
1188
|
/**
|
|
1196
1189
|
* Main entry point: parses CLI arguments, executes the matched command, and exits.
|
|
1197
1190
|
* Handles `--help`, `--version`, usage-on-error, and exit codes.
|
|
@@ -1206,8 +1199,7 @@ declare function commandChained<Context, Payload, Result>(information: CommandIn
|
|
|
1206
1199
|
* @param cliArgs - Raw arguments, typically `process.argv.slice(2)`.
|
|
1207
1200
|
* @param context - Forwarded to the handler.
|
|
1208
1201
|
* @param command - Root {@link Command}.
|
|
1209
|
-
* @param options.
|
|
1210
|
-
* `"mock"` (snapshot-friendly), `undefined` (auto-detect from env).
|
|
1202
|
+
* @param options.colorSetup - Configures color support; enables `--color` flag if set to `"flag"`.
|
|
1211
1203
|
* @param options.usageOnHelp - Enables `--help` flag (default `true`).
|
|
1212
1204
|
* @param options.usageOnError - Prints usage to stderr on parse error (default `true`).
|
|
1213
1205
|
* @param options.buildVersion - Enables `--version`; prints `<cliName> <buildVersion>`.
|
|
@@ -1218,12 +1210,12 @@ declare function commandChained<Context, Payload, Result>(information: CommandIn
|
|
|
1218
1210
|
*
|
|
1219
1211
|
* @example
|
|
1220
1212
|
* ```ts
|
|
1221
|
-
* import { runAndExit, command, operation, positionalRequired,
|
|
1213
|
+
* import { runAndExit, command, operation, positionalRequired, type } from "cli-kiss";
|
|
1222
1214
|
*
|
|
1223
1215
|
* const greetCommand = command(
|
|
1224
1216
|
* { description: "Greet someone" },
|
|
1225
1217
|
* operation(
|
|
1226
|
-
* { options: {}, positionals: [positionalRequired({ type:
|
|
1218
|
+
* { options: {}, positionals: [positionalRequired({ type: type("name") })] },
|
|
1227
1219
|
* async function (_ctx, { positionals: [name] }) {
|
|
1228
1220
|
* console.log(`Hello, ${name}!`);
|
|
1229
1221
|
* },
|
|
@@ -1235,8 +1227,8 @@ declare function commandChained<Context, Payload, Result>(information: CommandIn
|
|
|
1235
1227
|
* });
|
|
1236
1228
|
* ```
|
|
1237
1229
|
*/
|
|
1238
|
-
declare function runAndExit<Context>(cliName:
|
|
1239
|
-
|
|
1230
|
+
declare function runAndExit<Context>(cliName: string, cliArgs: ReadonlyArray<string>, context: Context, command: Command<Context, void>, options?: {
|
|
1231
|
+
colorSetup?: "flag" | RunColorMode | undefined;
|
|
1240
1232
|
usageOnHelp?: boolean | undefined;
|
|
1241
1233
|
usageOnError?: boolean | undefined;
|
|
1242
1234
|
buildVersion?: string | undefined;
|
|
@@ -1244,4 +1236,4 @@ declare function runAndExit<Context>(cliName: Lowercase<string>, cliArgs: Readon
|
|
|
1244
1236
|
onExit?: ((code: number) => never) | undefined;
|
|
1245
1237
|
}): Promise<never>;
|
|
1246
1238
|
|
|
1247
|
-
export { type Command, type CommandDecoder, type CommandInformation, type CommandInterpreter, type Operation, type OperationDecoder, type OperationInterpreter, type Option, type OptionDecoder, type Positional, type PositionalDecoder, ReaderArgs, type ReaderOptionKey, type ReaderOptionParsing, type ReaderOptionValue, type ReaderOptions, type ReaderPositionals, type Type, type TypoColor, TypoError, TypoGrid, TypoString, type TypoStyle, TypoSupport, TypoText, type UsageCommand, type
|
|
1239
|
+
export { type Command, type CommandDecoder, type CommandInformation, type CommandInterpreter, type Operation, type OperationDecoder, type OperationInterpreter, type Option, type OptionDecoder, type Positional, type PositionalDecoder, ReaderArgs, type ReaderOptionKey, type ReaderOptionParsing, type ReaderOptionValue, type ReaderOptions, type ReaderPositionals, type RunColorMode, type Type, type TypoColor, TypoError, TypoGrid, TypoString, type TypoStyle, TypoSupport, TypoText, type UsageCommand, type UsageOption, type UsagePositional, type UsageSubcommand, command, commandChained, commandWithSubcommands, operation, optionFlag, optionRepeatable, optionSingleValue, positionalOptional, positionalRequired, positionalVariadics, runAndExit, type, typeBoolean, typeBooleanValuesFalse, typeBooleanValuesTrue, typeChoice, typeConverted, typeDatetime, typeInteger, typeList, typeNumber, typePath, typeRenamed, typeTuple, typeUrl, typoStyleConstants, typoStyleFailure, typoStyleLogic, typoStyleQuote, typoStyleRegularStrong, typoStyleRegularWeaker, typoStyleTitle, typoStyleUserInput, usageToStyledLines };
|