@thi.ng/args 2.10.2 → 3.1.0
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/CHANGELOG.md +29 -1
- package/README.md +37 -14
- package/api.d.ts +66 -24
- package/args.d.ts +148 -85
- package/args.js +85 -54
- package/coerce.d.ts +0 -3
- package/coerce.js +0 -6
- package/package.json +2 -2
- package/parse.js +18 -20
- package/usage.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2025-09-
|
|
3
|
+
- **Last updated**: 2025-09-26T13:50:05Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -11,6 +11,34 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
11
11
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
12
12
|
and/or version bumps of transitive dependencies.
|
|
13
13
|
|
|
14
|
+
## [3.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/args@3.1.0) (2025-09-26)
|
|
15
|
+
|
|
16
|
+
#### 🚀 Features
|
|
17
|
+
|
|
18
|
+
- add ARG_TYPES index ([5f68489](https://github.com/thi-ng/umbrella/commit/5f68489))
|
|
19
|
+
|
|
20
|
+
#### ♻️ Refactoring
|
|
21
|
+
|
|
22
|
+
- update factory fns to only take single arg (spec) ([2766125](https://github.com/thi-ng/umbrella/commit/2766125))
|
|
23
|
+
- update `oneOf`, `oneOfMulti`, `tuple`, `size`, `vec`
|
|
24
|
+
- fix `required`-handling in `ARG_OUT_DIR` & `ARG_OUT_FILE` presets
|
|
25
|
+
- fix code example for `tuple()`
|
|
26
|
+
- update tests
|
|
27
|
+
|
|
28
|
+
# [3.0.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/args@3.0.0) (2025-09-26)
|
|
29
|
+
|
|
30
|
+
#### 🛑 Breaking changes
|
|
31
|
+
|
|
32
|
+
- update arg specs & arg factory fns, simplify types ([7ad3efb](https://github.com/thi-ng/umbrella/commit/7ad3efb))
|
|
33
|
+
- BREAKING CHANGES: update arg specs & arg factory fns, simplify types
|
|
34
|
+
- add `type` field in all arg specs
|
|
35
|
+
- add/update arg-related types
|
|
36
|
+
- update required arg handling: `optional: false` => `required: true`
|
|
37
|
+
- update delimiter handling (move into arg specs)
|
|
38
|
+
- update `tuple()` arg order
|
|
39
|
+
- remove obsolete coercion fns (`coerceFloats()` etc.)
|
|
40
|
+
- update tests
|
|
41
|
+
|
|
14
42
|
## [2.10.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/args@2.10.0) (2025-09-04)
|
|
15
43
|
|
|
16
44
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
- [Re-usable argument presets](#re-usable-argument-presets)
|
|
20
20
|
- [CLI app framework](#cli-app-framework)
|
|
21
21
|
- [Status](#status)
|
|
22
|
+
- [Breaking changes in 3.0.0](#breaking-changes-in-300)
|
|
22
23
|
- [Installation](#installation)
|
|
23
24
|
- [Dependencies](#dependencies)
|
|
24
25
|
- [Projects using this package](#projects-using-this-package)
|
|
@@ -97,6 +98,19 @@ section](#projects-using-this-package) in this readme.
|
|
|
97
98
|
|
|
98
99
|
[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=%5Bargs%5D+in%3Atitle)
|
|
99
100
|
|
|
101
|
+
### Breaking changes in 3.0.0
|
|
102
|
+
|
|
103
|
+
- Required arguments are now to be specified using either `required: true` or
|
|
104
|
+
given a `default` value
|
|
105
|
+
- All factory functions now only accept a single arg spec, with any type-specific
|
|
106
|
+
options moved into the spec, for example:
|
|
107
|
+
- old: `oneOf(["a","b","c"], {...})`
|
|
108
|
+
- new: `oneOf({ opts: ["a","b","c"], ...})`
|
|
109
|
+
- old: `tuple(identity, 3, {...})`
|
|
110
|
+
- new: `tuple({ size: 3, coerce: identity, ...})`
|
|
111
|
+
- Where applicable, `delim`iters are now to be included in the arg spec (rather
|
|
112
|
+
than given as separate function arg)
|
|
113
|
+
|
|
100
114
|
## Installation
|
|
101
115
|
|
|
102
116
|
```bash
|
|
@@ -115,7 +129,7 @@ For Node.js REPL:
|
|
|
115
129
|
const args = await import("@thi.ng/args");
|
|
116
130
|
```
|
|
117
131
|
|
|
118
|
-
Package sizes (brotli'd, pre-treeshake): ESM: 3.
|
|
132
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 3.47 KB
|
|
119
133
|
|
|
120
134
|
## Dependencies
|
|
121
135
|
|
|
@@ -191,42 +205,51 @@ const specs: Args<TestArgs> = {
|
|
|
191
205
|
hint: "PATH",
|
|
192
206
|
desc: "Config file path (CLI args always take precedence over those settings)",
|
|
193
207
|
}),
|
|
208
|
+
|
|
194
209
|
// boolean flag (default: false)
|
|
195
210
|
force: flag({
|
|
196
211
|
alias: "f",
|
|
197
212
|
desc: "Force operation",
|
|
198
|
-
// side effect
|
|
199
|
-
// parsing only continues if
|
|
213
|
+
// side effect and/or validation
|
|
214
|
+
// parsing only continues if function returns true
|
|
200
215
|
fn: (_) => (console.log("force mode enabled"), true),
|
|
201
216
|
}),
|
|
217
|
+
|
|
202
218
|
// hex int value
|
|
203
219
|
bg: hex({
|
|
204
220
|
desc: "Background color",
|
|
205
|
-
// mandatory args require a `default` value and/or `
|
|
221
|
+
// mandatory args require a `default` value and/or `required: true`
|
|
206
222
|
default: 0xffffff,
|
|
207
223
|
defaultHint: "ffffff",
|
|
208
224
|
}),
|
|
225
|
+
|
|
209
226
|
// enum value (mandatory)
|
|
210
|
-
type: oneOf(
|
|
227
|
+
type: oneOf({
|
|
211
228
|
alias: "t",
|
|
212
229
|
desc: "Image type",
|
|
213
|
-
|
|
214
|
-
|
|
230
|
+
opts: ["png", "jpg", "gif", "tiff"],
|
|
231
|
+
// mandatory args require a `default` value and/or `required: true`
|
|
232
|
+
required: true,
|
|
215
233
|
}),
|
|
234
|
+
|
|
216
235
|
// fixed size numeric tuple w/ `x` as delimiter
|
|
217
|
-
|
|
218
|
-
// syntax sugar for
|
|
219
|
-
size:
|
|
236
|
+
size: size({ size: 2, hint: "WxH", desc: "Target size", delim: "x" }),
|
|
237
|
+
// syntax sugar for:
|
|
238
|
+
// size: tuple(2, coerceInt, { hint: "WxH", desc: "Target size" }, "x"),
|
|
239
|
+
|
|
220
240
|
// another version for tuples of floating point values
|
|
221
|
-
|
|
222
|
-
|
|
241
|
+
pos: vec({ size: 2, desc: "Lat/Lon coordinates", hint: "LAT,LON" }),
|
|
242
|
+
// syntax sugar for:
|
|
243
|
+
// pos: tuple(2, coerceFloat, { desc: "Lat/Lon" }),
|
|
244
|
+
|
|
223
245
|
// JSON string arg
|
|
224
246
|
xtra: json({
|
|
225
247
|
alias: "x",
|
|
226
248
|
desc: "Extra options",
|
|
227
249
|
group: "extra",
|
|
228
250
|
}),
|
|
229
|
-
|
|
251
|
+
|
|
252
|
+
// key-value pairs parsed into an object (multiple allowed)
|
|
230
253
|
define: kvPairs({
|
|
231
254
|
alias: "D",
|
|
232
255
|
desc: "Define dict entry",
|
|
@@ -382,7 +405,7 @@ const HELLO: Command<HelloOpts, CommonOpts> = {
|
|
|
382
405
|
name: string({
|
|
383
406
|
alias: "n",
|
|
384
407
|
desc: "Name for greeting",
|
|
385
|
-
|
|
408
|
+
required: true,
|
|
386
409
|
}),
|
|
387
410
|
},
|
|
388
411
|
// this command does not accept any inputs
|
package/api.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import type { Fn, Fn2, IDeref, IObjectOf } from "@thi.ng/api";
|
|
1
|
+
import type { Fn, Fn2, IDeref, IObjectOf, Predicate } from "@thi.ng/api";
|
|
2
2
|
import type { ILogger } from "@thi.ng/logger";
|
|
3
3
|
import type { FormatPresets } from "@thi.ng/text-format";
|
|
4
4
|
export interface ArgSpecBase {
|
|
5
|
+
/**
|
|
6
|
+
* Unique arg type ID
|
|
7
|
+
*/
|
|
8
|
+
type: string;
|
|
5
9
|
/**
|
|
6
10
|
* Shorthand for given arg/option
|
|
7
11
|
*/
|
|
@@ -31,44 +35,82 @@ export interface ArgSpecBase {
|
|
|
31
35
|
*/
|
|
32
36
|
group?: string;
|
|
33
37
|
}
|
|
34
|
-
export type
|
|
35
|
-
|
|
38
|
+
export type ArgSpec<T> = ArgSpecBase & ArgSpecRequired<T>;
|
|
39
|
+
export type ArgSpecRequired<T> = undefined extends T ? {
|
|
40
|
+
default?: T;
|
|
41
|
+
} : {
|
|
42
|
+
required: true;
|
|
36
43
|
} | {
|
|
37
44
|
default: T;
|
|
38
45
|
};
|
|
39
|
-
export type
|
|
46
|
+
export type Args<T extends object> = {
|
|
47
|
+
[id in keyof T]: ArgSpec<T[id]>;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Partial arg spec given to various argument factory functions.
|
|
51
|
+
*/
|
|
52
|
+
export type ArgDef = Omit<ArgSpecBase, "type">;
|
|
53
|
+
/**
|
|
54
|
+
* Partial arg spec (for required arguments) given to various argument factory
|
|
55
|
+
* functions.
|
|
56
|
+
*/
|
|
57
|
+
export type ArgDefRequired<T> = ArgDef & ({
|
|
58
|
+
default: T;
|
|
59
|
+
} | {
|
|
60
|
+
required: true;
|
|
61
|
+
});
|
|
62
|
+
/**
|
|
63
|
+
* @internal
|
|
64
|
+
*/
|
|
40
65
|
export type ArgSpecExt = ArgSpec<any> & {
|
|
66
|
+
/**
|
|
67
|
+
* Value coercion fn.
|
|
68
|
+
*/
|
|
41
69
|
coerce?: Fn<any, any>;
|
|
70
|
+
/**
|
|
71
|
+
* Delimiter to split values (only used for `multi` args and if `split=false`)
|
|
72
|
+
*/
|
|
42
73
|
delim?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Default value
|
|
76
|
+
*/
|
|
43
77
|
default?: any;
|
|
44
|
-
|
|
45
|
-
|
|
78
|
+
/**
|
|
79
|
+
* User defined validation fn (can be used for side effects too).
|
|
80
|
+
*/
|
|
81
|
+
fn?: Predicate<string>;
|
|
82
|
+
/**
|
|
83
|
+
* Indicator flag for args accepting multiple values
|
|
84
|
+
*/
|
|
46
85
|
multi?: boolean;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
} : KVDict extends T[id] ? ArgSpec<T[id]> & {
|
|
57
|
-
coerce: Fn<string[], Exclude<T[id], undefined>>;
|
|
58
|
-
multi: true;
|
|
59
|
-
} : KVMultiDict extends T[id] ? ArgSpec<T[id]> & {
|
|
60
|
-
coerce: Fn<string[], Exclude<T[id], undefined>>;
|
|
61
|
-
multi: true;
|
|
62
|
-
} : ArgSpec<T[id]> & {
|
|
63
|
-
coerce: Fn<string, Exclude<T[id], undefined>>;
|
|
64
|
-
};
|
|
86
|
+
/**
|
|
87
|
+
* Indicator flag for required args.
|
|
88
|
+
*/
|
|
89
|
+
required?: true;
|
|
90
|
+
/**
|
|
91
|
+
* Unless false, collected values are split via `delim` prior to calling
|
|
92
|
+
* coercion function. Only used for `multi` specs.
|
|
93
|
+
*/
|
|
94
|
+
split?: boolean;
|
|
65
95
|
};
|
|
66
96
|
export type KVDict = IObjectOf<string>;
|
|
67
97
|
export type KVMultiDict = IObjectOf<string[]>;
|
|
68
98
|
export interface ParseResult<T> {
|
|
99
|
+
/**
|
|
100
|
+
* Parsed arguments
|
|
101
|
+
*/
|
|
69
102
|
result: T;
|
|
103
|
+
/**
|
|
104
|
+
* `process.argv` index (+1) where parsing stopped
|
|
105
|
+
*/
|
|
70
106
|
index: number;
|
|
107
|
+
/**
|
|
108
|
+
* If true, all elements of `process.argv` have been consumed
|
|
109
|
+
*/
|
|
71
110
|
done: boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Remaining unparsed elements of `process.argv` (if any)
|
|
113
|
+
*/
|
|
72
114
|
rest: string[];
|
|
73
115
|
}
|
|
74
116
|
export interface ParseOpts {
|
package/args.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { type Fn } from "@thi.ng/api/fn";
|
|
2
|
-
import type { ArgSpec, KVDict, KVMultiDict, Tuple } from "./api.js";
|
|
2
|
+
import type { ArgDef, ArgDefRequired, ArgSpec, KVDict, KVMultiDict, Tuple } from "./api.js";
|
|
3
3
|
/**
|
|
4
4
|
* Returns a full {@link ArgSpec} for a boolean flag. The mere presence of this
|
|
5
5
|
* arg will enable the flag.
|
|
6
6
|
*
|
|
7
7
|
* @param spec -
|
|
8
8
|
*/
|
|
9
|
-
export declare const flag: <S extends
|
|
10
|
-
|
|
9
|
+
export declare const flag: <S extends ArgDef>(spec: S) => S & {
|
|
10
|
+
type: "flag";
|
|
11
11
|
default: boolean;
|
|
12
12
|
group: string;
|
|
13
13
|
};
|
|
@@ -16,7 +16,8 @@ export declare const flag: <S extends Partial<ArgSpec<boolean>>>(spec: S) => S &
|
|
|
16
16
|
*
|
|
17
17
|
* @param spec -
|
|
18
18
|
*/
|
|
19
|
-
export declare const string: <S extends
|
|
19
|
+
export declare const string: <S extends ArgDef | ArgDefRequired<string>>(spec: S) => S & {
|
|
20
|
+
type: "string";
|
|
20
21
|
coerce: Fn<string, string>;
|
|
21
22
|
hint: string;
|
|
22
23
|
group: string;
|
|
@@ -28,13 +29,15 @@ export declare const string: <S extends Partial<ArgSpec<string>>>(spec: S) => S
|
|
|
28
29
|
*
|
|
29
30
|
* @param spec -
|
|
30
31
|
*/
|
|
31
|
-
export declare const strings: <S extends
|
|
32
|
-
delim
|
|
33
|
-
}
|
|
34
|
-
|
|
32
|
+
export declare const strings: <S extends ArgDef | ArgDefRequired<unknown[]>>(spec: S & {
|
|
33
|
+
delim?: string;
|
|
34
|
+
}) => S & {
|
|
35
|
+
type: "strings";
|
|
36
|
+
coerce: Fn<string[], unknown[]>;
|
|
35
37
|
hint: string;
|
|
36
|
-
multi: true;
|
|
37
38
|
group: string;
|
|
39
|
+
delim: string;
|
|
40
|
+
multi: true;
|
|
38
41
|
};
|
|
39
42
|
/**
|
|
40
43
|
* Returns a full {@link ArgSpec} for a floating point value arg. The value
|
|
@@ -42,21 +45,28 @@ export declare const strings: <S extends Partial<ArgSpec<string[]> & {
|
|
|
42
45
|
*
|
|
43
46
|
* @param spec -
|
|
44
47
|
*/
|
|
45
|
-
export declare const float: <S extends
|
|
48
|
+
export declare const float: <S extends ArgDef | ArgDefRequired<number>>(spec: S) => S & {
|
|
49
|
+
type: "float";
|
|
46
50
|
coerce: Fn<string, number>;
|
|
47
51
|
hint: string;
|
|
48
52
|
group: string;
|
|
49
53
|
};
|
|
50
54
|
/**
|
|
51
|
-
* Returns a full {@link ArgSpec} for a
|
|
52
|
-
*
|
|
55
|
+
* Multi-arg version of {@link float}. Returns a full {@link ArgSpec} for a
|
|
56
|
+
* multi floating point value arg. This argument can be provided mutiple times
|
|
57
|
+
* with values being coerced into numbers and collected into an array.
|
|
53
58
|
*
|
|
54
59
|
* @param spec -
|
|
55
60
|
*/
|
|
56
|
-
export declare const
|
|
57
|
-
|
|
61
|
+
export declare const floats: <S extends ArgDef | ArgDefRequired<unknown[]>>(spec: S & {
|
|
62
|
+
delim?: string;
|
|
63
|
+
}) => S & {
|
|
64
|
+
type: "floats";
|
|
65
|
+
coerce: Fn<string[], unknown[]>;
|
|
58
66
|
hint: string;
|
|
59
67
|
group: string;
|
|
68
|
+
delim: string;
|
|
69
|
+
multi: true;
|
|
60
70
|
};
|
|
61
71
|
/**
|
|
62
72
|
* Returns a full {@link ArgSpec} for a single integer value arg. The value
|
|
@@ -64,66 +74,57 @@ export declare const hex: <S extends Partial<ArgSpec<number>>>(spec: S) => S & {
|
|
|
64
74
|
*
|
|
65
75
|
* @param spec -
|
|
66
76
|
*/
|
|
67
|
-
export declare const int: <S extends
|
|
77
|
+
export declare const int: <S extends ArgDef | ArgDefRequired<number>>(spec: S) => S & {
|
|
78
|
+
type: "int";
|
|
68
79
|
coerce: Fn<string, number>;
|
|
69
80
|
hint: string;
|
|
70
81
|
group: string;
|
|
71
82
|
};
|
|
72
83
|
/**
|
|
73
|
-
* Multi-arg version of {@link
|
|
74
|
-
*
|
|
75
|
-
*
|
|
84
|
+
* Multi-arg version of {@link int}. Returns a full {@link ArgSpec} for a multi
|
|
85
|
+
* integer value arg. This argument can be provided mutiple times with values
|
|
86
|
+
* being coerced into numbers and collected into an array.
|
|
76
87
|
*
|
|
77
88
|
* @param spec -
|
|
78
89
|
*/
|
|
79
|
-
export declare const
|
|
80
|
-
delim
|
|
81
|
-
}
|
|
82
|
-
|
|
90
|
+
export declare const ints: <S extends ArgDef | ArgDefRequired<unknown[]>>(spec: S & {
|
|
91
|
+
delim?: string;
|
|
92
|
+
}) => S & {
|
|
93
|
+
type: "ints";
|
|
94
|
+
coerce: Fn<string[], unknown[]>;
|
|
83
95
|
hint: string;
|
|
84
|
-
multi: true;
|
|
85
96
|
group: string;
|
|
86
|
-
};
|
|
87
|
-
/**
|
|
88
|
-
* Multi-arg version of {@link hex}. Returns a full {@link ArgSpec} for a multi
|
|
89
|
-
* hex integer value arg. This argument can be provided mutiple times with
|
|
90
|
-
* values being coerced into numbers and collected into an array.
|
|
91
|
-
*
|
|
92
|
-
* @param spec -
|
|
93
|
-
*/
|
|
94
|
-
export declare const hexes: <S extends Partial<ArgSpec<number[]> & {
|
|
95
97
|
delim: string;
|
|
96
|
-
}>>(spec: S) => S & {
|
|
97
|
-
coerce: Fn<string[], number[]>;
|
|
98
|
-
hint: string;
|
|
99
98
|
multi: true;
|
|
100
|
-
group: string;
|
|
101
99
|
};
|
|
102
100
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* being coerced into numbers and collected into an array.
|
|
101
|
+
* Returns a full {@link ArgSpec} for a single hex integer value arg. The value
|
|
102
|
+
* will be autoatically coerced into a number using {@link coerceHexInt}.
|
|
106
103
|
*
|
|
107
104
|
* @param spec -
|
|
108
105
|
*/
|
|
109
|
-
export declare const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
coerce: Fn<string[], number[]>;
|
|
106
|
+
export declare const hex: <S extends ArgDef | ArgDefRequired<number>>(spec: S) => S & {
|
|
107
|
+
type: "hex";
|
|
108
|
+
coerce: Fn<string, number>;
|
|
113
109
|
hint: string;
|
|
114
|
-
multi: true;
|
|
115
110
|
group: string;
|
|
116
111
|
};
|
|
117
112
|
/**
|
|
118
|
-
*
|
|
119
|
-
*
|
|
113
|
+
* Multi-arg version of {@link hex}. Returns a full {@link ArgSpec} for a multi
|
|
114
|
+
* hex integer value arg. This argument can be provided mutiple times with
|
|
115
|
+
* values being coerced into numbers and collected into an array.
|
|
120
116
|
*
|
|
121
117
|
* @param spec -
|
|
122
118
|
*/
|
|
123
|
-
export declare const
|
|
124
|
-
|
|
119
|
+
export declare const hexes: <S extends ArgDef | ArgDefRequired<unknown[]>>(spec: S & {
|
|
120
|
+
delim?: string;
|
|
121
|
+
}) => S & {
|
|
122
|
+
type: "hexes";
|
|
123
|
+
coerce: Fn<string[], unknown[]>;
|
|
125
124
|
hint: string;
|
|
126
125
|
group: string;
|
|
126
|
+
delim: string;
|
|
127
|
+
multi: true;
|
|
127
128
|
};
|
|
128
129
|
/**
|
|
129
130
|
* Returns full {@link ArgSpec} for an enum-like string value arg. The raw CLI
|
|
@@ -132,12 +133,15 @@ export declare const json: <T, S extends Partial<ArgSpec<T>>>(spec: S) => S & {
|
|
|
132
133
|
* @param opts -
|
|
133
134
|
* @param spec -
|
|
134
135
|
*/
|
|
135
|
-
export declare const oneOf: <K extends string, S extends
|
|
136
|
+
export declare const oneOf: <K extends string, S extends ArgDef | ArgDefRequired<K>>(spec: S & {
|
|
137
|
+
opts: readonly K[];
|
|
138
|
+
}) => S & {
|
|
139
|
+
type: "oneOf";
|
|
136
140
|
coerce: Fn<string, K>;
|
|
141
|
+
desc: string;
|
|
137
142
|
hint: string;
|
|
138
143
|
group: string;
|
|
139
|
-
|
|
140
|
-
desc: string;
|
|
144
|
+
opts: readonly K[];
|
|
141
145
|
};
|
|
142
146
|
/**
|
|
143
147
|
* Multi-arg version of {@link oneOf}. Returns full {@link ArgSpec} for multiple
|
|
@@ -147,15 +151,18 @@ export declare const oneOf: <K extends string, S extends Partial<ArgSpec<K>>>(op
|
|
|
147
151
|
* @param opts -
|
|
148
152
|
* @param spec -
|
|
149
153
|
*/
|
|
150
|
-
export declare const oneOfMulti: <K extends string, S extends
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
+
export declare const oneOfMulti: <K extends string, S extends ArgDef | ArgDefRequired<K>>(spec: S & {
|
|
155
|
+
opts: readonly K[];
|
|
156
|
+
delim?: string;
|
|
157
|
+
}) => S & {
|
|
158
|
+
type: "oneOfMulti";
|
|
159
|
+
coerce: Fn<string, K>;
|
|
160
|
+
desc: string;
|
|
154
161
|
hint: string;
|
|
155
|
-
multi: true;
|
|
156
162
|
group: string;
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
multi: true;
|
|
164
|
+
opts: readonly K[];
|
|
165
|
+
delim?: string;
|
|
159
166
|
};
|
|
160
167
|
/**
|
|
161
168
|
* Returns a full {@link ArgSpec} for multiple `key=value` pair args, coerced
|
|
@@ -167,13 +174,19 @@ export declare const oneOfMulti: <K extends string, S extends Partial<ArgSpec<K[
|
|
|
167
174
|
* is true, only full KV pairs are allowed.
|
|
168
175
|
*
|
|
169
176
|
* @param spec -
|
|
170
|
-
* @param delim -
|
|
171
177
|
*/
|
|
172
|
-
export declare const kvPairs: <S extends
|
|
178
|
+
export declare const kvPairs: <S extends ArgDef | ArgDefRequired<KVDict>>(spec: S & {
|
|
179
|
+
delim?: string;
|
|
180
|
+
strict?: boolean;
|
|
181
|
+
}) => S & {
|
|
182
|
+
type: "kvPairs";
|
|
173
183
|
coerce: Fn<string[], KVDict>;
|
|
174
184
|
hint: string;
|
|
175
|
-
multi: true;
|
|
176
185
|
group: string;
|
|
186
|
+
multi: true;
|
|
187
|
+
kvDelim?: string;
|
|
188
|
+
strict?: boolean;
|
|
189
|
+
split: false;
|
|
177
190
|
};
|
|
178
191
|
/**
|
|
179
192
|
* Like {@link kvPairs}, but coerces KV pairs into a result {@link KVMultiDict}
|
|
@@ -181,20 +194,24 @@ export declare const kvPairs: <S extends Partial<ArgSpec<KVDict>>>(spec: S, deli
|
|
|
181
194
|
* into arrays).
|
|
182
195
|
*
|
|
183
196
|
* @param spec -
|
|
184
|
-
* @param delim -
|
|
185
|
-
* @param strict -
|
|
186
197
|
*/
|
|
187
|
-
export declare const kvPairsMulti: <S extends
|
|
198
|
+
export declare const kvPairsMulti: <S extends ArgDef | ArgDefRequired<KVMultiDict>>(spec: S & {
|
|
199
|
+
delim?: string;
|
|
200
|
+
strict?: boolean;
|
|
201
|
+
}) => S & {
|
|
202
|
+
type: "kvPairsMulti";
|
|
188
203
|
coerce: Fn<string[], KVMultiDict>;
|
|
189
204
|
hint: string;
|
|
190
|
-
multi: true;
|
|
191
205
|
group: string;
|
|
206
|
+
multi: true;
|
|
207
|
+
delim?: string;
|
|
208
|
+
strict?: boolean;
|
|
192
209
|
};
|
|
193
210
|
/**
|
|
194
211
|
* Returns a full {@link ArgSpec} for a fixed `size` tuple extracted from a
|
|
195
|
-
* single value string. The individual values are delimited by `delim`
|
|
196
|
-
* be coerced into their target type via `coerce`. The result
|
|
197
|
-
* wrapped in a {@link Tuple} instance.
|
|
212
|
+
* single value string. The individual values are delimited by `delim` (default:
|
|
213
|
+
* `,`) and will be coerced into their target type via `coerce`. The result
|
|
214
|
+
* tuple will be wrapped in a {@link Tuple} instance.
|
|
198
215
|
*
|
|
199
216
|
* @remarks
|
|
200
217
|
* An error will be thrown if the number of extracted values differs from the
|
|
@@ -202,10 +219,18 @@ export declare const kvPairsMulti: <S extends Partial<ArgSpec<KVMultiDict>>>(spe
|
|
|
202
219
|
*
|
|
203
220
|
* @example
|
|
204
221
|
* ```ts tangle:../export/tuple.ts
|
|
205
|
-
* import { coerceInt, parse, tuple } from "@thi.ng/args";
|
|
222
|
+
* import { coerceInt, parse, tuple, type Tuple } from "@thi.ng/args";
|
|
223
|
+
*
|
|
224
|
+
* interface A {
|
|
225
|
+
* a?: Tuple<number>;
|
|
226
|
+
* }
|
|
206
227
|
*
|
|
207
228
|
* console.log(
|
|
208
|
-
* parse(
|
|
229
|
+
* parse<A>(
|
|
230
|
+
* { a: tuple({ size: 2, coerce: coerceInt }) },
|
|
231
|
+
* ["--a", "1,2"],
|
|
232
|
+
* { start: 0 }
|
|
233
|
+
* )
|
|
209
234
|
* );
|
|
210
235
|
* // {
|
|
211
236
|
* // result: { a: Tuple { value: [1, 2] } },
|
|
@@ -215,40 +240,78 @@ export declare const kvPairsMulti: <S extends Partial<ArgSpec<KVMultiDict>>>(spe
|
|
|
215
240
|
* // }
|
|
216
241
|
* ```
|
|
217
242
|
*
|
|
218
|
-
* @param coerce -
|
|
219
|
-
* @param size -
|
|
220
243
|
* @param spec -
|
|
221
|
-
* @param delim -
|
|
222
244
|
*/
|
|
223
|
-
export declare const tuple: <T, S extends
|
|
245
|
+
export declare const tuple: <T, S extends ArgDef | ArgDefRequired<Tuple<T>>>(spec: S & {
|
|
246
|
+
size: number;
|
|
247
|
+
coerce: Fn<string, T>;
|
|
248
|
+
delim?: string;
|
|
249
|
+
}) => S & {
|
|
250
|
+
type: "tuple";
|
|
224
251
|
coerce: Fn<string, Tuple<T>>;
|
|
225
252
|
hint: string;
|
|
226
253
|
group: string;
|
|
254
|
+
size: number;
|
|
255
|
+
delim?: string;
|
|
227
256
|
};
|
|
228
257
|
/**
|
|
229
|
-
* Syntax sugar for `tuple(
|
|
258
|
+
* Syntax sugar for `tuple(size, coerceInt, {...})`. See {@link tuple} for
|
|
259
|
+
* further details.
|
|
230
260
|
*
|
|
231
|
-
* @param size -
|
|
232
261
|
* @param spec -
|
|
233
|
-
* @param delim -
|
|
234
262
|
*/
|
|
235
|
-
export declare const size: <S extends
|
|
263
|
+
export declare const size: <S extends ArgDef | ArgDefRequired<Tuple<number>>>(spec: S & {
|
|
264
|
+
size: number;
|
|
265
|
+
delim?: string;
|
|
266
|
+
}) => S & {
|
|
267
|
+
coerce: (x: string) => number;
|
|
268
|
+
size: number;
|
|
269
|
+
delim?: string;
|
|
270
|
+
} & {
|
|
271
|
+
type: "tuple";
|
|
236
272
|
coerce: Fn<string, Tuple<number>>;
|
|
237
273
|
hint: string;
|
|
238
274
|
group: string;
|
|
275
|
+
size: number;
|
|
276
|
+
delim?: string;
|
|
239
277
|
};
|
|
240
278
|
/**
|
|
241
|
-
* Syntax sugar for `tuple(
|
|
279
|
+
* Syntax sugar for `tuple(size, coerceFloat, {...})`. See {@link tuple} for
|
|
280
|
+
* further details.
|
|
242
281
|
*
|
|
243
|
-
* @param size -
|
|
244
282
|
* @param spec -
|
|
245
|
-
* @param delim -
|
|
246
283
|
*/
|
|
247
|
-
export declare const vec: <S extends
|
|
284
|
+
export declare const vec: <S extends ArgDef | ArgDefRequired<Tuple<number>>>(spec: S & {
|
|
285
|
+
size: number;
|
|
286
|
+
delim?: string;
|
|
287
|
+
}) => S & {
|
|
288
|
+
coerce: (x: string) => number;
|
|
289
|
+
size: number;
|
|
290
|
+
delim?: string;
|
|
291
|
+
} & {
|
|
292
|
+
type: "tuple";
|
|
248
293
|
coerce: Fn<string, Tuple<number>>;
|
|
249
294
|
hint: string;
|
|
250
295
|
group: string;
|
|
296
|
+
size: number;
|
|
297
|
+
delim?: string;
|
|
251
298
|
};
|
|
299
|
+
/**
|
|
300
|
+
* Returns full {@link ArgSpec} for a JSON value arg. The raw CLI value string
|
|
301
|
+
* will be automcatically coerced using {@link coerceJson}.
|
|
302
|
+
*
|
|
303
|
+
* @param spec -
|
|
304
|
+
*/
|
|
305
|
+
export declare const json: <T, S extends ArgDef | ArgDefRequired<T>>(spec: S) => S & {
|
|
306
|
+
type: "json";
|
|
307
|
+
coerce: Fn<string, T>;
|
|
308
|
+
hint: string;
|
|
309
|
+
group: string;
|
|
310
|
+
};
|
|
311
|
+
/**
|
|
312
|
+
* Index which maps arg type IDs to their factory functions
|
|
313
|
+
*/
|
|
314
|
+
export declare const ARG_TYPES: Record<string, Fn<any, ArgSpec<any>>>;
|
|
252
315
|
/**
|
|
253
316
|
* Re-usable preset arg spec for a `--dry-run` flag.
|
|
254
317
|
*/
|
|
@@ -256,7 +319,7 @@ export declare const ARG_DRY_RUN: {
|
|
|
256
319
|
dryRun: {
|
|
257
320
|
desc: string;
|
|
258
321
|
} & {
|
|
259
|
-
|
|
322
|
+
type: "flag";
|
|
260
323
|
default: boolean;
|
|
261
324
|
group: string;
|
|
262
325
|
};
|
|
@@ -269,7 +332,7 @@ export declare const ARG_QUIET: {
|
|
|
269
332
|
alias: string;
|
|
270
333
|
desc: string;
|
|
271
334
|
} & {
|
|
272
|
-
|
|
335
|
+
type: "flag";
|
|
273
336
|
default: boolean;
|
|
274
337
|
group: string;
|
|
275
338
|
};
|
|
@@ -282,7 +345,7 @@ export declare const ARG_VERBOSE: {
|
|
|
282
345
|
alias: string;
|
|
283
346
|
desc: string;
|
|
284
347
|
} & {
|
|
285
|
-
|
|
348
|
+
type: "flag";
|
|
286
349
|
default: boolean;
|
|
287
350
|
group: string;
|
|
288
351
|
};
|
package/args.js
CHANGED
|
@@ -2,88 +2,118 @@ import { identity } from "@thi.ng/api/fn";
|
|
|
2
2
|
import { repeat } from "@thi.ng/strings/repeat";
|
|
3
3
|
import {
|
|
4
4
|
coerceFloat,
|
|
5
|
-
coerceFloats,
|
|
6
5
|
coerceHexInt,
|
|
7
|
-
coerceHexInts,
|
|
8
6
|
coerceInt,
|
|
9
|
-
coerceInts,
|
|
10
7
|
coerceJson,
|
|
11
8
|
coerceKV,
|
|
12
9
|
coerceOneOf,
|
|
13
10
|
coerceTuple
|
|
14
11
|
} from "./coerce.js";
|
|
15
|
-
const
|
|
12
|
+
const __desc = (opts, prefix) => `${prefix ? prefix + ": " : ""}${opts.map((x) => `"${x}"`).join(", ")}`;
|
|
13
|
+
const __hint = (hint, delim) => hint + (delim ? `[${delim}..]` : "");
|
|
14
|
+
const defSingle = (type, coerce, hint) => (spec) => ({
|
|
15
|
+
type,
|
|
16
16
|
coerce,
|
|
17
17
|
hint,
|
|
18
18
|
group: "main",
|
|
19
19
|
...spec
|
|
20
20
|
});
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
const defMulti = (type, coerce, hint, delim = ",") => (spec) => ({
|
|
22
|
+
type,
|
|
23
|
+
delim,
|
|
24
|
+
hint: __hint(hint, spec.delim ?? delim),
|
|
25
|
+
coerce: (x) => x.map(coerce),
|
|
25
26
|
group: "main",
|
|
27
|
+
multi: true,
|
|
26
28
|
...spec
|
|
27
29
|
});
|
|
28
|
-
const $hint = (hint, delim) => hint + (delim ? `[${delim}..]` : "");
|
|
29
30
|
const flag = (spec) => ({
|
|
30
|
-
|
|
31
|
-
default: false,
|
|
31
|
+
type: "flag",
|
|
32
32
|
group: "flags",
|
|
33
|
+
default: false,
|
|
33
34
|
...spec
|
|
34
35
|
});
|
|
35
|
-
const string =
|
|
36
|
-
const strings =
|
|
37
|
-
const float =
|
|
38
|
-
const
|
|
39
|
-
const int =
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
coerce: coerceJson,
|
|
45
|
-
hint: "JSON",
|
|
46
|
-
group: "main",
|
|
47
|
-
...spec
|
|
48
|
-
});
|
|
49
|
-
const $desc = (opts, prefix) => `${prefix ? prefix + ": " : ""}${opts.map((x) => `"${x}"`).join(", ")}`;
|
|
50
|
-
const oneOf = (opts, spec) => ({
|
|
51
|
-
coerce: coerceOneOf(opts),
|
|
52
|
-
hint: "ID",
|
|
53
|
-
group: "main",
|
|
36
|
+
const string = defSingle("string", identity, "STR");
|
|
37
|
+
const strings = defMulti("strings", identity, "STR");
|
|
38
|
+
const float = defSingle("float", coerceFloat, "NUM");
|
|
39
|
+
const floats = defMulti("floats", coerceFloat, "NUM");
|
|
40
|
+
const int = defSingle("int", coerceInt, "INT");
|
|
41
|
+
const ints = defMulti("ints", coerceInt, "INT");
|
|
42
|
+
const hex = defSingle("hex", coerceHexInt, "HEX");
|
|
43
|
+
const hexes = defMulti("hexes", coerceHexInt, "HEX");
|
|
44
|
+
const oneOf = (spec) => ({
|
|
54
45
|
...spec,
|
|
55
|
-
|
|
46
|
+
type: "oneOf",
|
|
47
|
+
coerce: coerceOneOf(spec.opts),
|
|
48
|
+
hint: spec.hint ?? "ID",
|
|
49
|
+
group: spec.group ?? "main",
|
|
50
|
+
desc: __desc(spec.opts, spec.desc)
|
|
56
51
|
});
|
|
57
|
-
const oneOfMulti = (
|
|
58
|
-
coerce: (values) => values.map(coerceOneOf(opts)),
|
|
59
|
-
hint: $hint("ID", spec.delim),
|
|
60
|
-
multi: true,
|
|
61
|
-
group: "main",
|
|
52
|
+
const oneOfMulti = (spec) => ({
|
|
62
53
|
...spec,
|
|
63
|
-
|
|
54
|
+
type: "oneOfMulti",
|
|
55
|
+
coerce: coerceOneOf(spec.opts),
|
|
56
|
+
hint: spec.hint ?? __hint("ID", spec.delim),
|
|
57
|
+
group: spec.group ?? "main",
|
|
58
|
+
desc: __desc(spec.opts, spec.desc),
|
|
59
|
+
multi: true
|
|
64
60
|
});
|
|
65
|
-
const kvPairs = (spec
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
61
|
+
const kvPairs = (spec) => {
|
|
62
|
+
if (!spec.delim) spec.delim = "=";
|
|
63
|
+
return {
|
|
64
|
+
type: "kvPairs",
|
|
65
|
+
coerce: coerceKV(spec.delim, spec.strict, false),
|
|
66
|
+
hint: `key${spec.delim}val`,
|
|
67
|
+
group: "main",
|
|
68
|
+
multi: true,
|
|
69
|
+
split: false,
|
|
70
|
+
...spec
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
const kvPairsMulti = (spec) => ({
|
|
74
|
+
type: "kvPairsMulti",
|
|
75
|
+
coerce: coerceKV(spec.delim, spec.strict, true),
|
|
76
|
+
hint: `key${spec.delim}val`,
|
|
69
77
|
group: "main",
|
|
70
|
-
...spec
|
|
71
|
-
});
|
|
72
|
-
const kvPairsMulti = (spec, delim = "=", strict) => ({
|
|
73
|
-
coerce: coerceKV(delim, strict, true),
|
|
74
|
-
hint: `key${delim}val(s)`,
|
|
75
78
|
multi: true,
|
|
76
|
-
group: "main",
|
|
77
79
|
...spec
|
|
78
80
|
});
|
|
79
|
-
const tuple = (
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
const tuple = (spec) => {
|
|
82
|
+
if (!spec.delim) spec.delim = ",";
|
|
83
|
+
return {
|
|
84
|
+
...spec,
|
|
85
|
+
type: "tuple",
|
|
86
|
+
coerce: coerceTuple(spec.coerce, spec.size, spec.delim),
|
|
87
|
+
hint: spec.hint ?? [...repeat("N", spec.size)].join(spec.delim),
|
|
88
|
+
group: spec.group ?? "main"
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
const size = (spec) => tuple({ ...spec, coerce: coerceInt });
|
|
92
|
+
const vec = (spec) => tuple({ ...spec, coerce: coerceFloat });
|
|
93
|
+
const json = (spec) => ({
|
|
94
|
+
type: "json",
|
|
95
|
+
coerce: coerceJson,
|
|
96
|
+
hint: "JSON",
|
|
82
97
|
group: "main",
|
|
83
98
|
...spec
|
|
84
99
|
});
|
|
85
|
-
const
|
|
86
|
-
|
|
100
|
+
const ARG_TYPES = {
|
|
101
|
+
flag,
|
|
102
|
+
float,
|
|
103
|
+
floats,
|
|
104
|
+
hex,
|
|
105
|
+
hexes,
|
|
106
|
+
int,
|
|
107
|
+
ints,
|
|
108
|
+
json,
|
|
109
|
+
kvPairs,
|
|
110
|
+
kvPairsMulti,
|
|
111
|
+
oneOf,
|
|
112
|
+
oneOfMulti,
|
|
113
|
+
string,
|
|
114
|
+
strings,
|
|
115
|
+
tuple
|
|
116
|
+
};
|
|
87
117
|
const ARG_DRY_RUN = {
|
|
88
118
|
dryRun: flag({
|
|
89
119
|
desc: "Dry run (no changes applied)"
|
|
@@ -107,7 +137,7 @@ const ARG_OUT_DIR = (defaultVal, desc) => ({
|
|
|
107
137
|
desc: "Output directory" + (desc ?? ""),
|
|
108
138
|
hint: "PATH",
|
|
109
139
|
default: defaultVal,
|
|
110
|
-
|
|
140
|
+
required: !!defaultVal
|
|
111
141
|
})
|
|
112
142
|
});
|
|
113
143
|
const ARG_OUT_FILE = (defaultVal, desc) => ({
|
|
@@ -116,7 +146,7 @@ const ARG_OUT_FILE = (defaultVal, desc) => ({
|
|
|
116
146
|
desc: "Output file" + (desc ?? ""),
|
|
117
147
|
hint: "PATH",
|
|
118
148
|
default: defaultVal,
|
|
119
|
-
|
|
149
|
+
required: !!defaultVal
|
|
120
150
|
})
|
|
121
151
|
});
|
|
122
152
|
export {
|
|
@@ -124,6 +154,7 @@ export {
|
|
|
124
154
|
ARG_OUT_DIR,
|
|
125
155
|
ARG_OUT_FILE,
|
|
126
156
|
ARG_QUIET,
|
|
157
|
+
ARG_TYPES,
|
|
127
158
|
ARG_VERBOSE,
|
|
128
159
|
flag,
|
|
129
160
|
float,
|
package/coerce.d.ts
CHANGED
|
@@ -2,11 +2,8 @@ import type { Fn } from "@thi.ng/api";
|
|
|
2
2
|
import { Tuple, type KVDict, type KVMultiDict } from "./api.js";
|
|
3
3
|
export declare const coerceString: (x: string) => string;
|
|
4
4
|
export declare const coerceFloat: (x: string) => number;
|
|
5
|
-
export declare const coerceFloats: (values: string[]) => number[];
|
|
6
5
|
export declare const coerceHexInt: (x: string) => number;
|
|
7
|
-
export declare const coerceHexInts: (values: string[]) => number[];
|
|
8
6
|
export declare const coerceInt: (x: string) => number;
|
|
9
|
-
export declare const coerceInts: (values: string[]) => number[];
|
|
10
7
|
export declare const coerceJson: <T>(x: string) => T;
|
|
11
8
|
export declare const coerceOneOf: <K extends string>(values: readonly K[]) => (x: string) => K;
|
|
12
9
|
export declare function coerceKV(delim?: string, strict?: boolean, multi?: false): Fn<string[], KVDict>;
|
package/coerce.js
CHANGED
|
@@ -4,11 +4,8 @@ import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
|
|
|
4
4
|
import { Tuple } from "./api.js";
|
|
5
5
|
const coerceString = (x) => x;
|
|
6
6
|
const coerceFloat = (x) => isNumericFloat(x) ? parseFloat(x) : illegalArgs(`not a numeric value: ${x}`);
|
|
7
|
-
const coerceFloats = (values) => values.map(coerceFloat);
|
|
8
7
|
const coerceHexInt = (x) => isHex(x) ? parseInt(x, 16) : illegalArgs(`not a hex value: ${x}`);
|
|
9
|
-
const coerceHexInts = (values) => values.map(coerceHexInt);
|
|
10
8
|
const coerceInt = (x) => isNumericInt(x) ? parseInt(x) : illegalArgs(`not an integer: ${x}`);
|
|
11
|
-
const coerceInts = (values) => values.map(coerceInt);
|
|
12
9
|
const coerceJson = (x) => JSON.parse(x);
|
|
13
10
|
const coerceOneOf = (values) => (x) => values.includes(x) ? x : illegalArgs(`invalid option: ${x}`);
|
|
14
11
|
function coerceKV(delim = "=", strict = false, multi = false) {
|
|
@@ -38,11 +35,8 @@ const coerceTuple = (coerce, size, delim = ",") => (src) => {
|
|
|
38
35
|
};
|
|
39
36
|
export {
|
|
40
37
|
coerceFloat,
|
|
41
|
-
coerceFloats,
|
|
42
38
|
coerceHexInt,
|
|
43
|
-
coerceHexInts,
|
|
44
39
|
coerceInt,
|
|
45
|
-
coerceInts,
|
|
46
40
|
coerceJson,
|
|
47
41
|
coerceKV,
|
|
48
42
|
coerceOneOf,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/args",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Declarative, functional CLI argument/options parser, app framework, arg value coercions, multi/sub-commands, usage generation, error handling etc.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -110,5 +110,5 @@
|
|
|
110
110
|
"tag": "cli",
|
|
111
111
|
"year": 2018
|
|
112
112
|
},
|
|
113
|
-
"gitHead": "
|
|
113
|
+
"gitHead": "d86306c5375d19fa95bc900e433d097226516b1e\n"
|
|
114
114
|
}
|
package/parse.js
CHANGED
|
@@ -58,25 +58,23 @@ const __aliasIndex = (specs) => Object.entries(specs).reduce(
|
|
|
58
58
|
{}
|
|
59
59
|
);
|
|
60
60
|
const __parseKey = (specs, aliases, acc, a) => {
|
|
61
|
-
if (a[0]
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
return { state: 0, id, spec };
|
|
61
|
+
if (a[0] !== "-") return { state: 2 };
|
|
62
|
+
let id;
|
|
63
|
+
if (a[1] === "-") {
|
|
64
|
+
if (a.length === 2) return { state: 1 };
|
|
65
|
+
id = camel(a.substring(2));
|
|
66
|
+
} else {
|
|
67
|
+
id = aliases[a.substring(1)];
|
|
68
|
+
!id && illegalArgs(`unknown option: ${a}`);
|
|
69
|
+
}
|
|
70
|
+
const spec = specs[id];
|
|
71
|
+
!spec && illegalArgs(id);
|
|
72
|
+
if (spec.type === "flag") {
|
|
73
|
+
acc[id] = true;
|
|
74
|
+
id = void 0;
|
|
75
|
+
if (spec.fn && !spec.fn("true")) return { state: 1, spec };
|
|
78
76
|
}
|
|
79
|
-
return { state:
|
|
77
|
+
return { state: 0, id, spec };
|
|
80
78
|
};
|
|
81
79
|
const __parseValue = (spec, acc, id, a) => {
|
|
82
80
|
if (spec.multi) {
|
|
@@ -93,7 +91,7 @@ const __processResults = (specs, acc) => {
|
|
|
93
91
|
if (acc[id] === void 0) {
|
|
94
92
|
if (spec.default !== void 0) {
|
|
95
93
|
acc[id] = spec.default;
|
|
96
|
-
} else if (spec.
|
|
94
|
+
} else if (spec.required) {
|
|
97
95
|
illegalArgs(`missing arg: --${kebab(id)}`);
|
|
98
96
|
}
|
|
99
97
|
} else if (spec.coerce) {
|
|
@@ -104,7 +102,7 @@ const __processResults = (specs, acc) => {
|
|
|
104
102
|
};
|
|
105
103
|
const __coerceValue = (spec, acc, id) => {
|
|
106
104
|
try {
|
|
107
|
-
if (spec.multi && spec.delim) {
|
|
105
|
+
if (spec.multi && spec.delim && spec.split !== false) {
|
|
108
106
|
acc[id] = acc[id].reduce(
|
|
109
107
|
(acc2, x) => (acc2.push(...x.split(spec.delim)), acc2),
|
|
110
108
|
[]
|
package/usage.js
CHANGED
|
@@ -48,7 +48,7 @@ const __argUsage = (id, spec, opts, theme, indent) => {
|
|
|
48
48
|
const alias = __argAlias(spec, theme, hint);
|
|
49
49
|
const name = __ansi(`--${kebab(id)}`, theme.param);
|
|
50
50
|
const params = `${alias}${name}${hint}`;
|
|
51
|
-
const isRequired = spec.
|
|
51
|
+
const isRequired = !!spec.required && spec.default === void 0;
|
|
52
52
|
const prefixes = [];
|
|
53
53
|
isRequired && prefixes.push("required");
|
|
54
54
|
spec.multi && prefixes.push("multiple");
|