cli-kiss 0.1.8 → 0.1.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/dist/index.d.ts +1310 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/Command.ts +227 -0
- package/src/lib/Operation.ts +108 -0
- package/src/lib/Option.ts +164 -0
- package/src/lib/Positional.ts +139 -0
- package/src/lib/Reader.ts +110 -0
- package/src/lib/Run.ts +70 -0
- package/src/lib/Type.ts +223 -0
- package/src/lib/Typo.ts +226 -0
- package/src/lib/Usage.ts +43 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,65 +1,482 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An opaque key that uniquely identifies a registered CLI option within a
|
|
3
|
+
* {@link ReaderArgs} instance.
|
|
4
|
+
*
|
|
5
|
+
* Keys are returned by {@link ReaderArgs.registerOption} and passed back to
|
|
6
|
+
* {@link ReaderArgs.getOptionValues} to retrieve the parsed values. The internal
|
|
7
|
+
* representation is intentionally opaque — treat it as a handle, not a string.
|
|
8
|
+
*/
|
|
1
9
|
type ReaderOptionKey = (string | {
|
|
2
10
|
__brand: "ReaderOptionKey";
|
|
3
11
|
}) & {
|
|
4
12
|
__brand: "ReaderOptionKey";
|
|
5
13
|
};
|
|
14
|
+
/**
|
|
15
|
+
* Interface for registering and querying CLI options during argument parsing.
|
|
16
|
+
*
|
|
17
|
+
* {@link ReaderArgs} implements both `ReaderOptions` and {@link ReaderPositionals}.
|
|
18
|
+
* The two interfaces are exposed separately so that option and positional parsing logic
|
|
19
|
+
* can depend only on the capability they need.
|
|
20
|
+
*/
|
|
6
21
|
type ReaderOptions = {
|
|
22
|
+
/**
|
|
23
|
+
* Registers a new option so the parser can recognise it when scanning argument tokens.
|
|
24
|
+
*
|
|
25
|
+
* @param definition.longs - The long-form names (without `--`) for this option.
|
|
26
|
+
* @param definition.shorts - The short-form names (without `-`) for this option.
|
|
27
|
+
* @param definition.valued - When `true`, the option consumes the following token as
|
|
28
|
+
* its value. When `false`, the option is a boolean flag.
|
|
29
|
+
* @returns An opaque {@link ReaderOptionKey} used to retrieve parsed values later.
|
|
30
|
+
* @throws `Error` if any of the given names has already been registered, or if a
|
|
31
|
+
* short name overlaps (is a prefix of, or has as a prefix, another registered short).
|
|
32
|
+
*/
|
|
7
33
|
registerOption(definition: {
|
|
8
34
|
longs: Array<string>;
|
|
9
35
|
shorts: Array<string>;
|
|
10
36
|
valued: boolean;
|
|
11
37
|
}): ReaderOptionKey;
|
|
38
|
+
/**
|
|
39
|
+
* Returns all values collected for the option identified by `key`.
|
|
40
|
+
*
|
|
41
|
+
* @param key - The key returned by a prior {@link ReaderOptions.registerOption} call.
|
|
42
|
+
* @returns An array of raw string values, one per occurrence of the option on the
|
|
43
|
+
* command line. Empty if the option was never provided.
|
|
44
|
+
* @throws `Error` if `key` was not previously registered on this instance.
|
|
45
|
+
*/
|
|
12
46
|
getOptionValues(key: ReaderOptionKey): Array<string>;
|
|
13
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* Interface for consuming positional (non-option) argument tokens during parsing.
|
|
50
|
+
*
|
|
51
|
+
* {@link ReaderArgs} implements both {@link ReaderOptions} and `ReaderPositionals`.
|
|
52
|
+
*/
|
|
14
53
|
type ReaderPositionals = {
|
|
54
|
+
/**
|
|
55
|
+
* Consumes and returns the next positional token from the argument list, skipping
|
|
56
|
+
* any option tokens (which are parsed as side-effects).
|
|
57
|
+
*
|
|
58
|
+
* @returns The next positional string value, or `undefined` if no more positionals
|
|
59
|
+
* are available.
|
|
60
|
+
* @throws {@link TypoError} if an unrecognised option token is encountered while
|
|
61
|
+
* scanning for the next positional.
|
|
62
|
+
*/
|
|
15
63
|
consumePositional(): string | undefined;
|
|
16
64
|
};
|
|
65
|
+
/**
|
|
66
|
+
* The core argument parser for `cli-kiss`. Parses a flat array of raw CLI tokens into
|
|
67
|
+
* named options and positional values.
|
|
68
|
+
*
|
|
69
|
+
* Options must be registered with {@link ReaderArgs.registerOption} **before**
|
|
70
|
+
* {@link ReaderArgs.consumePositional} is called, because the parser needs to know
|
|
71
|
+
* whether each token is an option name, an option value, or a bare positional.
|
|
72
|
+
*
|
|
73
|
+
* **Supported argument syntax:**
|
|
74
|
+
* - Long options: `--name`, `--name value`, `--name=value`
|
|
75
|
+
* - Short options: `-n`, `-n value`, `-n=value`, `-nvalue`, `-abc` (stacked flags)
|
|
76
|
+
* - End-of-options separator: `--` — all subsequent tokens are treated as positionals.
|
|
77
|
+
*
|
|
78
|
+
* In most cases you do not need to use `ReaderArgs` directly; it is created internally
|
|
79
|
+
* by {@link runAsCliAndExit}. It is exposed for advanced use cases such as building
|
|
80
|
+
* custom runners.
|
|
81
|
+
*/
|
|
17
82
|
declare class ReaderArgs {
|
|
18
83
|
#private;
|
|
84
|
+
/**
|
|
85
|
+
* @param args - The raw command-line tokens to parse. Typically `process.argv.slice(2)`.
|
|
86
|
+
* The array is not modified; a read cursor is maintained internally.
|
|
87
|
+
*/
|
|
19
88
|
constructor(args: ReadonlyArray<string>);
|
|
89
|
+
/**
|
|
90
|
+
* Registers a CLI option so the parser can recognise it.
|
|
91
|
+
*
|
|
92
|
+
* All `longs` and `shorts` are associated with the same returned key. Calling
|
|
93
|
+
* `getOptionValues(key)` after parsing will return values collected under any of the
|
|
94
|
+
* registered names.
|
|
95
|
+
*
|
|
96
|
+
* Short names support stacking (e.g. `-abc` is parsed as `-a -b -c`) and inline
|
|
97
|
+
* values (e.g. `-nvalue`). Short names must not be a prefix of, nor have as a prefix,
|
|
98
|
+
* any other registered short name — the parser uses prefix matching to parse stacked
|
|
99
|
+
* shorts, so overlapping prefixes would be ambiguous.
|
|
100
|
+
*
|
|
101
|
+
* @param definition.longs - Long-form names (without `--`).
|
|
102
|
+
* @param definition.shorts - Short-form names (without `-`).
|
|
103
|
+
* @param definition.valued - `true` if the option consumes a value; `false` for flags.
|
|
104
|
+
* @returns An opaque {@link ReaderOptionKey} to pass to {@link ReaderArgs.getOptionValues}.
|
|
105
|
+
* @throws `Error` if any name is already registered or if two short names overlap.
|
|
106
|
+
*/
|
|
20
107
|
registerOption(definition: {
|
|
21
108
|
longs: Array<string>;
|
|
22
109
|
shorts: Array<string>;
|
|
23
110
|
valued: boolean;
|
|
24
111
|
}): ReaderOptionKey;
|
|
112
|
+
/**
|
|
113
|
+
* Returns all raw string values collected for the given option key.
|
|
114
|
+
*
|
|
115
|
+
* @param key - A key previously returned by {@link ReaderArgs.registerOption}.
|
|
116
|
+
* @returns An array of string values, one per occurrence on the command line. For
|
|
117
|
+
* flags this will be `["true"]` per occurrence; for valued options it will be the
|
|
118
|
+
* literal value strings.
|
|
119
|
+
* @throws `Error` if `key` was not registered on this instance.
|
|
120
|
+
*/
|
|
25
121
|
getOptionValues(key: ReaderOptionKey): Array<string>;
|
|
122
|
+
/**
|
|
123
|
+
* Scans forward through the argument list and returns the next bare positional token,
|
|
124
|
+
* consuming and parsing any intervening option tokens as side-effects.
|
|
125
|
+
*
|
|
126
|
+
* Option tokens encountered during the scan are recorded in the internal results map
|
|
127
|
+
* (equivalent to recording their values against their key). Any unrecognised option token
|
|
128
|
+
* causes a {@link TypoError} to be thrown immediately.
|
|
129
|
+
*
|
|
130
|
+
* After `--` is encountered, all remaining tokens are treated as positionals.
|
|
131
|
+
*
|
|
132
|
+
* @returns The next positional string, or `undefined` when the argument list is
|
|
133
|
+
* exhausted.
|
|
134
|
+
* @throws {@link TypoError} if an unrecognised option (long or short) is encountered.
|
|
135
|
+
*/
|
|
26
136
|
consumePositional(): string | undefined;
|
|
27
137
|
}
|
|
28
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Describes how to decode a raw CLI string token into a typed TypeScript value.
|
|
141
|
+
*
|
|
142
|
+
* A `Type` is a pair of:
|
|
143
|
+
* - a `content` string — a human-readable name shown in help/error messages (e.g.
|
|
144
|
+
* `"String"`, `"Number"`, `"Url"`).
|
|
145
|
+
* - a `decoder` function — converts the raw string or throws a {@link TypoError} on
|
|
146
|
+
* invalid input.
|
|
147
|
+
*
|
|
148
|
+
* Built-in types: {@link typeString}, {@link typeBoolean}, {@link typeNumber},
|
|
149
|
+
* {@link typeInteger}, {@link typeDate}, {@link typeUrl}.
|
|
150
|
+
*
|
|
151
|
+
* Composite types: {@link typeOneOf}, {@link typeConverted}, {@link typeTuple},
|
|
152
|
+
* {@link typeList}.
|
|
153
|
+
*
|
|
154
|
+
* @typeParam Value - The TypeScript type that the decoder produces.
|
|
155
|
+
*/
|
|
29
156
|
type Type<Value> = {
|
|
157
|
+
/**
|
|
158
|
+
* Human-readable name for this type, used in help text and error messages.
|
|
159
|
+
* Examples: `"String"`, `"Number"`, `"Url"`.
|
|
160
|
+
*/
|
|
30
161
|
content: string;
|
|
162
|
+
/**
|
|
163
|
+
* Decodes a raw string token into a `Value`.
|
|
164
|
+
*
|
|
165
|
+
* @param value - The raw string from the command line.
|
|
166
|
+
* @returns The decoded value.
|
|
167
|
+
* @throws {@link TypoError} if the value cannot be decoded.
|
|
168
|
+
*/
|
|
31
169
|
decoder(value: string): Value;
|
|
32
170
|
};
|
|
171
|
+
/**
|
|
172
|
+
* A {@link Type} that decodes `"true"` / `"yes"` to `true` and `"false"` / `"no"` to
|
|
173
|
+
* `false` (case-insensitive). Any other value throws a {@link TypoError}.
|
|
174
|
+
*
|
|
175
|
+
* Primarily used internally by {@link optionFlag} for the `--flag=<value>` syntax, but
|
|
176
|
+
* can also be used in positionals or valued options.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* typeBoolean.decoder("yes") // → true
|
|
181
|
+
* typeBoolean.decoder("false") // → false
|
|
182
|
+
* typeBoolean.decoder("1") // throws TypoError
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
33
185
|
declare const typeBoolean: Type<boolean>;
|
|
186
|
+
/**
|
|
187
|
+
* A {@link Type} that parses a date/time string using `Date.parse`.
|
|
188
|
+
*
|
|
189
|
+
* Accepts any format supported by the JavaScript `Date.parse` API, including ISO 8601
|
|
190
|
+
* strings (e.g. `"2024-01-15"`, `"2024-01-15T10:30:00Z"`). Non-parseable values throw
|
|
191
|
+
* a {@link TypoError}.
|
|
192
|
+
*
|
|
193
|
+
* Produces a `Date` object. The decoded value is the result of `new Date(Date.parse(value))`.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```ts
|
|
197
|
+
* typeDate.decoder("2024-01-15") // → Date object for 2024-01-15
|
|
198
|
+
* typeDate.decoder("not a date") // throws TypoError
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
34
201
|
declare const typeDate: Type<Date>;
|
|
202
|
+
/**
|
|
203
|
+
* A {@link Type} that parses a string into a JavaScript `number` using the `Number()`
|
|
204
|
+
* constructor.
|
|
205
|
+
*
|
|
206
|
+
* Accepts integers, floating-point values, and scientific notation (e.g. `"3.14"`,
|
|
207
|
+
* `"-1"`, `"1e10"`). Values that produce `NaN` throw a {@link TypoError}.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```ts
|
|
211
|
+
* typeNumber.decoder("3.14") // → 3.14
|
|
212
|
+
* typeNumber.decoder("-1") // → -1
|
|
213
|
+
* typeNumber.decoder("hello") // throws TypoError
|
|
214
|
+
* ```
|
|
215
|
+
*/
|
|
35
216
|
declare const typeNumber: Type<number>;
|
|
217
|
+
/**
|
|
218
|
+
* A {@link Type} that parses a string into a JavaScript `bigint` using the `BigInt()`
|
|
219
|
+
* constructor.
|
|
220
|
+
*
|
|
221
|
+
* Only accepts valid integer strings (e.g. `"42"`, `"-100"`, `"9007199254740993"`).
|
|
222
|
+
* Floating-point strings or non-numeric values throw a {@link TypoError}.
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```ts
|
|
226
|
+
* typeInteger.decoder("42") // → 42n
|
|
227
|
+
* typeInteger.decoder("3.14") // throws TypoError
|
|
228
|
+
* typeInteger.decoder("abc") // throws TypoError
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
36
231
|
declare const typeInteger: Type<bigint>;
|
|
232
|
+
/**
|
|
233
|
+
* A {@link Type} that parses a string into a `URL` object using the `URL` constructor.
|
|
234
|
+
*
|
|
235
|
+
* The string must be a valid absolute URL (e.g. `"https://example.com/path?q=1"`).
|
|
236
|
+
* Relative URLs and malformed strings throw a {@link TypoError}.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```ts
|
|
240
|
+
* typeUrl.decoder("https://example.com") // → URL { href: "https://example.com/", ... }
|
|
241
|
+
* typeUrl.decoder("not-a-url") // throws TypoError
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
37
244
|
declare const typeUrl: Type<URL>;
|
|
245
|
+
/**
|
|
246
|
+
* A {@link Type} that passes the raw string through unchanged (identity decoder).
|
|
247
|
+
*
|
|
248
|
+
* This is the simplest type and accepts any string value without validation.
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```ts
|
|
252
|
+
* typeString.decoder("hello") // → "hello"
|
|
253
|
+
* typeString.decoder("") // → ""
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
38
256
|
declare const typeString: Type<string>;
|
|
257
|
+
/**
|
|
258
|
+
* Creates a new {@link Type} by chaining a `before` type decoder with an `after`
|
|
259
|
+
* transformation.
|
|
260
|
+
*
|
|
261
|
+
* The raw string is first decoded by `before.decoder`; its result is then passed to
|
|
262
|
+
* `after.decoder`. Errors from `before` are wrapped with a "from: <content>" context
|
|
263
|
+
* prefix so that the full decoding path is visible in error messages.
|
|
264
|
+
*
|
|
265
|
+
* Use this when an existing type (e.g. {@link typeString}, {@link typeOneOf}) produces
|
|
266
|
+
* an intermediate value that needs a further transformation (e.g. parsing a
|
|
267
|
+
* string-keyed enum into a number).
|
|
268
|
+
*
|
|
269
|
+
* @typeParam Before - The intermediate type produced by `before.decoder`.
|
|
270
|
+
* @typeParam After - The final type produced by `after.decoder`.
|
|
271
|
+
*
|
|
272
|
+
* @param before - The base type that decodes the raw CLI string.
|
|
273
|
+
* @param after - The transformation applied to the `Before` value.
|
|
274
|
+
* @param after.content - Human-readable name for the resulting type (shown in errors).
|
|
275
|
+
* @param after.decoder - Function that converts a `Before` value into `After`.
|
|
276
|
+
* @returns A new {@link Type}`<After>` whose `content` is `after.content`.
|
|
277
|
+
*
|
|
278
|
+
* @example
|
|
279
|
+
* ```ts
|
|
280
|
+
* const typePort = typeConverted(typeNumber, {
|
|
281
|
+
* content: "Port",
|
|
282
|
+
* decoder: (n) => {
|
|
283
|
+
* if (n < 1 || n > 65535) throw new Error("Out of range");
|
|
284
|
+
* return n;
|
|
285
|
+
* },
|
|
286
|
+
* });
|
|
287
|
+
* // "--port 8080" → 8080
|
|
288
|
+
* // "--port 99999" → TypoError: --port: <PORT>: Port: Out of range
|
|
289
|
+
* ```
|
|
290
|
+
*/
|
|
39
291
|
declare function typeConverted<Before, After>(before: Type<Before>, after: {
|
|
40
292
|
content: string;
|
|
41
293
|
decoder: (value: Before) => After;
|
|
42
294
|
}): Type<After>;
|
|
295
|
+
/**
|
|
296
|
+
* Creates a {@link Type}`<string>` that only accepts a fixed set of string values.
|
|
297
|
+
*
|
|
298
|
+
* The decoder performs an exact (case-sensitive) lookup in `values`. If the input is
|
|
299
|
+
* not in the set, a {@link TypoError} is thrown listing up to 5 of the valid options.
|
|
300
|
+
*
|
|
301
|
+
* Combine with {@link typeConverted} to map the accepted strings to a richer type.
|
|
302
|
+
*
|
|
303
|
+
* @param content - Human-readable name for this type shown in help text and error
|
|
304
|
+
* messages (e.g. `"Environment"`, `"LogLevel"`).
|
|
305
|
+
* @param values - The ordered list of accepted string values. The order is preserved in
|
|
306
|
+
* the error message preview.
|
|
307
|
+
* @returns A {@link Type}`<string>` that validates membership in `values`.
|
|
308
|
+
*
|
|
309
|
+
* @example
|
|
310
|
+
* ```ts
|
|
311
|
+
* const typeEnv = typeOneOf("Environment", ["dev", "staging", "prod"]);
|
|
312
|
+
* typeEnv.decoder("prod") // → "prod"
|
|
313
|
+
* typeEnv.decoder("unknown") // throws TypoError: Invalid value: "unknown" (expected one of: "dev" | "staging" | "prod")
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
43
316
|
declare function typeOneOf(content: string, values: Array<string>): Type<string>;
|
|
317
|
+
/**
|
|
318
|
+
* Creates a {@link Type} that decodes a single delimited string into a fixed-length
|
|
319
|
+
* tuple of typed elements.
|
|
320
|
+
*
|
|
321
|
+
* The raw string is split on `separator` into exactly `elementTypes.length` parts.
|
|
322
|
+
* Each part is decoded by its corresponding element type. If the number of splits does
|
|
323
|
+
* not match, or if any element's decoder fails, a {@link TypoError} is thrown with the
|
|
324
|
+
* index and element type context.
|
|
325
|
+
*
|
|
326
|
+
* The resulting `content` is the element types' `content` values joined by `separator`
|
|
327
|
+
* (e.g. `"Number,String"` for a `[number, string]` tuple with `","` separator).
|
|
328
|
+
*
|
|
329
|
+
* @typeParam Elements - The tuple type of decoded element values (inferred from
|
|
330
|
+
* `elementTypes`).
|
|
331
|
+
*
|
|
332
|
+
* @param elementTypes - An ordered array of {@link Type}s, one per tuple element.
|
|
333
|
+
* @param separator - The string used to split the raw value (default: `","`).
|
|
334
|
+
* @returns A {@link Type}`<Elements>` tuple type.
|
|
335
|
+
*
|
|
336
|
+
* @example
|
|
337
|
+
* ```ts
|
|
338
|
+
* const typePoint = typeTuple([typeNumber, typeNumber]);
|
|
339
|
+
* typePoint.decoder("3.14,2.71") // → [3.14, 2.71]
|
|
340
|
+
* typePoint.decoder("1,2,3") // → [1, 2]
|
|
341
|
+
* typePoint.decoder("x,2") // throws TypoError: at 0: Number: Unable to parse: "x"
|
|
342
|
+
* ```
|
|
343
|
+
*/
|
|
44
344
|
declare function typeTuple<const Elements extends Array<any>>(elementTypes: {
|
|
45
345
|
[K in keyof Elements]: Type<Elements[K]>;
|
|
46
346
|
}, separator?: string): Type<Elements>;
|
|
347
|
+
/**
|
|
348
|
+
* Creates a {@link Type} that decodes a single delimited string into an array of
|
|
349
|
+
* homogeneous typed elements.
|
|
350
|
+
*
|
|
351
|
+
* The raw string is split on `separator` and each part is decoded by `elementType`.
|
|
352
|
+
* If any element's decoder fails, a {@link TypoError} is thrown with the index and
|
|
353
|
+
* element type context.
|
|
354
|
+
*
|
|
355
|
+
* Unlike {@link typeTuple}, the number of elements is not fixed; the result array
|
|
356
|
+
* length equals the number of `separator`-delimited parts in the input string. To pass
|
|
357
|
+
* an empty array, the user must pass an empty string (`""`), which splits into one
|
|
358
|
+
* empty-string element — consider using {@link optionRepeatable} instead if you want a
|
|
359
|
+
* naturally empty default.
|
|
360
|
+
*
|
|
361
|
+
* The `content` is formatted as `"<elementContent>[<sep><elementContent>]..."` to
|
|
362
|
+
* signal repeatability.
|
|
363
|
+
*
|
|
364
|
+
* @typeParam Value - The TypeScript element type produced by `elementType.decoder`.
|
|
365
|
+
*
|
|
366
|
+
* @param elementType - The {@link Type} used to decode each element.
|
|
367
|
+
* @param separator - The string used to split the raw value (default: `","`).
|
|
368
|
+
* @returns A {@link Type}`<Array<Value>>`.
|
|
369
|
+
*
|
|
370
|
+
* @example
|
|
371
|
+
* ```ts
|
|
372
|
+
* const typeNumbers = typeList(typeNumber);
|
|
373
|
+
* typeNumbers.decoder("1,2,3") // → [1, 2, 3]
|
|
374
|
+
* typeNumbers.decoder("1,x,3") // throws TypoError: at 1: Number: Unable to parse: "x"
|
|
375
|
+
*
|
|
376
|
+
* const typePaths = typeList(typeString, ":");
|
|
377
|
+
* typePaths.decoder("/usr/bin:/usr/local/bin") // → ["/usr/bin", "/usr/local/bin"]
|
|
378
|
+
* ```
|
|
379
|
+
*/
|
|
47
380
|
declare function typeList<Value>(elementType: Type<Value>, separator?: string): Type<Array<Value>>;
|
|
48
381
|
|
|
382
|
+
/**
|
|
383
|
+
* Describes a single CLI option (a flag or a valued option) together with its parsing
|
|
384
|
+
* and usage-generation logic.
|
|
385
|
+
*
|
|
386
|
+
* Options are created with {@link optionFlag}, {@link optionSingleValue}, or
|
|
387
|
+
* {@link optionRepeatable} and are passed via the `options` map of {@link operation}.
|
|
388
|
+
*
|
|
389
|
+
* @typeParam Value - The TypeScript type of the parsed option value.
|
|
390
|
+
* - `boolean` for flags created with {@link optionFlag}.
|
|
391
|
+
* - `T` for single-value options created with {@link optionSingleValue}.
|
|
392
|
+
* - `Array<T>` for repeatable options created with {@link optionRepeatable}.
|
|
393
|
+
*/
|
|
49
394
|
type Option<Value> = {
|
|
395
|
+
/** Returns human-readable metadata used to render the `Options:` section of help. */
|
|
50
396
|
generateUsage(): OptionUsage;
|
|
397
|
+
/**
|
|
398
|
+
* Registers the option on `readerOptions` so the argument reader recognises it, and
|
|
399
|
+
* returns an {@link OptionGetter} that can later retrieve the parsed value(s).
|
|
400
|
+
*
|
|
401
|
+
* @param readerOptions - The shared {@link ReaderArgs} that will parse the raw
|
|
402
|
+
* command-line tokens.
|
|
403
|
+
*/
|
|
51
404
|
createGetter(readerOptions: ReaderArgs): OptionGetter<Value>;
|
|
52
405
|
};
|
|
406
|
+
/**
|
|
407
|
+
* Human-readable metadata for a single CLI option, used to render the `Options:` section
|
|
408
|
+
* of the help output produced by {@link usageToStyledLines}.
|
|
409
|
+
*/
|
|
53
410
|
type OptionUsage = {
|
|
411
|
+
/** Short description of what the option does. */
|
|
54
412
|
description: string | undefined;
|
|
413
|
+
/**
|
|
414
|
+
* Optional supplementary note shown in parentheses next to the description.
|
|
415
|
+
* Suitable for short caveats such as `"required"` or `"defaults to 42"`.
|
|
416
|
+
*/
|
|
55
417
|
hint: string | undefined;
|
|
418
|
+
/**
|
|
419
|
+
* The primary long-form name of the option, without the `--` prefix (e.g. `"verbose"`).
|
|
420
|
+
* The user passes this as `--verbose` on the command line.
|
|
421
|
+
*/
|
|
56
422
|
long: Lowercase<string>;
|
|
423
|
+
/**
|
|
424
|
+
* The optional short-form name of the option, without the `-` prefix (e.g. `"v"`).
|
|
425
|
+
* The user passes this as `-v` on the command line.
|
|
426
|
+
*/
|
|
57
427
|
short: string | undefined;
|
|
428
|
+
/**
|
|
429
|
+
* The value placeholder label shown after the long option name in the help output
|
|
430
|
+
* (e.g. `"<FILE>"`). `undefined` for flags that take no value.
|
|
431
|
+
*/
|
|
58
432
|
label: Uppercase<string> | undefined;
|
|
59
433
|
};
|
|
434
|
+
/**
|
|
435
|
+
* Retrieves the parsed value for a registered option after argument parsing is complete.
|
|
436
|
+
*
|
|
437
|
+
* Returned by {@link Option.createGetter} and called by {@link OperationFactory.createInstance}.
|
|
438
|
+
*
|
|
439
|
+
* @typeParam Value - The TypeScript type of the parsed value.
|
|
440
|
+
*/
|
|
60
441
|
type OptionGetter<Value> = {
|
|
442
|
+
/**
|
|
443
|
+
* Returns the fully decoded and validated value for the option.
|
|
444
|
+
*
|
|
445
|
+
* @throws {@link TypoError} if the option appeared more times than allowed, the value
|
|
446
|
+
* failed type decoding, or a required default could not be computed.
|
|
447
|
+
*/
|
|
61
448
|
getValue(): Value;
|
|
62
449
|
};
|
|
450
|
+
/**
|
|
451
|
+
* Creates a boolean flag option — an option that the user passes without a value (e.g.
|
|
452
|
+
* `--verbose`) to signal `true`, or can explicitly set with `--flag=true` / `--flag=no`.
|
|
453
|
+
*
|
|
454
|
+
* **Parsing rules:**
|
|
455
|
+
* - Absent → `false` (or the return value of `default()` when provided).
|
|
456
|
+
* - `--flag` / `--flag=true` / `--flag=yes` → `true`.
|
|
457
|
+
* - `--flag=false` / `--flag=no` → `false`.
|
|
458
|
+
* - Specified more than once → {@link TypoError} ("Must not be set multiple times").
|
|
459
|
+
*
|
|
460
|
+
* @param definition - Configuration for the flag.
|
|
461
|
+
* @param definition.long - Primary long-form name (without `--`). Must be lowercase.
|
|
462
|
+
* @param definition.short - Optional short-form name (without `-`).
|
|
463
|
+
* @param definition.description - Human-readable description for the help output.
|
|
464
|
+
* @param definition.hint - Optional supplementary note shown in parentheses.
|
|
465
|
+
* @param definition.aliases - Additional long/short names that the parser also
|
|
466
|
+
* recognises as this flag.
|
|
467
|
+
* @param definition.default - Factory for the default value when the flag is absent.
|
|
468
|
+
* Defaults to `() => false` when omitted.
|
|
469
|
+
* @returns An {@link Option}`<boolean>`.
|
|
470
|
+
*
|
|
471
|
+
* @example
|
|
472
|
+
* ```ts
|
|
473
|
+
* const verboseFlag = optionFlag({
|
|
474
|
+
* long: "verbose",
|
|
475
|
+
* short: "v",
|
|
476
|
+
* description: "Enable verbose output",
|
|
477
|
+
* });
|
|
478
|
+
* ```
|
|
479
|
+
*/
|
|
63
480
|
declare function optionFlag(definition: {
|
|
64
481
|
long: Lowercase<string>;
|
|
65
482
|
short?: string;
|
|
@@ -71,6 +488,47 @@ declare function optionFlag(definition: {
|
|
|
71
488
|
};
|
|
72
489
|
default?: () => boolean;
|
|
73
490
|
}): Option<boolean>;
|
|
491
|
+
/**
|
|
492
|
+
* Creates an option that accepts exactly one value (e.g. `--output dist/` or
|
|
493
|
+
* `--output=dist/`).
|
|
494
|
+
*
|
|
495
|
+
* **Parsing rules:**
|
|
496
|
+
* - Absent → `definition.default()` is called. If the default factory throws, a
|
|
497
|
+
* {@link TypoError} is produced.
|
|
498
|
+
* - Specified once → the value is decoded with `definition.type`.
|
|
499
|
+
* - Specified more than once → {@link TypoError} ("Requires a single value, but got
|
|
500
|
+
* multiple").
|
|
501
|
+
*
|
|
502
|
+
* **Value syntax:** `--long value`, `--long=value`, or (if `short` is set) `-s value`,
|
|
503
|
+
* `-s=value`, or `-svalue`.
|
|
504
|
+
*
|
|
505
|
+
* @typeParam Value - The TypeScript type produced by the type decoder.
|
|
506
|
+
*
|
|
507
|
+
* @param definition - Configuration for the option.
|
|
508
|
+
* @param definition.long - Primary long-form name (without `--`). Must be lowercase.
|
|
509
|
+
* @param definition.short - Optional short-form name (without `-`).
|
|
510
|
+
* @param definition.description - Human-readable description for the help output.
|
|
511
|
+
* @param definition.hint - Optional supplementary note shown in parentheses.
|
|
512
|
+
* @param definition.aliases - Additional long/short names the parser also recognises.
|
|
513
|
+
* @param definition.label - Custom label shown in the help output (e.g. `"FILE"`).
|
|
514
|
+
* Defaults to the uppercased `type.content`.
|
|
515
|
+
* @param definition.type - The {@link Type} used to decode the raw string value.
|
|
516
|
+
* @param definition.default - Factory for the default value when the option is absent.
|
|
517
|
+
* Throw an error from this factory to make the option effectively required.
|
|
518
|
+
* @returns An {@link Option}`<Value>`.
|
|
519
|
+
*
|
|
520
|
+
* @example
|
|
521
|
+
* ```ts
|
|
522
|
+
* const outputOption = optionSingleValue({
|
|
523
|
+
* long: "output",
|
|
524
|
+
* short: "o",
|
|
525
|
+
* type: typeString,
|
|
526
|
+
* label: "PATH",
|
|
527
|
+
* description: "Output directory",
|
|
528
|
+
* default: () => "dist/",
|
|
529
|
+
* });
|
|
530
|
+
* ```
|
|
531
|
+
*/
|
|
74
532
|
declare function optionSingleValue<Value>(definition: {
|
|
75
533
|
long: Lowercase<string>;
|
|
76
534
|
short?: string;
|
|
@@ -84,6 +542,45 @@ declare function optionSingleValue<Value>(definition: {
|
|
|
84
542
|
type: Type<Value>;
|
|
85
543
|
default: () => Value;
|
|
86
544
|
}): Option<Value>;
|
|
545
|
+
/**
|
|
546
|
+
* Creates an option that can be specified any number of times, collecting all provided
|
|
547
|
+
* values into an array (e.g. `--file a.ts --file b.ts`).
|
|
548
|
+
*
|
|
549
|
+
* **Parsing rules:**
|
|
550
|
+
* - Absent → empty array `[]`.
|
|
551
|
+
* - Specified N times → array of N decoded values, in the order they appear on the
|
|
552
|
+
* command line.
|
|
553
|
+
* - Each occurrence is decoded independently with `definition.type`.
|
|
554
|
+
*
|
|
555
|
+
* **Value syntax:** `--long value`, `--long=value`, or (if `short` is set) `-s value`,
|
|
556
|
+
* `-s=value`, or `-svalue`.
|
|
557
|
+
*
|
|
558
|
+
* @typeParam Value - The TypeScript type produced by the type decoder for each
|
|
559
|
+
* occurrence.
|
|
560
|
+
*
|
|
561
|
+
* @param definition - Configuration for the option.
|
|
562
|
+
* @param definition.long - Primary long-form name (without `--`). Must be lowercase.
|
|
563
|
+
* @param definition.short - Optional short-form name (without `-`).
|
|
564
|
+
* @param definition.description - Human-readable description for the help output.
|
|
565
|
+
* @param definition.hint - Optional supplementary note shown in parentheses.
|
|
566
|
+
* @param definition.aliases - Additional long/short names the parser also recognises.
|
|
567
|
+
* @param definition.label - Custom label shown in the help output (e.g. `"FILE"`).
|
|
568
|
+
* Defaults to the uppercased `type.content`.
|
|
569
|
+
* @param definition.type - The {@link Type} used to decode each raw string value.
|
|
570
|
+
* @returns An {@link Option}`<Array<Value>>`.
|
|
571
|
+
*
|
|
572
|
+
* @example
|
|
573
|
+
* ```ts
|
|
574
|
+
* const filesOption = optionRepeatable({
|
|
575
|
+
* long: "file",
|
|
576
|
+
* short: "f",
|
|
577
|
+
* type: typeString,
|
|
578
|
+
* label: "PATH",
|
|
579
|
+
* description: "Input file (may be repeated)",
|
|
580
|
+
* });
|
|
581
|
+
* // Usage: my-cli --file a.ts --file b.ts → ["a.ts", "b.ts"]
|
|
582
|
+
* ```
|
|
583
|
+
*/
|
|
87
584
|
declare function optionRepeatable<Value>(definition: {
|
|
88
585
|
long: Lowercase<string>;
|
|
89
586
|
short?: string;
|
|
@@ -97,21 +594,121 @@ declare function optionRepeatable<Value>(definition: {
|
|
|
97
594
|
type: Type<Value>;
|
|
98
595
|
}): Option<Array<Value>>;
|
|
99
596
|
|
|
597
|
+
/**
|
|
598
|
+
* Describes a single positional argument — a bare (non-option) token on the command
|
|
599
|
+
* line — together with its parsing and usage-generation logic.
|
|
600
|
+
*
|
|
601
|
+
* Positionals are created with {@link positionalRequired}, {@link positionalOptional}, or
|
|
602
|
+
* {@link positionalVariadics} and are passed via the `positionals` array of
|
|
603
|
+
* {@link operation}, where they are consumed in declaration order.
|
|
604
|
+
*
|
|
605
|
+
* @typeParam Value - The TypeScript type of the parsed positional value.
|
|
606
|
+
*/
|
|
100
607
|
type Positional<Value> = {
|
|
608
|
+
/** Returns human-readable metadata used to render the `Positionals:` section of help. */
|
|
101
609
|
generateUsage(): PositionalUsage;
|
|
610
|
+
/**
|
|
611
|
+
* Consumes the next positional token(s) from `readerPositionals` and returns the
|
|
612
|
+
* decoded value.
|
|
613
|
+
*
|
|
614
|
+
* @param readerPositionals - The shared {@link ReaderArgs} that manages the queue of
|
|
615
|
+
* remaining positional tokens.
|
|
616
|
+
* @throws {@link TypoError} if the positional is required but absent, or if the raw
|
|
617
|
+
* value fails type decoding.
|
|
618
|
+
*/
|
|
102
619
|
consumePositionals(readerPositionals: ReaderPositionals): Value;
|
|
103
620
|
};
|
|
621
|
+
/**
|
|
622
|
+
* Human-readable metadata for a single positional argument, used to render the
|
|
623
|
+
* `Positionals:` section of the help output produced by {@link usageToStyledLines}.
|
|
624
|
+
*/
|
|
104
625
|
type PositionalUsage = {
|
|
626
|
+
/** Short description of what the positional represents. */
|
|
105
627
|
description: string | undefined;
|
|
628
|
+
/**
|
|
629
|
+
* Optional supplementary note shown in parentheses next to the description.
|
|
630
|
+
* Suitable for short caveats such as `"defaults to 'world'"`.
|
|
631
|
+
*/
|
|
106
632
|
hint: string | undefined;
|
|
633
|
+
/**
|
|
634
|
+
* The placeholder label shown in the usage line and the `Positionals:` section.
|
|
635
|
+
* Required positionals use angle-bracket notation (e.g. `"<NAME>"`); optional ones
|
|
636
|
+
* use square-bracket notation (e.g. `"[FILE]"`); variadic ones append `...`
|
|
637
|
+
* (e.g. `"[ITEM]..."`).
|
|
638
|
+
*/
|
|
107
639
|
label: Uppercase<string>;
|
|
108
640
|
};
|
|
641
|
+
/**
|
|
642
|
+
* Creates a required positional argument — one that must be present on the command line.
|
|
643
|
+
*
|
|
644
|
+
* The parser consumes the next available positional token and decodes it with
|
|
645
|
+
* `definition.type`. If no token is available, a {@link TypoError} is thrown immediately
|
|
646
|
+
* during parsing (i.e. inside {@link OperationDescriptor.createFactory}).
|
|
647
|
+
*
|
|
648
|
+
* The label displayed in the usage line defaults to the uppercased `type.content`
|
|
649
|
+
* wrapped in angle brackets (e.g. `<STRING>`). Supply `label` to override.
|
|
650
|
+
*
|
|
651
|
+
* @typeParam Value - The TypeScript type produced by the type decoder.
|
|
652
|
+
*
|
|
653
|
+
* @param definition - Configuration for the positional.
|
|
654
|
+
* @param definition.description - Human-readable description for the help output.
|
|
655
|
+
* @param definition.hint - Optional supplementary note shown in parentheses.
|
|
656
|
+
* @param definition.label - Custom label shown in the usage line (without angle brackets).
|
|
657
|
+
* Defaults to the uppercased `type.content`.
|
|
658
|
+
* @param definition.type - The {@link Type} used to decode the raw string token.
|
|
659
|
+
* @returns A {@link Positional}`<Value>`.
|
|
660
|
+
*
|
|
661
|
+
* @example
|
|
662
|
+
* ```ts
|
|
663
|
+
* const namePositional = positionalRequired({
|
|
664
|
+
* type: typeString,
|
|
665
|
+
* label: "NAME",
|
|
666
|
+
* description: "The name to greet",
|
|
667
|
+
* });
|
|
668
|
+
* // Parses: my-cli Alice → "Alice"
|
|
669
|
+
* ```
|
|
670
|
+
*/
|
|
109
671
|
declare function positionalRequired<Value>(definition: {
|
|
110
672
|
description?: string;
|
|
111
673
|
hint?: string;
|
|
112
674
|
label?: Uppercase<string>;
|
|
113
675
|
type: Type<Value>;
|
|
114
676
|
}): Positional<Value>;
|
|
677
|
+
/**
|
|
678
|
+
* Creates an optional positional argument — one that may or may not appear on the
|
|
679
|
+
* command line.
|
|
680
|
+
*
|
|
681
|
+
* The parser consumes the next available positional token. If no token is available,
|
|
682
|
+
* `definition.default()` is called to supply the fallback value. If the default factory
|
|
683
|
+
* throws, a {@link TypoError} is produced.
|
|
684
|
+
*
|
|
685
|
+
* The label displayed in the usage line defaults to the uppercased `type.content`
|
|
686
|
+
* wrapped in square brackets (e.g. `[STRING]`). Supply `label` to override.
|
|
687
|
+
*
|
|
688
|
+
* @typeParam Value - The TypeScript type produced by the type decoder (or the default).
|
|
689
|
+
*
|
|
690
|
+
* @param definition - Configuration for the positional.
|
|
691
|
+
* @param definition.description - Human-readable description for the help output.
|
|
692
|
+
* @param definition.hint - Optional supplementary note shown in parentheses.
|
|
693
|
+
* @param definition.label - Custom label shown in the usage line (without square brackets).
|
|
694
|
+
* Defaults to the uppercased `type.content`.
|
|
695
|
+
* @param definition.type - The {@link Type} used to decode the raw string token.
|
|
696
|
+
* @param definition.default - Factory called when the positional is absent to supply the
|
|
697
|
+
* default value. Throw from this factory to make omission an error.
|
|
698
|
+
* @returns A {@link Positional}`<Value>`.
|
|
699
|
+
*
|
|
700
|
+
* @example
|
|
701
|
+
* ```ts
|
|
702
|
+
* const greeteePositional = positionalOptional({
|
|
703
|
+
* type: typeString,
|
|
704
|
+
* label: "NAME",
|
|
705
|
+
* description: "Name to greet (default: world)",
|
|
706
|
+
* default: () => "world",
|
|
707
|
+
* });
|
|
708
|
+
* // my-cli → "world"
|
|
709
|
+
* // my-cli Alice → "Alice"
|
|
710
|
+
* ```
|
|
711
|
+
*/
|
|
115
712
|
declare function positionalOptional<Value>(definition: {
|
|
116
713
|
description?: string;
|
|
117
714
|
hint?: string;
|
|
@@ -119,6 +716,45 @@ declare function positionalOptional<Value>(definition: {
|
|
|
119
716
|
type: Type<Value>;
|
|
120
717
|
default: () => Value;
|
|
121
718
|
}): Positional<Value>;
|
|
719
|
+
/**
|
|
720
|
+
* Creates a variadic positional argument — one that collects zero or more remaining
|
|
721
|
+
* positional tokens into an array.
|
|
722
|
+
*
|
|
723
|
+
* The parser greedily consumes tokens until either there are no more tokens or it
|
|
724
|
+
* encounters the optional `endDelimiter` sentinel string, which is consumed but not
|
|
725
|
+
* included in the result. Each token is decoded independently with `definition.type`.
|
|
726
|
+
*
|
|
727
|
+
* If absent entirely, the result is an empty array `[]`.
|
|
728
|
+
*
|
|
729
|
+
* The label displayed in the usage line defaults to the uppercased `type.content`
|
|
730
|
+
* wrapped in square brackets followed by `...` (e.g. `[STRING]...`). When an
|
|
731
|
+
* `endDelimiter` is configured, the delimiter is also shown (e.g. `[STRING]...["--"]`).
|
|
732
|
+
* Supply `label` to override the base label.
|
|
733
|
+
*
|
|
734
|
+
* @typeParam Value - The TypeScript type produced by the type decoder for each token.
|
|
735
|
+
*
|
|
736
|
+
* @param definition - Configuration for the variadic positional.
|
|
737
|
+
* @param definition.endDelimiter - Optional sentinel string that signals the end of
|
|
738
|
+
* the variadic sequence (e.g. `"--"`). When encountered it is consumed but not
|
|
739
|
+
* included in the result array.
|
|
740
|
+
* @param definition.description - Human-readable description for the help output.
|
|
741
|
+
* @param definition.hint - Optional supplementary note shown in parentheses.
|
|
742
|
+
* @param definition.label - Custom label shown in the usage line (without brackets).
|
|
743
|
+
* Defaults to the uppercased `type.content`.
|
|
744
|
+
* @param definition.type - The {@link Type} used to decode each raw string token.
|
|
745
|
+
* @returns A {@link Positional}`<Array<Value>>`.
|
|
746
|
+
*
|
|
747
|
+
* @example
|
|
748
|
+
* ```ts
|
|
749
|
+
* const filesPositional = positionalVariadics({
|
|
750
|
+
* type: typeString,
|
|
751
|
+
* label: "FILE",
|
|
752
|
+
* description: "Files to process",
|
|
753
|
+
* });
|
|
754
|
+
* // my-cli a.ts b.ts c.ts → ["a.ts", "b.ts", "c.ts"]
|
|
755
|
+
* // my-cli → []
|
|
756
|
+
* ```
|
|
757
|
+
*/
|
|
122
758
|
declare function positionalVariadics<Value>(definition: {
|
|
123
759
|
endDelimiter?: string;
|
|
124
760
|
description?: string;
|
|
@@ -127,20 +763,128 @@ declare function positionalVariadics<Value>(definition: {
|
|
|
127
763
|
type: Type<Value>;
|
|
128
764
|
}): Positional<Array<Value>>;
|
|
129
765
|
|
|
766
|
+
/**
|
|
767
|
+
* Describes an operation — the combination of options, positional arguments, and an
|
|
768
|
+
* async execution handler that together form the core logic of a CLI command.
|
|
769
|
+
*
|
|
770
|
+
* An `OperationDescriptor` is created with {@link operation} and passed to
|
|
771
|
+
* {@link command}, {@link commandWithSubcommands}, or {@link commandChained} to build
|
|
772
|
+
* a full {@link CommandDescriptor}.
|
|
773
|
+
*
|
|
774
|
+
* @typeParam Input - The context value the handler receives at execution time (forwarded
|
|
775
|
+
* from the parent command's context or from a preceding chained operation).
|
|
776
|
+
* @typeParam Output - The value the handler produces. For leaf operations this is
|
|
777
|
+
* typically `void`; for intermediate stages it is the payload forwarded to the next
|
|
778
|
+
* command in a chain.
|
|
779
|
+
*/
|
|
130
780
|
type OperationDescriptor<Input, Output> = {
|
|
781
|
+
/**
|
|
782
|
+
* Returns usage metadata (options and positionals) without consuming any arguments.
|
|
783
|
+
* Called by the parent command factory when building the help/usage output.
|
|
784
|
+
*/
|
|
131
785
|
generateUsage(): OperationUsage;
|
|
786
|
+
/**
|
|
787
|
+
* Parses options and positionals from `readerArgs` and returns an
|
|
788
|
+
* {@link OperationFactory} that can create a ready-to-execute
|
|
789
|
+
* {@link OperationInstance}.
|
|
790
|
+
*
|
|
791
|
+
* Any parse error (unknown option, type mismatch, etc.) is captured and re-thrown
|
|
792
|
+
* when {@link OperationFactory.createInstance} is called.
|
|
793
|
+
*
|
|
794
|
+
* @param readerArgs - The shared argument reader. Options are registered on it and
|
|
795
|
+
* positionals are consumed in declaration order.
|
|
796
|
+
*/
|
|
132
797
|
createFactory(readerArgs: ReaderArgs): OperationFactory<Input, Output>;
|
|
133
798
|
};
|
|
799
|
+
/**
|
|
800
|
+
* Produced by {@link OperationDescriptor.createFactory} after argument parsing.
|
|
801
|
+
* Instantiating it finalises value extraction and produces an {@link OperationInstance}.
|
|
802
|
+
*
|
|
803
|
+
* @typeParam Input - Forwarded from the parent {@link OperationDescriptor}.
|
|
804
|
+
* @typeParam Output - Forwarded from the parent {@link OperationDescriptor}.
|
|
805
|
+
*/
|
|
134
806
|
type OperationFactory<Input, Output> = {
|
|
807
|
+
/**
|
|
808
|
+
* Extracts the final parsed values for all options and returns an
|
|
809
|
+
* {@link OperationInstance} ready for execution.
|
|
810
|
+
*
|
|
811
|
+
* @throws {@link TypoError} if any option or positional validation failed during
|
|
812
|
+
* {@link OperationDescriptor.createFactory}.
|
|
813
|
+
*/
|
|
135
814
|
createInstance(): OperationInstance<Input, Output>;
|
|
136
815
|
};
|
|
816
|
+
/**
|
|
817
|
+
* A fully parsed, ready-to-execute operation.
|
|
818
|
+
*
|
|
819
|
+
* @typeParam Input - The value the caller must supply as context.
|
|
820
|
+
* @typeParam Output - The value produced on successful execution.
|
|
821
|
+
*/
|
|
137
822
|
type OperationInstance<Input, Output> = {
|
|
823
|
+
/**
|
|
824
|
+
* Runs the operation handler with the provided input context and the parsed
|
|
825
|
+
* option/positional values.
|
|
826
|
+
*
|
|
827
|
+
* @param input - Context from the parent command (or the root context supplied to
|
|
828
|
+
* {@link runAsCliAndExit}).
|
|
829
|
+
* @returns A promise resolving to the handler's return value.
|
|
830
|
+
*/
|
|
138
831
|
executeWithContext(input: Input): Promise<Output>;
|
|
139
832
|
};
|
|
833
|
+
/**
|
|
834
|
+
* Collected usage metadata produced by {@link OperationDescriptor.generateUsage}.
|
|
835
|
+
* Consumed by the parent command factory when building {@link CommandUsage}.
|
|
836
|
+
*/
|
|
140
837
|
type OperationUsage = {
|
|
838
|
+
/** Usage descriptors for all options registered by this operation. */
|
|
141
839
|
options: Array<OptionUsage>;
|
|
840
|
+
/** Usage descriptors for all positionals declared by this operation, in order. */
|
|
142
841
|
positionals: Array<PositionalUsage>;
|
|
143
842
|
};
|
|
843
|
+
/**
|
|
844
|
+
* Creates an {@link OperationDescriptor} from a set of options, positionals, and an
|
|
845
|
+
* async handler function.
|
|
846
|
+
*
|
|
847
|
+
* The `handler` receives:
|
|
848
|
+
* - `context` — the value passed down from the parent command (or from
|
|
849
|
+
* {@link runAsCliAndExit}).
|
|
850
|
+
* - `inputs.options` — an object whose keys match those declared in `inputs.options` and whose values are
|
|
851
|
+
* the parsed option values.
|
|
852
|
+
* - `inputs.positionals` — a tuple whose elements match `inputs.positionals` and whose
|
|
853
|
+
* values are the parsed positional values, in declaration order.
|
|
854
|
+
*
|
|
855
|
+
* @typeParam Context - The context type accepted by the handler.
|
|
856
|
+
* @typeParam Result - The return type of the handler.
|
|
857
|
+
* @typeParam Options - Object type mapping option keys to their parsed value types.
|
|
858
|
+
* @typeParam Positionals - Tuple type of parsed positional value types, in order.
|
|
859
|
+
*
|
|
860
|
+
* @param inputs - Declares the options and positionals this operation accepts.
|
|
861
|
+
* @param inputs.options - A map from arbitrary keys to {@link Option} descriptors.
|
|
862
|
+
* The same keys appear in `handler`'s `inputs.options` argument.
|
|
863
|
+
* @param inputs.positionals - An ordered array of {@link Positional} descriptors.
|
|
864
|
+
* Their parsed values appear in `handler`'s `inputs.positionals` argument, in the
|
|
865
|
+
* same order.
|
|
866
|
+
* @param handler - The async function that implements the command logic. Receives the
|
|
867
|
+
* execution context and all parsed inputs.
|
|
868
|
+
* @returns An {@link OperationDescriptor} ready to be composed into a command.
|
|
869
|
+
*
|
|
870
|
+
* @example
|
|
871
|
+
* ```ts
|
|
872
|
+
* const greetOperation = operation(
|
|
873
|
+
* {
|
|
874
|
+
* options: {
|
|
875
|
+
* loud: optionFlag({ long: "loud", description: "Print in uppercase" }),
|
|
876
|
+
* },
|
|
877
|
+
* positionals: [
|
|
878
|
+
* positionalRequired({ type: typeString, label: "NAME", description: "Name to greet" }),
|
|
879
|
+
* ],
|
|
880
|
+
* },
|
|
881
|
+
* async (_ctx, { options: { loud }, positionals: [name] }) => {
|
|
882
|
+
* const message = `Hello, ${name}!`;
|
|
883
|
+
* console.log(loud ? message.toUpperCase() : message);
|
|
884
|
+
* },
|
|
885
|
+
* );
|
|
886
|
+
* ```
|
|
887
|
+
*/
|
|
144
888
|
declare function operation<Context, Result, Options extends {
|
|
145
889
|
[option: string]: any;
|
|
146
890
|
}, const Positionals extends Array<any>>(inputs: {
|
|
@@ -155,45 +899,342 @@ declare function operation<Context, Result, Options extends {
|
|
|
155
899
|
positionals: Positionals;
|
|
156
900
|
}) => Promise<Result>): OperationDescriptor<Context, Result>;
|
|
157
901
|
|
|
902
|
+
/**
|
|
903
|
+
* Describes a CLI command: how to parse its arguments from raw CLI input and how to
|
|
904
|
+
* execute it within a given context.
|
|
905
|
+
*
|
|
906
|
+
* A `CommandDescriptor` is the central building block of a `cli-kiss` CLI. You create
|
|
907
|
+
* one with {@link command}, {@link commandWithSubcommands}, or {@link commandChained},
|
|
908
|
+
* and pass it to {@link runAsCliAndExit} to run your CLI.
|
|
909
|
+
*
|
|
910
|
+
* @typeParam Context - The value passed into the command when it is executed. It flows
|
|
911
|
+
* from {@link runAsCliAndExit}'s `context` argument down through the command chain.
|
|
912
|
+
* @typeParam Result - The value produced by executing the command. For root commands
|
|
913
|
+
* passed to {@link runAsCliAndExit} this is always `void`.
|
|
914
|
+
*/
|
|
158
915
|
type CommandDescriptor<Context, Result> = {
|
|
916
|
+
/** Returns the static metadata (description, hint, details) for this command. */
|
|
159
917
|
getInformation(): CommandInformation;
|
|
918
|
+
/**
|
|
919
|
+
* Parses `readerArgs` and returns a {@link CommandFactory} that can generate usage
|
|
920
|
+
* information or create a ready-to-run {@link CommandInstance}.
|
|
921
|
+
*
|
|
922
|
+
* Parsing errors are captured and deferred: `createFactory` never throws; instead
|
|
923
|
+
* the error surfaces when {@link CommandFactory.createInstance} is called on the
|
|
924
|
+
* returned factory.
|
|
925
|
+
*/
|
|
160
926
|
createFactory(readerArgs: ReaderArgs): CommandFactory<Context, Result>;
|
|
161
927
|
};
|
|
928
|
+
/**
|
|
929
|
+
* Produced by {@link CommandDescriptor.createFactory} after the raw CLI arguments have
|
|
930
|
+
* been parsed. Provides two capabilities:
|
|
931
|
+
*
|
|
932
|
+
* 1. **Usage generation** — always available, even when parsing failed.
|
|
933
|
+
* 2. **Instance creation** — throws a {@link TypoError} if parsing failed.
|
|
934
|
+
*
|
|
935
|
+
* @typeParam Context - Forwarded from the parent {@link CommandDescriptor}.
|
|
936
|
+
* @typeParam Result - Forwarded from the parent {@link CommandDescriptor}.
|
|
937
|
+
*/
|
|
162
938
|
type CommandFactory<Context, Result> = {
|
|
939
|
+
/**
|
|
940
|
+
* Builds the complete {@link CommandUsage} for the currently parsed command path.
|
|
941
|
+
* This is called to render the `--help` output and on error when `usageOnError`
|
|
942
|
+
* is enabled.
|
|
943
|
+
*/
|
|
163
944
|
generateUsage(): CommandUsage;
|
|
945
|
+
/**
|
|
946
|
+
* Creates a {@link CommandInstance} that is ready to execute.
|
|
947
|
+
*
|
|
948
|
+
* @throws {@link TypoError} if the argument parsing that occurred during
|
|
949
|
+
* {@link CommandDescriptor.createFactory} encountered an error (e.g. unknown
|
|
950
|
+
* option, missing required positional, invalid type).
|
|
951
|
+
*/
|
|
164
952
|
createInstance(): CommandInstance<Context, Result>;
|
|
165
953
|
};
|
|
954
|
+
/**
|
|
955
|
+
* A fully parsed, ready-to-execute command.
|
|
956
|
+
*
|
|
957
|
+
* @typeParam Context - The value the caller must provide when executing the command.
|
|
958
|
+
* @typeParam Result - The value the command produces on successful execution.
|
|
959
|
+
*/
|
|
166
960
|
type CommandInstance<Context, Result> = {
|
|
961
|
+
/**
|
|
962
|
+
* Executes the command with the provided context.
|
|
963
|
+
*
|
|
964
|
+
* @param context - Arbitrary value injected by the caller (see {@link runAsCliAndExit}).
|
|
965
|
+
* @returns A promise that resolves to the command's result, or rejects if the
|
|
966
|
+
* command handler throws.
|
|
967
|
+
*/
|
|
167
968
|
executeWithContext(context: Context): Promise<Result>;
|
|
168
969
|
};
|
|
970
|
+
/**
|
|
971
|
+
* Static, human-readable metadata attached to a command.
|
|
972
|
+
*
|
|
973
|
+
* This information is displayed in the usage/help output produced by
|
|
974
|
+
* {@link usageToStyledLines}.
|
|
975
|
+
*/
|
|
169
976
|
type CommandInformation = {
|
|
977
|
+
/** Short description of what the command does. Shown prominently in the usage header. */
|
|
170
978
|
description: string;
|
|
979
|
+
/**
|
|
980
|
+
* Optional supplementary note shown in parentheses next to the description.
|
|
981
|
+
* Suitable for short caveats such as `"deprecated"` or `"experimental"`.
|
|
982
|
+
*/
|
|
171
983
|
hint?: string;
|
|
984
|
+
/**
|
|
985
|
+
* Optional list of additional detail lines printed below the description.
|
|
986
|
+
* Useful for multi-line explanations, examples, or caveats that don't fit in
|
|
987
|
+
* a single sentence.
|
|
988
|
+
*/
|
|
172
989
|
details?: Array<string>;
|
|
173
990
|
};
|
|
991
|
+
/**
|
|
992
|
+
* The full usage/help model for a command as it appears after argument parsing.
|
|
993
|
+
*
|
|
994
|
+
* This is produced by {@link CommandFactory.generateUsage} and consumed by
|
|
995
|
+
* {@link usageToStyledLines} to render the `--help` output.
|
|
996
|
+
*/
|
|
174
997
|
type CommandUsage = {
|
|
998
|
+
/**
|
|
999
|
+
* Ordered list of breadcrumb segments that form the command's usage line, e.g.:
|
|
1000
|
+
* `Usage: my-cli <POSITIONAL> subcommand <ANOTHER_POSITIONAL>`.
|
|
1001
|
+
*
|
|
1002
|
+
* Each element is either a positional placeholder or a literal subcommand name.
|
|
1003
|
+
*/
|
|
175
1004
|
breadcrumbs: Array<CommandUsageBreadcrumb>;
|
|
1005
|
+
/** The command's static metadata (description, hint, details). */
|
|
176
1006
|
information: CommandInformation;
|
|
1007
|
+
/**
|
|
1008
|
+
* Positional arguments that belong to the current command path,
|
|
1009
|
+
* in the order they must appear on the command line.
|
|
1010
|
+
*/
|
|
177
1011
|
positionals: Array<PositionalUsage>;
|
|
1012
|
+
/**
|
|
1013
|
+
* Subcommands available at the current level of the command hierarchy.
|
|
1014
|
+
* Non-empty only when the command is a {@link commandWithSubcommands} and the
|
|
1015
|
+
* subcommand selection could not be resolved (i.e. on error or `--help`).
|
|
1016
|
+
*/
|
|
178
1017
|
subcommands: Array<CommandUsageSubcommand>;
|
|
1018
|
+
/**
|
|
1019
|
+
* Options (flags and valued options) accepted by the current command path,
|
|
1020
|
+
* in the order they were registered.
|
|
1021
|
+
*/
|
|
179
1022
|
options: Array<OptionUsage>;
|
|
180
1023
|
};
|
|
1024
|
+
/**
|
|
1025
|
+
* A single element in the usage breadcrumb trail shown at the top of the help output.
|
|
1026
|
+
*
|
|
1027
|
+
* - `{ positional: string }` — A positional placeholder such as `<NAME>` or `[FILE]`.
|
|
1028
|
+
* - `{ command: string }` — A literal subcommand token such as `deploy`.
|
|
1029
|
+
*/
|
|
181
1030
|
type CommandUsageBreadcrumb = {
|
|
182
1031
|
positional: string;
|
|
183
1032
|
} | {
|
|
184
1033
|
command: string;
|
|
185
1034
|
};
|
|
1035
|
+
/**
|
|
1036
|
+
* Summary information about a single subcommand shown in the `Subcommands:` section
|
|
1037
|
+
* of the usage output.
|
|
1038
|
+
*/
|
|
186
1039
|
type CommandUsageSubcommand = {
|
|
1040
|
+
/** The literal token the user types to select this subcommand (e.g. `"deploy"`). */
|
|
187
1041
|
name: string;
|
|
1042
|
+
/** Short description forwarded from the subcommand's {@link CommandInformation}. */
|
|
188
1043
|
description: string | undefined;
|
|
1044
|
+
/** Optional hint forwarded from the subcommand's {@link CommandInformation}. */
|
|
189
1045
|
hint: string | undefined;
|
|
190
1046
|
};
|
|
1047
|
+
/**
|
|
1048
|
+
* Creates a leaf command — a command that has no subcommands and directly executes
|
|
1049
|
+
* an {@link OperationDescriptor}.
|
|
1050
|
+
*
|
|
1051
|
+
* During parsing, `command` reads all positionals and options consumed by `operation`,
|
|
1052
|
+
* then asserts that no extra positionals remain. Any unexpected trailing positional
|
|
1053
|
+
* causes a {@link TypoError} deferred to {@link CommandFactory.createInstance}.
|
|
1054
|
+
*
|
|
1055
|
+
* @typeParam Context - The context value forwarded to the operation handler at
|
|
1056
|
+
* execution time.
|
|
1057
|
+
* @typeParam Result - The value returned by the operation handler.
|
|
1058
|
+
*
|
|
1059
|
+
* @param information - Static metadata (description, hint, details) for the command.
|
|
1060
|
+
* @param operation - The operation that defines options, positionals, and the execution
|
|
1061
|
+
* handler for this command.
|
|
1062
|
+
* @returns A {@link CommandDescriptor} suitable for passing to {@link runAsCliAndExit}
|
|
1063
|
+
* or composing with {@link commandWithSubcommands} / {@link commandChained}.
|
|
1064
|
+
*
|
|
1065
|
+
* @example
|
|
1066
|
+
* ```ts
|
|
1067
|
+
* const greet = command(
|
|
1068
|
+
* { description: "Greet a user" },
|
|
1069
|
+
* operation(
|
|
1070
|
+
* { options: {}, positionals: [positionalRequired({ type: typeString, label: "NAME" })] },
|
|
1071
|
+
* async (_ctx, { positionals: [name] }) => console.log(`Hello, ${name}!`),
|
|
1072
|
+
* ),
|
|
1073
|
+
* );
|
|
1074
|
+
* ```
|
|
1075
|
+
*/
|
|
191
1076
|
declare function command<Context, Result>(information: CommandInformation, operation: OperationDescriptor<Context, Result>): CommandDescriptor<Context, Result>;
|
|
1077
|
+
/**
|
|
1078
|
+
* Creates a command that first runs an {@link OperationDescriptor} to produce an
|
|
1079
|
+
* intermediate `Payload`, then dispatches execution to one of several named subcommands
|
|
1080
|
+
* based on the next positional argument.
|
|
1081
|
+
*
|
|
1082
|
+
* **Parsing behaviour:**
|
|
1083
|
+
* 1. The `operation`'s positionals and options are parsed from `readerArgs`.
|
|
1084
|
+
* 2. The next positional token is consumed as the subcommand name.
|
|
1085
|
+
* - If no token is present, a {@link TypoError} is deferred.
|
|
1086
|
+
* - If the token does not match any key in `subcommands`, a {@link TypoError} is
|
|
1087
|
+
* deferred.
|
|
1088
|
+
* 3. The matched subcommand's factory is created with the remaining `readerArgs`.
|
|
1089
|
+
*
|
|
1090
|
+
* **Usage on error / `--help`:** when the subcommand cannot be determined, the usage
|
|
1091
|
+
* output lists all available subcommands under a `Subcommands:` section.
|
|
1092
|
+
*
|
|
1093
|
+
* @typeParam Context - The context value accepted by the root operation handler.
|
|
1094
|
+
* @typeParam Payload - The value produced by the root operation and forwarded as the
|
|
1095
|
+
* context to the selected subcommand.
|
|
1096
|
+
* @typeParam Result - The value produced by the selected subcommand.
|
|
1097
|
+
*
|
|
1098
|
+
* @param information - Static metadata shown in the top-level usage when no valid
|
|
1099
|
+
* subcommand has been selected.
|
|
1100
|
+
* @param operation - The operation that is always executed first, before the
|
|
1101
|
+
* subcommand. Its output becomes the subcommand's context.
|
|
1102
|
+
* @param subcommands - A map of lowercase subcommand names to their
|
|
1103
|
+
* {@link CommandDescriptor}s. The keys are the literal tokens the user types.
|
|
1104
|
+
* @returns A {@link CommandDescriptor} that dispatches to one of the provided
|
|
1105
|
+
* subcommands.
|
|
1106
|
+
*
|
|
1107
|
+
* @example
|
|
1108
|
+
* ```ts
|
|
1109
|
+
* const rootCmd = commandWithSubcommands(
|
|
1110
|
+
* { description: "My CLI" },
|
|
1111
|
+
* operation({ options: {}, positionals: [] }, async (ctx) => ctx),
|
|
1112
|
+
* {
|
|
1113
|
+
* deploy: command({ description: "Deploy" }, deployOperation),
|
|
1114
|
+
* rollback: command({ description: "Rollback" }, rollbackOperation),
|
|
1115
|
+
* },
|
|
1116
|
+
* );
|
|
1117
|
+
* ```
|
|
1118
|
+
*/
|
|
192
1119
|
declare function commandWithSubcommands<Context, Payload, Result>(information: CommandInformation, operation: OperationDescriptor<Context, Payload>, subcommands: {
|
|
193
1120
|
[subcommand: Lowercase<string>]: CommandDescriptor<Payload, Result>;
|
|
194
1121
|
}): CommandDescriptor<Context, Result>;
|
|
1122
|
+
/**
|
|
1123
|
+
* Creates a command that chains two command stages by piping the output of an
|
|
1124
|
+
* {@link OperationDescriptor} directly into a {@link CommandDescriptor} as its context.
|
|
1125
|
+
*
|
|
1126
|
+
* Unlike {@link commandWithSubcommands}, there is no runtime token consumed for routing;
|
|
1127
|
+
* the `nextCommand` is always the continuation. This is useful for splitting a complex
|
|
1128
|
+
* command into reusable pieces, such as a shared authentication step followed by
|
|
1129
|
+
* different sub-actions.
|
|
1130
|
+
*
|
|
1131
|
+
* **Parsing behaviour:**
|
|
1132
|
+
* 1. `operation`'s positionals and options are parsed.
|
|
1133
|
+
* 2. `nextCommand`'s factory is immediately created from the same `readerArgs` (the
|
|
1134
|
+
* remaining unparsed tokens).
|
|
1135
|
+
* 3. At execution time, `operation` runs first; its result is passed as the context to
|
|
1136
|
+
* `nextCommand`.
|
|
1137
|
+
*
|
|
1138
|
+
* **Usage:** breadcrumbs, positionals, and options from both stages are merged into a
|
|
1139
|
+
* single flat usage description. The `information` of `nextCommand` takes precedence in
|
|
1140
|
+
* the generated usage output.
|
|
1141
|
+
*
|
|
1142
|
+
* @typeParam Context - The context value accepted by `operation`.
|
|
1143
|
+
* @typeParam Payload - The value produced by `operation` and used as the context for
|
|
1144
|
+
* `nextCommand`.
|
|
1145
|
+
* @typeParam Result - The value produced by `nextCommand`.
|
|
1146
|
+
*
|
|
1147
|
+
* @param information - Fallback metadata used in the usage output when `nextCommand`'s
|
|
1148
|
+
* factory cannot be created (i.e. on parse error in the next stage).
|
|
1149
|
+
* @param operation - The first stage operation. Its output becomes `nextCommand`'s
|
|
1150
|
+
* context.
|
|
1151
|
+
* @param nextCommand - The second stage command, executed after `operation` succeeds.
|
|
1152
|
+
* @returns A {@link CommandDescriptor} that transparently composes the two stages.
|
|
1153
|
+
*
|
|
1154
|
+
* @example
|
|
1155
|
+
* ```ts
|
|
1156
|
+
* const authenticatedDeploy = commandChained(
|
|
1157
|
+
* { description: "Authenticate then deploy" },
|
|
1158
|
+
* operation(
|
|
1159
|
+
* { options: { token: optionSingleValue({ long: "token", type: typeString, default: () => "" }) }, positionals: [] },
|
|
1160
|
+
* async (_ctx, { options: { token } }) => ({ token }),
|
|
1161
|
+
* ),
|
|
1162
|
+
* command({ description: "Deploy" }, deployOperation),
|
|
1163
|
+
* );
|
|
1164
|
+
* ```
|
|
1165
|
+
*/
|
|
195
1166
|
declare function commandChained<Context, Payload, Result>(information: CommandInformation, operation: OperationDescriptor<Context, Payload>, nextCommand: CommandDescriptor<Payload, Result>): CommandDescriptor<Context, Result>;
|
|
196
1167
|
|
|
1168
|
+
/**
|
|
1169
|
+
* Parses the provided CLI arguments against the given command descriptor, executes
|
|
1170
|
+
* the matched command, and exits the process with an appropriate exit code.
|
|
1171
|
+
*
|
|
1172
|
+
* This is the primary entry point for running a `cli-kiss`-based CLI application.
|
|
1173
|
+
* It handles argument parsing, `--help` / `--version` flags, usage printing on errors,
|
|
1174
|
+
* and exit code management.
|
|
1175
|
+
*
|
|
1176
|
+
* **Exit codes:**
|
|
1177
|
+
* - `0` — Command executed successfully, or `--help` / `--version` was handled.
|
|
1178
|
+
* - `1` — Argument parsing failed (a usage summary is also printed to stderr), or the
|
|
1179
|
+
* command threw an unhandled execution error.
|
|
1180
|
+
*
|
|
1181
|
+
* **Built-in flags (opt-out):**
|
|
1182
|
+
* - `--help` — Enabled by default (`usageOnHelp: true`). Prints the usage summary to
|
|
1183
|
+
* stdout and exits with code `0`. This flag takes precedence over `--version`.
|
|
1184
|
+
* - `--version` — Enabled when `buildVersion` is provided. Prints `<cliName> <version>`
|
|
1185
|
+
* to stdout and exits with code `0`.
|
|
1186
|
+
*
|
|
1187
|
+
* @typeParam Context - Arbitrary value passed unchanged to the command's execution handler.
|
|
1188
|
+
* Use this to inject dependencies (e.g. a database connection, a logger) into your commands.
|
|
1189
|
+
*
|
|
1190
|
+
* @param cliName - The name of the CLI program (e.g. `"my-cli"`). Used in the usage
|
|
1191
|
+
* summary header and in the `--version` output.
|
|
1192
|
+
* @param cliArgs - The raw command-line arguments to parse, typically `process.argv.slice(2)`.
|
|
1193
|
+
* @param context - The context value forwarded to the command's execution handler.
|
|
1194
|
+
* @param command - The root {@link CommandDescriptor} that describes how to parse and execute
|
|
1195
|
+
* the CLI.
|
|
1196
|
+
* @param options - Optional configuration for the runner.
|
|
1197
|
+
* @param options.useTtyColors - Controls terminal color output in styled messages.
|
|
1198
|
+
* - `true` — Always apply ANSI color codes.
|
|
1199
|
+
* - `false` — Never apply color codes (plain text).
|
|
1200
|
+
* - `"mock"` — Use a deterministic mock style useful for snapshot testing.
|
|
1201
|
+
* - `undefined` (default) — Auto-detect based on `process.stdout.isTTY` and the
|
|
1202
|
+
* `FORCE_COLOR` / `NO_COLOR` environment variables.
|
|
1203
|
+
* @param options.usageOnHelp - When `true` (default), registers a `--help` flag that
|
|
1204
|
+
* prints the usage summary and exits with code `0`.
|
|
1205
|
+
* @param options.usageOnError - When `true` (default), prints the usage summary to
|
|
1206
|
+
* stderr before the error message whenever argument parsing fails.
|
|
1207
|
+
* @param options.buildVersion - When provided, registers a `--version` flag that prints
|
|
1208
|
+
* `<cliName> <buildVersion>` to stdout and exits with code `0`.
|
|
1209
|
+
* @param options.onExecutionError - Custom handler for errors thrown during command
|
|
1210
|
+
* execution. If omitted, the error is printed to stderr via {@link TypoSupport}.
|
|
1211
|
+
* @param options.onLogStdOut - Overrides the standard output sink (default: `console.log`).
|
|
1212
|
+
* @param options.onLogStdErr - Overrides the standard error sink (default: `console.error`).
|
|
1213
|
+
* @param options.onExit - Overrides the process exit function (default: `process.exit`).
|
|
1214
|
+
* Useful for testing — supply a function that throws or captures the exit code instead
|
|
1215
|
+
* of actually terminating the process.
|
|
1216
|
+
*
|
|
1217
|
+
* @returns A `Promise<never>` because the function always terminates by calling `onExit`.
|
|
1218
|
+
*
|
|
1219
|
+
* @example
|
|
1220
|
+
* ```ts
|
|
1221
|
+
* import { runAsCliAndExit, command, operation, positionalRequired, typeString } from "cli-kiss";
|
|
1222
|
+
*
|
|
1223
|
+
* const greetCommand = command(
|
|
1224
|
+
* { description: "Greet someone" },
|
|
1225
|
+
* operation(
|
|
1226
|
+
* { options: {}, positionals: [positionalRequired({ type: typeString, label: "NAME" })] },
|
|
1227
|
+
* async (_ctx, { positionals: [name] }) => {
|
|
1228
|
+
* console.log(`Hello, ${name}!`);
|
|
1229
|
+
* },
|
|
1230
|
+
* ),
|
|
1231
|
+
* );
|
|
1232
|
+
*
|
|
1233
|
+
* await runAsCliAndExit("greet", process.argv.slice(2), undefined, greetCommand, {
|
|
1234
|
+
* buildVersion: "1.0.0",
|
|
1235
|
+
* });
|
|
1236
|
+
* ```
|
|
1237
|
+
*/
|
|
197
1238
|
declare function runAsCliAndExit<Context>(cliName: Lowercase<string>, cliArgs: ReadonlyArray<string>, context: Context, command: CommandDescriptor<Context, void>, options?: {
|
|
198
1239
|
useTtyColors?: boolean | undefined | "mock";
|
|
199
1240
|
usageOnHelp?: boolean | undefined;
|
|
@@ -205,62 +1246,331 @@ declare function runAsCliAndExit<Context>(cliName: Lowercase<string>, cliArgs: R
|
|
|
205
1246
|
onExit?: ((code: number) => never) | undefined;
|
|
206
1247
|
}): Promise<never>;
|
|
207
1248
|
|
|
1249
|
+
/**
|
|
1250
|
+
* Available foreground and background color names for terminal styling.
|
|
1251
|
+
*
|
|
1252
|
+
* Colors are divided into two groups:
|
|
1253
|
+
* - **dark** variants correspond to standard ANSI colors (codes 30–37 / 40–47).
|
|
1254
|
+
* - **bright** variants correspond to high-intensity ANSI colors (codes 90–97 / 100–107).
|
|
1255
|
+
*
|
|
1256
|
+
* Used by {@link TypoStyle}'s `fgColor` and `bgColor` fields.
|
|
1257
|
+
*/
|
|
208
1258
|
type TypoColor = "darkBlack" | "darkRed" | "darkGreen" | "darkYellow" | "darkBlue" | "darkMagenta" | "darkCyan" | "darkWhite" | "brightBlack" | "brightRed" | "brightGreen" | "brightYellow" | "brightBlue" | "brightMagenta" | "brightCyan" | "brightWhite";
|
|
1259
|
+
/**
|
|
1260
|
+
* Describes the visual styling to apply to a text segment when rendered by a
|
|
1261
|
+
* {@link TypoSupport} instance.
|
|
1262
|
+
*
|
|
1263
|
+
* All fields are optional. When `TypoSupport` is in `"none"` mode, no styling is
|
|
1264
|
+
* applied and the raw text is returned unchanged. In `"tty"` mode the corresponding
|
|
1265
|
+
* ANSI escape codes are emitted. In `"mock"` mode a deterministic textual representation
|
|
1266
|
+
* is produced (useful for snapshot tests).
|
|
1267
|
+
*/
|
|
209
1268
|
type TypoStyle = {
|
|
1269
|
+
/** Foreground (text) color. */
|
|
210
1270
|
fgColor?: TypoColor;
|
|
1271
|
+
/** Background color. */
|
|
211
1272
|
bgColor?: TypoColor;
|
|
1273
|
+
/** Render the text with reduced intensity. */
|
|
212
1274
|
dim?: boolean;
|
|
1275
|
+
/** Render the text in bold. */
|
|
213
1276
|
bold?: boolean;
|
|
1277
|
+
/** Render the text in italic. */
|
|
214
1278
|
italic?: boolean;
|
|
1279
|
+
/** Render the text with an underline. */
|
|
215
1280
|
underline?: boolean;
|
|
1281
|
+
/** Render the text with a strikethrough. */
|
|
216
1282
|
strikethrough?: boolean;
|
|
217
1283
|
};
|
|
1284
|
+
/**
|
|
1285
|
+
* Pre-defined {@link TypoStyle} for section titles in the usage output (e.g.
|
|
1286
|
+
* `"Positionals:"`, `"Options:"`).
|
|
1287
|
+
* Rendered in bold dark-green.
|
|
1288
|
+
*/
|
|
218
1289
|
declare const typoStyleTitle: TypoStyle;
|
|
1290
|
+
/** Pre-defined {@link TypoStyle} for logic/type identifiers in error messages. Rendered in bold dark-magenta. */
|
|
219
1291
|
declare const typoStyleLogic: TypoStyle;
|
|
1292
|
+
/** Pre-defined {@link TypoStyle} for quoted user-supplied values in error messages. Rendered in bold dark-yellow. */
|
|
220
1293
|
declare const typoStyleQuote: TypoStyle;
|
|
1294
|
+
/** Pre-defined {@link TypoStyle} for failure/error labels (e.g. `"Error:"`). Rendered in bold dark-red. */
|
|
221
1295
|
declare const typoStyleFailure: TypoStyle;
|
|
1296
|
+
/** Pre-defined {@link TypoStyle} for CLI flag/option/command constant names. Rendered in bold dark-cyan. */
|
|
222
1297
|
declare const typoStyleConstants: TypoStyle;
|
|
1298
|
+
/** Pre-defined {@link TypoStyle} for positional placeholders and user-input labels. Rendered in bold dark-blue. */
|
|
223
1299
|
declare const typoStyleUserInput: TypoStyle;
|
|
1300
|
+
/** Pre-defined {@link TypoStyle} for strong regular text (e.g. command descriptions). Rendered in bold. */
|
|
224
1301
|
declare const typoStyleRegularStrong: TypoStyle;
|
|
1302
|
+
/** Pre-defined {@link TypoStyle} for subtle supplementary text (e.g. hints). Rendered in italic and dim. */
|
|
225
1303
|
declare const typoStyleRegularWeaker: TypoStyle;
|
|
1304
|
+
/**
|
|
1305
|
+
* An immutable styled string segment consisting of a raw text value and an associated
|
|
1306
|
+
* {@link TypoStyle}.
|
|
1307
|
+
*
|
|
1308
|
+
* Multiple `TypoString`s are composed into a {@link TypoText} for multi-part messages.
|
|
1309
|
+
* Rendering is deferred until {@link TypoString.computeStyledString} is called with a
|
|
1310
|
+
* {@link TypoSupport} instance.
|
|
1311
|
+
*/
|
|
226
1312
|
declare class TypoString {
|
|
227
1313
|
#private;
|
|
1314
|
+
/**
|
|
1315
|
+
* @param value - The raw text content.
|
|
1316
|
+
* @param typoStyle - The style to apply when rendering. Defaults to `{}` (no style).
|
|
1317
|
+
*/
|
|
228
1318
|
constructor(value: string, typoStyle?: TypoStyle);
|
|
1319
|
+
/** Returns the unstyled raw text content. */
|
|
229
1320
|
getRawString(): string;
|
|
1321
|
+
/**
|
|
1322
|
+
* Returns the text with ANSI escape codes (or mock markers) applied by `typoSupport`.
|
|
1323
|
+
*
|
|
1324
|
+
* @param typoSupport - Controls how styles are rendered (tty colors, mock, or none).
|
|
1325
|
+
*/
|
|
230
1326
|
computeStyledString(typoSupport: TypoSupport): string;
|
|
231
1327
|
}
|
|
1328
|
+
/**
|
|
1329
|
+
* A mutable sequence of {@link TypoString} segments that together form a styled
|
|
1330
|
+
* multi-part message.
|
|
1331
|
+
*
|
|
1332
|
+
* `TypoText` is used throughout the library to build error messages and usage output
|
|
1333
|
+
* that carry styling information without being coupled to a specific output mode.
|
|
1334
|
+
* Rendering is deferred to {@link TypoText.computeStyledString}.
|
|
1335
|
+
*/
|
|
232
1336
|
declare class TypoText {
|
|
233
1337
|
#private;
|
|
1338
|
+
/**
|
|
1339
|
+
* Creates a `TypoText` pre-populated with the provided parts. Each part can be a
|
|
1340
|
+
* `TypoText` (flattened by value), a `TypoString`, or a plain `string` (wrapped in an
|
|
1341
|
+
* unstyled `TypoString`).
|
|
1342
|
+
*
|
|
1343
|
+
* @param typoParts - Initial parts to append. Can be any mix of `TypoText`,
|
|
1344
|
+
* `TypoString`, and `string`.
|
|
1345
|
+
*/
|
|
234
1346
|
constructor(...typoParts: Array<TypoText | TypoString | string>);
|
|
1347
|
+
/**
|
|
1348
|
+
* Appends a single {@link TypoString} segment to the end of this text.
|
|
1349
|
+
*
|
|
1350
|
+
* @param typoString - The segment to append.
|
|
1351
|
+
*/
|
|
235
1352
|
pushString(typoString: TypoString): void;
|
|
1353
|
+
/**
|
|
1354
|
+
* Appends all segments from another {@link TypoText} to the end of this text
|
|
1355
|
+
* (shallow copy of segments).
|
|
1356
|
+
*
|
|
1357
|
+
* @param typoText - The text whose segments are appended.
|
|
1358
|
+
*/
|
|
236
1359
|
pushText(typoText: TypoText): void;
|
|
1360
|
+
/**
|
|
1361
|
+
* Renders all segments into a single string, applying styles via `typoSupport`.
|
|
1362
|
+
*
|
|
1363
|
+
* @param typoSupport - Controls how styles are rendered.
|
|
1364
|
+
* @returns The concatenated, optionally styled string.
|
|
1365
|
+
*/
|
|
237
1366
|
computeStyledString(typoSupport: TypoSupport): string;
|
|
1367
|
+
/**
|
|
1368
|
+
* Returns the concatenation of all segments' raw (unstyled) text.
|
|
1369
|
+
* Equivalent to calling {@link TypoText.computeStyledString} with
|
|
1370
|
+
* {@link TypoSupport.none}.
|
|
1371
|
+
*/
|
|
238
1372
|
computeRawString(): string;
|
|
1373
|
+
/**
|
|
1374
|
+
* Returns the total character length of the raw (unstyled) text.
|
|
1375
|
+
* Used by {@link TypoGrid} to compute column widths for alignment.
|
|
1376
|
+
*/
|
|
239
1377
|
computeRawLength(): number;
|
|
240
1378
|
}
|
|
1379
|
+
/**
|
|
1380
|
+
* A grid of {@link TypoText} cells that renders with column-aligned padding.
|
|
1381
|
+
*
|
|
1382
|
+
* Each row is an array of `TypoText` cells. When {@link TypoGrid.computeStyledGrid} is
|
|
1383
|
+
* called, each column is padded to the width of its widest cell (measured in raw
|
|
1384
|
+
* characters). The last column in each row is **not** padded.
|
|
1385
|
+
*
|
|
1386
|
+
* Used internally by {@link usageToStyledLines} to render the `Positionals:`,
|
|
1387
|
+
* `Subcommands:`, and `Options:` sections with neat alignment.
|
|
1388
|
+
*/
|
|
241
1389
|
declare class TypoGrid {
|
|
242
1390
|
#private;
|
|
243
1391
|
constructor();
|
|
1392
|
+
/**
|
|
1393
|
+
* Appends a row of cells to the grid.
|
|
1394
|
+
*
|
|
1395
|
+
* @param cells - An ordered array of {@link TypoText} cells for this row. All rows
|
|
1396
|
+
* should have the same number of cells for alignment to be meaningful.
|
|
1397
|
+
*/
|
|
244
1398
|
pushRow(cells: Array<TypoText>): void;
|
|
1399
|
+
/**
|
|
1400
|
+
* Renders the grid into a 2-D array of styled strings, with space padding added
|
|
1401
|
+
* between columns (except after the last column).
|
|
1402
|
+
*
|
|
1403
|
+
* @param typoSupport - Controls how styles are rendered.
|
|
1404
|
+
* @returns A 2-D array where each inner array is the styled (and padded) cells of
|
|
1405
|
+
* one row. Join the inner arrays with `""` to get a single line string.
|
|
1406
|
+
*/
|
|
245
1407
|
computeStyledGrid(typoSupport: TypoSupport): Array<Array<string>>;
|
|
246
1408
|
}
|
|
1409
|
+
/**
|
|
1410
|
+
* An `Error` subclass that carries a {@link TypoText} styled message in addition to
|
|
1411
|
+
* the plain-text `Error.message` used by the standard JS error chain.
|
|
1412
|
+
*
|
|
1413
|
+
* `TypoError` is used throughout `cli-kiss` to report parsing failures (unknown option,
|
|
1414
|
+
* type decoding error, missing required argument, etc.). Its styled representation is
|
|
1415
|
+
* rendered by {@link TypoSupport.computeStyledErrorMessage} when outputting errors to
|
|
1416
|
+
* the terminal.
|
|
1417
|
+
*
|
|
1418
|
+
* Errors can be chained: if `source` is a `TypoError`, its styled text is appended
|
|
1419
|
+
* after `": "` to form the full message context chain.
|
|
1420
|
+
*/
|
|
247
1421
|
declare class TypoError extends Error {
|
|
248
1422
|
#private;
|
|
1423
|
+
/**
|
|
1424
|
+
* @param currentTypoText - The styled message for this error level.
|
|
1425
|
+
* @param source - An optional cause. If it is a `TypoError`, its styled text is
|
|
1426
|
+
* appended (chained context). If it is a plain `Error`, its `.message` is appended
|
|
1427
|
+
* as a plain string. Any other value is stringified with `String()`.
|
|
1428
|
+
*/
|
|
249
1429
|
constructor(currentTypoText: TypoText, source?: unknown);
|
|
1430
|
+
/**
|
|
1431
|
+
* Renders this error's styled message as a string.
|
|
1432
|
+
*
|
|
1433
|
+
* @param typoSupport - Controls how ANSI styles are applied.
|
|
1434
|
+
* @returns The full styled error message (without a leading `"Error:"` prefix).
|
|
1435
|
+
*/
|
|
250
1436
|
computeStyledString(typoSupport: TypoSupport): string;
|
|
1437
|
+
/**
|
|
1438
|
+
* Executes `thrower` and returns its result. If `thrower` throws any error, the error
|
|
1439
|
+
* is re-thrown as a new `TypoError` whose message is `context()` with the original
|
|
1440
|
+
* error chained as the source.
|
|
1441
|
+
*
|
|
1442
|
+
* This is a convenience helper for adding contextual information to errors that arise
|
|
1443
|
+
* deep in a call chain (e.g. "at 0: Number: Unable to parse: ...").
|
|
1444
|
+
*
|
|
1445
|
+
* @typeParam Value - The return type of `thrower`.
|
|
1446
|
+
* @param thrower - A zero-argument function whose return value is passed through on
|
|
1447
|
+
* success.
|
|
1448
|
+
* @param context - A zero-argument factory that produces the {@link TypoText} context
|
|
1449
|
+
* prepended to the caught error. Called only when `thrower` throws.
|
|
1450
|
+
* @returns The value returned by `thrower`.
|
|
1451
|
+
* @throws `TypoError` wrapping the original error with the provided context prepended.
|
|
1452
|
+
*/
|
|
251
1453
|
static tryWithContext<Value>(thrower: () => Value, context: () => TypoText): Value;
|
|
252
1454
|
}
|
|
1455
|
+
/**
|
|
1456
|
+
* Controls whether and how ANSI terminal styling is applied when rendering
|
|
1457
|
+
* {@link TypoString}, {@link TypoText}, and error messages.
|
|
1458
|
+
*
|
|
1459
|
+
* Instances are created via the static factory methods:
|
|
1460
|
+
* - {@link TypoSupport.none} — strips all styling (plain text).
|
|
1461
|
+
* - {@link TypoSupport.tty} — applies ANSI escape codes for color terminals.
|
|
1462
|
+
* - {@link TypoSupport.mock} — applies a deterministic textual representation useful
|
|
1463
|
+
* for snapshot tests.
|
|
1464
|
+
* - {@link TypoSupport.inferFromProcess} — auto-detects based on `process.stdout.isTTY`
|
|
1465
|
+
* and the `FORCE_COLOR` / `NO_COLOR` environment variables.
|
|
1466
|
+
*
|
|
1467
|
+
* `TypoSupport` is consumed by {@link runAsCliAndExit} (via the `useTtyColors` option)
|
|
1468
|
+
* and can also be used directly when building custom usage renderers with
|
|
1469
|
+
* {@link usageToStyledLines}.
|
|
1470
|
+
*/
|
|
253
1471
|
declare class TypoSupport {
|
|
254
1472
|
#private;
|
|
255
1473
|
private constructor();
|
|
1474
|
+
/**
|
|
1475
|
+
* Returns a `TypoSupport` that strips all styling — every styled string is returned
|
|
1476
|
+
* as-is (plain text, no ANSI codes).
|
|
1477
|
+
*/
|
|
256
1478
|
static none(): TypoSupport;
|
|
1479
|
+
/**
|
|
1480
|
+
* Returns a `TypoSupport` that applies ANSI escape codes.
|
|
1481
|
+
* Use this when writing to a color-capable terminal (`stdout.isTTY === true`).
|
|
1482
|
+
*/
|
|
257
1483
|
static tty(): TypoSupport;
|
|
1484
|
+
/**
|
|
1485
|
+
* Returns a `TypoSupport` that applies a deterministic mock styling representation.
|
|
1486
|
+
*
|
|
1487
|
+
* Instead of real ANSI codes, each style flag is expressed as a readable suffix:
|
|
1488
|
+
* `{text}@color`, `{text}+` (bold), `{text}-` (dim), `{text}*` (italic),
|
|
1489
|
+
* `{text}_` (underline), `{text}~` (strikethrough). Useful for snapshot testing.
|
|
1490
|
+
*/
|
|
258
1491
|
static mock(): TypoSupport;
|
|
1492
|
+
/**
|
|
1493
|
+
* Selects a `TypoSupport` mode automatically based on the current process environment:
|
|
1494
|
+
*
|
|
1495
|
+
* 1. `FORCE_COLOR=0` or `NO_COLOR` env var set → {@link TypoSupport.none}.
|
|
1496
|
+
* 2. `FORCE_COLOR` env var set (any truthy value) → {@link TypoSupport.tty}.
|
|
1497
|
+
* 3. `process.stdout.isTTY === true` → {@link TypoSupport.tty}.
|
|
1498
|
+
* 4. Otherwise → {@link TypoSupport.none}.
|
|
1499
|
+
*
|
|
1500
|
+
* Falls back to {@link TypoSupport.none} if `process` is not available (e.g. in a
|
|
1501
|
+
* non-Node environment).
|
|
1502
|
+
*/
|
|
259
1503
|
static inferFromProcess(): TypoSupport;
|
|
1504
|
+
/**
|
|
1505
|
+
* Applies the given {@link TypoStyle} to `value` and returns the styled string.
|
|
1506
|
+
*
|
|
1507
|
+
* - In `"none"` mode: returns `value` unchanged.
|
|
1508
|
+
* - In `"tty"` mode: wraps `value` in ANSI escape codes and appends a reset code.
|
|
1509
|
+
* - In `"mock"` mode: wraps `value` in a deterministic textual representation.
|
|
1510
|
+
*
|
|
1511
|
+
* @param value - The raw text to style.
|
|
1512
|
+
* @param typoStyle - The style to apply.
|
|
1513
|
+
* @returns The styled string.
|
|
1514
|
+
*/
|
|
260
1515
|
computeStyledString(value: string, typoStyle: TypoStyle): string;
|
|
1516
|
+
/**
|
|
1517
|
+
* Formats an error value as a styled `"Error: <message>"` string.
|
|
1518
|
+
*
|
|
1519
|
+
* - If `error` is a {@link TypoError}, its styled text is used for the message part.
|
|
1520
|
+
* - If `error` is a plain `Error`, its `.message` property is used.
|
|
1521
|
+
* - Otherwise `String(error)` is used.
|
|
1522
|
+
*
|
|
1523
|
+
* The `"Error:"` prefix is always styled with {@link typoStyleFailure}.
|
|
1524
|
+
*
|
|
1525
|
+
* @param error - The error to format (any value thrown by a handler).
|
|
1526
|
+
* @returns A styled error string ready to print to stderr.
|
|
1527
|
+
*/
|
|
261
1528
|
computeStyledErrorMessage(error: unknown): string;
|
|
262
1529
|
}
|
|
263
1530
|
|
|
1531
|
+
/**
|
|
1532
|
+
* Converts a {@link CommandUsage} model into an array of styled lines ready to be
|
|
1533
|
+
* joined with `"\n"` and printed to the terminal.
|
|
1534
|
+
*
|
|
1535
|
+
* The output format is:
|
|
1536
|
+
* ```
|
|
1537
|
+
* Usage: <cliName> [breadcrumbs...]
|
|
1538
|
+
*
|
|
1539
|
+
* <description> (<hint>)
|
|
1540
|
+
* <detail lines...>
|
|
1541
|
+
*
|
|
1542
|
+
* Positionals:
|
|
1543
|
+
* <LABEL> <description> (<hint>)
|
|
1544
|
+
*
|
|
1545
|
+
* Subcommands:
|
|
1546
|
+
* <name> <description> (<hint>)
|
|
1547
|
+
*
|
|
1548
|
+
* Options:
|
|
1549
|
+
* -s, --long <LABEL> <description> (<hint>)
|
|
1550
|
+
*
|
|
1551
|
+
* ```
|
|
1552
|
+
* Sections that have no entries are omitted. The trailing empty line is always included.
|
|
1553
|
+
*
|
|
1554
|
+
* Column alignment within each section is handled by {@link TypoGrid}: the widest entry
|
|
1555
|
+
* in each column sets the width for the entire section.
|
|
1556
|
+
*
|
|
1557
|
+
* @param params.cliName - The CLI program name shown at the start of the usage line.
|
|
1558
|
+
* @param params.commandUsage - The usage model produced by
|
|
1559
|
+
* {@link CommandFactory.generateUsage}.
|
|
1560
|
+
* @param params.typoSupport - Controls color/styling of the output.
|
|
1561
|
+
* @returns An ordered array of strings, one per output line (including a trailing
|
|
1562
|
+
* empty string for the blank line at the end).
|
|
1563
|
+
*
|
|
1564
|
+
* @example
|
|
1565
|
+
* ```ts
|
|
1566
|
+
* const lines = usageToStyledLines({
|
|
1567
|
+
* cliName: "my-cli",
|
|
1568
|
+
* commandUsage: commandFactory.generateUsage(),
|
|
1569
|
+
* typoSupport: TypoSupport.none(),
|
|
1570
|
+
* });
|
|
1571
|
+
* process.stdout.write(lines.join("\n"));
|
|
1572
|
+
* ```
|
|
1573
|
+
*/
|
|
264
1574
|
declare function usageToStyledLines(params: {
|
|
265
1575
|
cliName: Lowercase<string>;
|
|
266
1576
|
commandUsage: CommandUsage;
|