argue-cli 2.0.0 → 3.0.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/README.md +85 -64
- package/dist/args.d.ts +1 -1
- package/dist/args.d.ts.map +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.d.ts.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +152 -181
- package/dist/index.js.map +1 -1
- package/dist/options.d.ts +2 -2
- package/dist/options.d.ts.map +1 -1
- package/dist/types.d.ts +9 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +6 -6
- package/dist/utils.d.ts.map +1 -1
- package/package.json +12 -32
- package/dist/index.cjs +0 -223
- package/dist/index.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# argue-cli
|
|
2
2
|
|
|
3
|
+
[![ESM-only package][package]][package-url]
|
|
3
4
|
[![NPM version][npm]][npm-url]
|
|
4
5
|
[![Node version][node]][node-url]
|
|
5
6
|
[![Dependencies status][deps]][deps-url]
|
|
7
|
+
[![Install size][size]][size-url]
|
|
6
8
|
[![Build status][build]][build-url]
|
|
7
9
|
[![Coverage status][coverage]][coverage-url]
|
|
8
|
-
|
|
10
|
+
|
|
11
|
+
[package]: https://img.shields.io/badge/package-ESM--only-ffe536.svg
|
|
12
|
+
[package-url]: https://nodejs.org/api/esm.html
|
|
9
13
|
|
|
10
14
|
[npm]: https://img.shields.io/npm/v/argue-cli.svg
|
|
11
15
|
[npm-url]: https://www.npmjs.com/package/argue-cli
|
|
@@ -14,28 +18,28 @@
|
|
|
14
18
|
[node-url]: https://nodejs.org
|
|
15
19
|
|
|
16
20
|
[deps]: https://img.shields.io/librariesio/release/npm/argue-cli
|
|
17
|
-
[deps-url]: https://libraries.io/npm/argue-cli
|
|
21
|
+
[deps-url]: https://libraries.io/npm/argue-cli
|
|
18
22
|
|
|
19
|
-
[
|
|
20
|
-
[
|
|
23
|
+
[size]: https://packagephobia.com/badge?p=argue-cli
|
|
24
|
+
[size-url]: https://packagephobia.com/result?p=argue-cli
|
|
21
25
|
|
|
22
|
-
[
|
|
23
|
-
[
|
|
26
|
+
[build]: https://img.shields.io/github/actions/workflow/status/TrigenSoftware/Argue/tests.yml?branch=master
|
|
27
|
+
[build-url]: https://github.com/TrigenSoftware/Argue/actions
|
|
24
28
|
|
|
25
|
-
[
|
|
26
|
-
[
|
|
29
|
+
[coverage]: https://img.shields.io/codecov/c/github/TrigenSoftware/Argue.svg
|
|
30
|
+
[coverage-url]: https://app.codecov.io/gh/TrigenSoftware/Argue
|
|
27
31
|
|
|
28
|
-
A thin and strongly typed CLI
|
|
32
|
+
A thin and strongly typed CLI arguments parser for Node.js.
|
|
29
33
|
|
|
30
34
|
## Usage
|
|
31
35
|
|
|
32
36
|
1. Install
|
|
33
37
|
|
|
34
38
|
```bash
|
|
35
|
-
# yarn
|
|
36
|
-
yarn add argue-cli
|
|
37
39
|
# pnpm
|
|
38
40
|
pnpm add argue-cli
|
|
41
|
+
# yarn
|
|
42
|
+
yarn add argue-cli
|
|
39
43
|
# npm
|
|
40
44
|
npm i argue-cli
|
|
41
45
|
```
|
|
@@ -80,89 +84,106 @@ end()
|
|
|
80
84
|
|
|
81
85
|
## API
|
|
82
86
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
</thead>
|
|
90
|
-
<tbody>
|
|
91
|
-
<tr>
|
|
92
|
-
<td>
|
|
87
|
+
Argue reads arguments sequentially from an internal state, which is initialized with `process.argv`. Every call consumes the arguments it reads, so you describe your CLI step by step: expect a command, read its options, read positional arguments, and finally assert the end.
|
|
88
|
+
|
|
89
|
+
> [!TIP]
|
|
90
|
+
> The internal state can be controlled manually with `setArgs(...args)` and `resetArgs()` — handy in tests.
|
|
91
|
+
|
|
92
|
+
### read
|
|
93
93
|
|
|
94
94
|
```ts
|
|
95
95
|
function read(): string
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
98
|
+
Reads the next argument and returns it. Throws an error if there are no arguments left.
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
// my-cli sort-imports
|
|
102
|
+
const fileName = read() // 'sort-imports'
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### end
|
|
105
106
|
|
|
106
107
|
```ts
|
|
107
108
|
function end(): void
|
|
108
109
|
```
|
|
109
110
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
111
|
+
Asserts that all arguments were consumed. Throws an error if there are any arguments left — useful to catch typos and unexpected input.
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
// my-cli install --sav
|
|
115
|
+
expect('install')
|
|
116
|
+
readOptions(
|
|
117
|
+
option(alias('save', 'S'), Boolean)
|
|
118
|
+
)
|
|
119
|
+
end() // throws: Unexpected argument "--sav"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### expect
|
|
117
123
|
|
|
118
124
|
```ts
|
|
119
125
|
function expect(...argRefs: ArgRef[]): string
|
|
120
126
|
```
|
|
121
127
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
128
|
+
Expects the next argument to be one of the given ones and returns the matched name. If an [alias](#alias) matches, the main name is returned. Throws an error on any other input.
|
|
129
|
+
|
|
130
|
+
The return type is inferred as a union of the given names:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
// my-cli i
|
|
134
|
+
const command = expect(alias('install', 'i'), 'remove')
|
|
135
|
+
// typeof command: 'install' | 'remove'
|
|
136
|
+
// command === 'install'
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### alias
|
|
129
140
|
|
|
130
141
|
```ts
|
|
131
142
|
function alias(name: string, ...aliases: string[]): AliasArgRef
|
|
132
143
|
```
|
|
133
144
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
145
|
+
Describes an argument that has alternative names. Use it anywhere an argument name is expected — in [`expect`](#expect) and [`option`](#option).
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
alias('install', 'i')
|
|
149
|
+
alias('saveDev', 'save-dev', 'D')
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### option
|
|
141
153
|
|
|
142
154
|
```ts
|
|
143
155
|
function option(argRef: ArgRef, type: PrimitiveConstructor): OptionReader
|
|
144
156
|
```
|
|
145
157
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
158
|
+
Describes an option with a value of the given type, to be read by [`readOptions`](#readoptions):
|
|
159
|
+
|
|
160
|
+
- `String` — takes the next argument as a value: `--workspace packages/app`
|
|
161
|
+
- `Number` — parses the next argument as a number: `--port 8080`
|
|
162
|
+
- `Boolean` — a flag without a value, `true` when present: `--verbose`
|
|
163
|
+
- `Array` — splits the next argument by commas; repeated options are merged: `--plugins eslint,swc --plugins tsc` → `['eslint', 'swc', 'tsc']`
|
|
164
|
+
|
|
165
|
+
### readOptions
|
|
153
166
|
|
|
154
167
|
```ts
|
|
155
168
|
function readOptions(...optionReaders: OptionReader[]): OptionResult
|
|
156
169
|
```
|
|
157
170
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
171
|
+
Scans the arguments and reads all described options. Both `--option` and `-o` prefixes are accepted. Arguments that don't match any described option are left untouched, so you can continue reading them afterwards.
|
|
172
|
+
|
|
173
|
+
The result is a strongly typed object, where every property is optional — an option simply may not be passed:
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
// my-cli --save-dev --workspace packages/app my-package
|
|
177
|
+
const options = readOptions(
|
|
178
|
+
option(alias('saveDev', 'save-dev', 'D'), Boolean),
|
|
179
|
+
option('workspace', String)
|
|
180
|
+
)
|
|
181
|
+
// typeof options: { saveDev?: boolean, workspace?: string }
|
|
182
|
+
// options: { saveDev: true, workspace: 'packages/app' }
|
|
183
|
+
|
|
184
|
+
const packageName = read() // 'my-package'
|
|
185
|
+
```
|
|
165
186
|
|
|
166
187
|
## TypeScript
|
|
167
188
|
|
|
168
|
-
In [API section](#
|
|
189
|
+
In the [API section](#api) types are described in a simplified way. A detailed example of the inferred types you can see in [type tests](src/types.spec.ts).
|
package/dist/args.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AliasArgRef, ArgRef, PrimitiveConstructor, OptionsReaderState, OptionsReaderRead, OptionResult } from './types';
|
|
1
|
+
import type { AliasArgRef, ArgRef, PrimitiveConstructor, OptionsReaderState, OptionsReaderRead, OptionResult } from './types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Describe argument with aliases.
|
|
4
4
|
* @param name - Main name.
|
package/dist/args.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,MAAM,EACN,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACb,MAAM,YAAY,CAAA;AAGnB;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,CAKxG;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,oBAAoB,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,YA8B/E,MAAM,QAAQ,iBAAiB,WAAW,kBAAkB,+BA6B/E"}
|
package/dist/core.d.ts
CHANGED
package/dist/core.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAIxC;;;;GAIG;AACH,wBAAgB,IAAI,WAQnB;AAED;;;GAGG;AACH,wBAAgB,GAAG,SAIlB;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KASpE"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export * from './types';
|
|
2
|
-
export * from './argv';
|
|
3
|
-
export * from './core';
|
|
4
|
-
export * from './args';
|
|
5
|
-
export * from './options';
|
|
1
|
+
export type * from './types.js';
|
|
2
|
+
export * from './argv.js';
|
|
3
|
+
export * from './core.js';
|
|
4
|
+
export * from './args.js';
|
|
5
|
+
export * from './options.js';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,YAAY,CAAA;AAC/B,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,210 +1,181 @@
|
|
|
1
|
+
//#region src/argv.ts
|
|
1
2
|
const ARGV_START_INDEX = 2;
|
|
2
3
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
* Internal state of arguments.
|
|
5
|
+
*/
|
|
6
|
+
const argv = process.argv.slice(ARGV_START_INDEX);
|
|
5
7
|
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
* Reset arguments state.
|
|
9
|
+
*/
|
|
10
|
+
function resetArgs() {
|
|
11
|
+
argv.splice(0, argv.length);
|
|
12
|
+
argv.push(...process.argv.slice(ARGV_START_INDEX));
|
|
10
13
|
}
|
|
11
14
|
/**
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
* Set arguments state.
|
|
16
|
+
* @param args
|
|
17
|
+
*/
|
|
18
|
+
function setArgs(...args) {
|
|
19
|
+
argv.splice(0, argv.length);
|
|
20
|
+
argv.push(...args);
|
|
17
21
|
}
|
|
18
|
-
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/utils.ts
|
|
19
24
|
/**
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return argRef.name;
|
|
30
|
-
}
|
|
31
|
-
return argRef.aliases.includes(arg) ? argRef.name : null;
|
|
25
|
+
* Match reference with argument.
|
|
26
|
+
* @param argRef
|
|
27
|
+
* @param arg
|
|
28
|
+
* @returns Full name or null.
|
|
29
|
+
*/
|
|
30
|
+
function matchArgName(argRef, arg) {
|
|
31
|
+
if (typeof argRef === "string") return argRef === arg ? argRef : null;
|
|
32
|
+
if (argRef.name === arg) return argRef.name;
|
|
33
|
+
return argRef.aliases.includes(arg) ? argRef.name : null;
|
|
32
34
|
}
|
|
33
35
|
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return null;
|
|
36
|
+
* Find full argument name in references.
|
|
37
|
+
* @param argRefs
|
|
38
|
+
* @param arg
|
|
39
|
+
* @returns Found argument's full name or null.
|
|
40
|
+
*/
|
|
41
|
+
function findArgName(argRefs, arg) {
|
|
42
|
+
let argRef;
|
|
43
|
+
let argName;
|
|
44
|
+
for (argRef of argRefs) {
|
|
45
|
+
argName = matchArgName(argRef, arg);
|
|
46
|
+
if (argName) return argName;
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
48
49
|
}
|
|
49
|
-
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region src/core.ts
|
|
50
52
|
/**
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return value;
|
|
53
|
+
* Read next argument.
|
|
54
|
+
* Throws error if no next argument.
|
|
55
|
+
* @returns Next argument.
|
|
56
|
+
*/
|
|
57
|
+
function read() {
|
|
58
|
+
const value = argv.shift();
|
|
59
|
+
if (!value) throw new Error("Unexpected end of arguments");
|
|
60
|
+
return value;
|
|
60
61
|
}
|
|
61
62
|
/**
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
63
|
+
* Expectation of the end.
|
|
64
|
+
* Throws an error if there are more arguments left.
|
|
65
|
+
*/
|
|
66
|
+
function end() {
|
|
67
|
+
if (argv.length) throw new Error(`Unexpected argument "${argv[0]}"`);
|
|
68
68
|
}
|
|
69
69
|
/**
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return argName;
|
|
70
|
+
* Expect one of the given arguments.
|
|
71
|
+
* @param argRefs
|
|
72
|
+
* @returns Expected full argument name.
|
|
73
|
+
*/
|
|
74
|
+
function expect(...argRefs) {
|
|
75
|
+
const arg = read();
|
|
76
|
+
const argName = findArgName(argRefs, arg);
|
|
77
|
+
if (!argName) throw new Error(`Unexpected argument "${arg}"`);
|
|
78
|
+
return argName;
|
|
80
79
|
}
|
|
81
|
-
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region src/args.ts
|
|
82
82
|
/**
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
]
|
|
95
|
-
};
|
|
83
|
+
* Describe argument with aliases.
|
|
84
|
+
* @param name - Main name.
|
|
85
|
+
* @param alias - Alias name.
|
|
86
|
+
* @param restAliases - Rest aliases.
|
|
87
|
+
* @returns Description of argument with aliases..
|
|
88
|
+
*/
|
|
89
|
+
function alias(name, alias, ...restAliases) {
|
|
90
|
+
return {
|
|
91
|
+
name,
|
|
92
|
+
aliases: [alias, ...restAliases]
|
|
93
|
+
};
|
|
96
94
|
}
|
|
97
95
|
/**
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (argName) {
|
|
129
|
-
const prevValues = options[argName];
|
|
130
|
-
const values = read().split(',');
|
|
131
|
-
return {
|
|
132
|
-
[argName]: Array.isArray(prevValues) ? prevValues.concat(values) : values
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
return null;
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
return (option4)=>{
|
|
139
|
-
const argName = matchArgName(argRef, option4);
|
|
140
|
-
if (argName) {
|
|
141
|
-
return {
|
|
142
|
-
[argName]: true
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
return null;
|
|
146
|
-
};
|
|
96
|
+
* Describe option with value.
|
|
97
|
+
* @param argRef - Option name.
|
|
98
|
+
* @param type - Value type.
|
|
99
|
+
* @returns Option reader.
|
|
100
|
+
*/
|
|
101
|
+
function option(argRef, type) {
|
|
102
|
+
if (type === String) return (option, read) => {
|
|
103
|
+
const argName = matchArgName(argRef, option);
|
|
104
|
+
if (argName) return { [argName]: read() };
|
|
105
|
+
return null;
|
|
106
|
+
};
|
|
107
|
+
if (type === Number) return (option, read) => {
|
|
108
|
+
const argName = matchArgName(argRef, option);
|
|
109
|
+
if (argName) return { [argName]: parseFloat(read()) };
|
|
110
|
+
return null;
|
|
111
|
+
};
|
|
112
|
+
if (type === Array) return (option, read, options) => {
|
|
113
|
+
const argName = matchArgName(argRef, option);
|
|
114
|
+
if (argName) {
|
|
115
|
+
const prevValues = options[argName];
|
|
116
|
+
const values = read().split(",");
|
|
117
|
+
return { [argName]: Array.isArray(prevValues) ? prevValues.concat(values) : values };
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
};
|
|
121
|
+
return (option) => {
|
|
122
|
+
const argName = matchArgName(argRef, option);
|
|
123
|
+
if (argName) return { [argName]: true };
|
|
124
|
+
return null;
|
|
125
|
+
};
|
|
147
126
|
}
|
|
148
|
-
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/options.ts
|
|
149
129
|
function isOption(arg) {
|
|
150
|
-
|
|
130
|
+
return /^--?[^-].*/.test(arg);
|
|
151
131
|
}
|
|
152
132
|
function removePrefix(arg) {
|
|
153
|
-
|
|
133
|
+
return arg.replace(/^--?/, "");
|
|
154
134
|
}
|
|
155
135
|
function createOptionReader(optionReaders) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
return (option, read, options)=>readOption(option, read, options) ?? readNextOption(option, read, options)
|
|
161
|
-
;
|
|
162
|
-
}, null);
|
|
163
|
-
return optionReader;
|
|
136
|
+
return optionReaders.reduceRight((readNextOption, readOption) => {
|
|
137
|
+
if (!readNextOption) return readOption;
|
|
138
|
+
return (option, read, options) => readOption(option, read, options) ?? readNextOption(option, read, options);
|
|
139
|
+
}, null);
|
|
164
140
|
}
|
|
165
141
|
/**
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
Object.assign(options, optionResult);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
next();
|
|
205
|
-
}
|
|
206
|
-
return options;
|
|
142
|
+
* Read options from arguments.
|
|
143
|
+
* @param optionReaders
|
|
144
|
+
* @returns Options with values.
|
|
145
|
+
*/
|
|
146
|
+
function readOptions(...optionReaders) {
|
|
147
|
+
if (!argv.length) return {};
|
|
148
|
+
const readOption = createOptionReader(optionReaders);
|
|
149
|
+
if (!readOption) return {};
|
|
150
|
+
const options = {};
|
|
151
|
+
let i = 0;
|
|
152
|
+
let arg = argv[i];
|
|
153
|
+
let optionResult;
|
|
154
|
+
const next = () => {
|
|
155
|
+
arg = argv[++i];
|
|
156
|
+
};
|
|
157
|
+
const remove = () => {
|
|
158
|
+
argv.splice(i--, 1);
|
|
159
|
+
};
|
|
160
|
+
const read = () => {
|
|
161
|
+
next();
|
|
162
|
+
remove();
|
|
163
|
+
if (!arg) throw new Error("Unexpected end of arguments");
|
|
164
|
+
return arg;
|
|
165
|
+
};
|
|
166
|
+
while (arg) {
|
|
167
|
+
if (isOption(arg)) {
|
|
168
|
+
optionResult = readOption(removePrefix(arg), read, options);
|
|
169
|
+
if (optionResult) {
|
|
170
|
+
remove();
|
|
171
|
+
Object.assign(options, optionResult);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
next();
|
|
175
|
+
}
|
|
176
|
+
return options;
|
|
207
177
|
}
|
|
208
|
-
|
|
178
|
+
//#endregion
|
|
209
179
|
export { alias, argv, end, expect, option, read, readOptions, resetArgs, setArgs };
|
|
210
|
-
|
|
180
|
+
|
|
181
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/argv.ts","../src/utils.ts","../src/core.ts","../src/args.ts","../src/options.ts"],"sourcesContent":["\nconst ARGV_START_INDEX = 2\n\n/**\n * Internal state of arguments.\n */\nexport const argv = process.argv.slice(ARGV_START_INDEX)\n\n/**\n * Reset arguments state.\n */\nexport function resetArgs() {\n argv.splice(0, argv.length)\n argv.push(...process.argv.slice(ARGV_START_INDEX))\n}\n\n/**\n * Set arguments state.\n * @param args\n */\nexport function setArgs(...args: string[]) {\n argv.splice(0, argv.length)\n argv.push(...args)\n}\n","\nimport { ArgRef } from './types'\n\ntype FlatMerge<T> = T extends infer U ? { [K in keyof U]: U[K] } : never\n\nexport type Merge<T extends readonly [...unknown[]]> = T extends [infer L, ...infer R]\n ? FlatMerge<NonNullable<L> & Merge<R>>\n : unknown\n\nexport type UnionMerge<T extends readonly [...unknown[]]> = T extends [infer L, ...infer R]\n ? L | Merge<R>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n : any\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyFunction = (...args: any[]) => any\n\nexport type ReturnTypes<T extends readonly [...AnyFunction[]]> = T extends [infer L, ...infer R]\n ? L extends AnyFunction\n ? R extends AnyFunction[]\n ? [ReturnType<L>, ...ReturnTypes<R>]\n : []\n : []\n : []\n\n/**\n * Match reference with argument.\n * @param argRef\n * @param arg\n * @returns Full name or null.\n */\nexport function matchArgName<T extends string>(argRef: ArgRef<T>, arg: string) {\n if (typeof argRef === 'string') {\n return argRef === arg\n ? argRef\n : null\n }\n\n if (argRef.name === arg) {\n return argRef.name\n }\n\n return argRef.aliases.includes(arg)\n ? argRef.name\n : null\n}\n\n/**\n * Find full argument name in references.\n * @param argRefs\n * @param arg\n * @returns Found argument's full name or null.\n */\nexport function findArgName<T extends string>(argRefs: [...ArgRef<T>[]], arg: string) {\n let argRef: ArgRef<T>\n let argName: T | null\n\n for (argRef of argRefs) {\n argName = matchArgName(argRef, arg)\n\n if (argName) {\n return argName\n }\n }\n\n return null\n}\n","import { argv } from './argv'\nimport { ArgRef } from './types'\nimport { findArgName } from './utils'\n\n/**\n * Read next argument.\n * Throws error if no next argument.\n * @returns Next argument.\n */\nexport function read() {\n const value = argv.shift()\n\n if (!value) {\n throw new Error('Unexpected end of arguments')\n }\n\n return value\n}\n\n/**\n * Expectation of the end.\n * Throws an error if there are more arguments left.\n */\nexport function end() {\n if (argv.length) {\n throw new Error(`Unexpected argument \"${argv[0]}\"`)\n }\n}\n\n/**\n * Expect one of the given arguments.\n * @param argRefs\n * @returns Expected full argument name.\n */\nexport function expect<T extends string>(...argRefs: [...ArgRef<T>[]]) {\n const arg = read()\n const argName = findArgName(argRefs, arg)\n\n if (!argName) {\n throw new Error(`Unexpected argument \"${arg}\"`)\n }\n\n return argName\n}\n","import {\n AliasArgRef,\n ArgRef,\n PrimitiveConstructor,\n OptionsReaderState,\n OptionsReaderRead,\n OptionResult\n} from './types'\nimport { matchArgName } from './utils'\n\n/**\n * Describe argument with aliases.\n * @param name - Main name.\n * @param alias - Alias name.\n * @param restAliases - Rest aliases.\n * @returns Description of argument with aliases..\n */\nexport function alias<T extends string>(name: T, alias: string, ...restAliases: string[]): AliasArgRef<T> {\n return {\n name,\n aliases: [alias, ...restAliases]\n }\n}\n\n/**\n * Describe option with value.\n * @param argRef - Option name.\n * @param type - Value type.\n * @returns Option reader.\n */\nexport function option<T extends string, K extends PrimitiveConstructor>(argRef: ArgRef<T>, type: K) {\n if (type === String) {\n return (option: string, read: OptionsReaderRead) => {\n const argName = matchArgName(argRef, option)\n\n if (argName) {\n return {\n [argName]: read()\n } as OptionResult<T, K>\n }\n\n return null\n }\n }\n\n if (type === Number) {\n return (option: string, read: OptionsReaderRead) => {\n const argName = matchArgName(argRef, option)\n\n if (argName) {\n return {\n [argName]: parseFloat(read())\n } as OptionResult<T, K>\n }\n\n return null\n }\n }\n\n if (type === Array) {\n return (option: string, read: OptionsReaderRead, options: OptionsReaderState) => {\n const argName = matchArgName(argRef, option)\n\n if (argName) {\n const prevValues = options[argName]\n const values = read().split(',')\n\n return {\n [argName]: Array.isArray(prevValues)\n ? prevValues.concat(values)\n : values\n } as OptionResult<T, K>\n }\n\n return null\n }\n }\n\n return (option: string) => {\n const argName = matchArgName(argRef, option)\n\n if (argName) {\n return {\n [argName]: true\n } as OptionResult<T, K>\n }\n\n return null\n }\n}\n","import { argv } from './argv'\nimport { OptionReader, OptionResult } from './types'\nimport { Merge, ReturnTypes, UnionMerge } from './utils'\n\nfunction isOption(arg: string) {\n return /^--?[^-].*/.test(arg)\n}\n\nfunction removePrefix(arg: string) {\n return arg.replace(/^--?/, '')\n}\n\nfunction createOptionReader<T extends OptionReader[]>(optionReaders: [...T]) {\n const optionReader = optionReaders.reduceRight<OptionReader | null>(\n (readNextOption, readOption) => {\n if (!readNextOption) {\n return readOption\n }\n\n return (option, read, options) => readOption(option, read, options) ?? readNextOption(option, read, options)\n },\n null\n )\n\n return optionReader as OptionReader<UnionMerge<ReturnTypes<T>>> | null\n}\n\n/**\n * Read options from arguments.\n * @param optionReaders\n * @returns Options with values.\n */\nexport function readOptions<T extends OptionReader[]>(...optionReaders: [...T]): Partial<Merge<ReturnTypes<T>>> {\n if (!argv.length) {\n return {}\n }\n\n const readOption = createOptionReader(optionReaders)\n\n if (!readOption) {\n return {}\n }\n\n const options = {}\n let i = 0\n let arg = argv[i]\n let optionResult: OptionResult | null\n const next = () => {\n arg = argv[++i]\n }\n const remove = () => {\n argv.splice(i--, 1)\n }\n const read = () => {\n next()\n remove()\n\n if (!arg) {\n throw new Error('Unexpected end of arguments')\n }\n\n return arg\n }\n\n // eslint-disable-next-line no-unmodified-loop-condition\n while (arg) {\n if (isOption(arg)) {\n optionResult = readOption(removePrefix(arg), read, options)\n\n if (optionResult) {\n remove()\n Object.assign(options, optionResult)\n }\n }\n\n next()\n }\n\n return options\n}\n"],"names":["ARGV_START_INDEX","argv","process","slice","resetArgs","splice","length","push","setArgs","args","matchArgName","argRef","arg","name","aliases","includes","findArgName","argRefs","argName","read","value","shift","Error","end","expect","alias","restAliases","option","type","String","Number","parseFloat","Array","options","prevValues","values","split","isArray","concat","isOption","test","removePrefix","replace","createOptionReader","optionReaders","optionReader","reduceRight","readNextOption","readOption","readOptions","i","optionResult","next","remove","Object","assign"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/argv.ts","../src/utils.ts","../src/core.ts","../src/args.ts","../src/options.ts"],"sourcesContent":["\nconst ARGV_START_INDEX = 2\n\n/**\n * Internal state of arguments.\n */\nexport const argv = process.argv.slice(ARGV_START_INDEX)\n\n/**\n * Reset arguments state.\n */\nexport function resetArgs() {\n argv.splice(0, argv.length)\n argv.push(...process.argv.slice(ARGV_START_INDEX))\n}\n\n/**\n * Set arguments state.\n * @param args\n */\nexport function setArgs(...args: string[]) {\n argv.splice(0, argv.length)\n argv.push(...args)\n}\n","\nimport type { ArgRef } from './types.js'\n\ntype FlatMerge<T> = T extends infer U ? { [K in keyof U]: U[K] } : never\n\nexport type Merge<T extends readonly [...unknown[]]> = T extends [infer L, ...infer R]\n ? FlatMerge<NonNullable<L> & Merge<R>>\n : unknown\n\nexport type UnionMerge<T extends readonly [...unknown[]]> = T extends [infer L, ...infer R]\n ? L | Merge<R>\n // oxlint-disable-next-line typescript/no-explicit-any\n : any\n\n// oxlint-disable-next-line typescript/no-explicit-any\ntype AnyFunction = (...args: any[]) => any\n\nexport type ReturnTypes<T extends readonly [...AnyFunction[]]> = T extends [infer L, ...infer R]\n ? L extends AnyFunction\n ? R extends AnyFunction[]\n ? [ReturnType<L>, ...ReturnTypes<R>]\n : []\n : []\n : []\n\n/**\n * Match reference with argument.\n * @param argRef\n * @param arg\n * @returns Full name or null.\n */\nexport function matchArgName<T extends string>(argRef: ArgRef<T>, arg: string) {\n if (typeof argRef === 'string') {\n return argRef === arg\n ? argRef\n : null\n }\n\n if (argRef.name === arg) {\n return argRef.name\n }\n\n return argRef.aliases.includes(arg)\n ? argRef.name\n : null\n}\n\n/**\n * Find full argument name in references.\n * @param argRefs\n * @param arg\n * @returns Found argument's full name or null.\n */\nexport function findArgName<T extends string>(argRefs: [...ArgRef<T>[]], arg: string) {\n let argRef: ArgRef<T>\n let argName: T | null\n\n for (argRef of argRefs) {\n argName = matchArgName(argRef, arg)\n\n if (argName) {\n return argName\n }\n }\n\n return null\n}\n","import type { ArgRef } from './types.js'\nimport { argv } from './argv.js'\nimport { findArgName } from './utils.js'\n\n/**\n * Read next argument.\n * Throws error if no next argument.\n * @returns Next argument.\n */\nexport function read() {\n const value = argv.shift()\n\n if (!value) {\n throw new Error('Unexpected end of arguments')\n }\n\n return value\n}\n\n/**\n * Expectation of the end.\n * Throws an error if there are more arguments left.\n */\nexport function end() {\n if (argv.length) {\n throw new Error(`Unexpected argument \"${argv[0]}\"`)\n }\n}\n\n/**\n * Expect one of the given arguments.\n * @param argRefs\n * @returns Expected full argument name.\n */\nexport function expect<T extends string>(...argRefs: [...ArgRef<T>[]]) {\n const arg = read()\n const argName = findArgName(argRefs, arg)\n\n if (!argName) {\n throw new Error(`Unexpected argument \"${arg}\"`)\n }\n\n return argName\n}\n","import type {\n AliasArgRef,\n ArgRef,\n PrimitiveConstructor,\n OptionsReaderState,\n OptionsReaderRead,\n OptionResult\n} from './types.js'\nimport { matchArgName } from './utils.js'\n\n/**\n * Describe argument with aliases.\n * @param name - Main name.\n * @param alias - Alias name.\n * @param restAliases - Rest aliases.\n * @returns Description of argument with aliases..\n */\nexport function alias<T extends string>(name: T, alias: string, ...restAliases: string[]): AliasArgRef<T> {\n return {\n name,\n aliases: [alias, ...restAliases]\n }\n}\n\n/**\n * Describe option with value.\n * @param argRef - Option name.\n * @param type - Value type.\n * @returns Option reader.\n */\nexport function option<T extends string, K extends PrimitiveConstructor>(argRef: ArgRef<T>, type: K) {\n if (type === String) {\n return (option: string, read: OptionsReaderRead) => {\n const argName = matchArgName(argRef, option)\n\n if (argName) {\n return {\n [argName]: read()\n } as OptionResult<T, K>\n }\n\n return null\n }\n }\n\n if (type === Number) {\n return (option: string, read: OptionsReaderRead) => {\n const argName = matchArgName(argRef, option)\n\n if (argName) {\n return {\n [argName]: parseFloat(read())\n } as OptionResult<T, K>\n }\n\n return null\n }\n }\n\n if (type === Array) {\n return (option: string, read: OptionsReaderRead, options: OptionsReaderState) => {\n const argName = matchArgName(argRef, option)\n\n if (argName) {\n const prevValues = options[argName]\n const values = read().split(',')\n\n return {\n [argName]: Array.isArray(prevValues)\n ? prevValues.concat(values)\n : values\n } as OptionResult<T, K>\n }\n\n return null\n }\n }\n\n return (option: string) => {\n const argName = matchArgName(argRef, option)\n\n if (argName) {\n return {\n [argName]: true\n } as OptionResult<T, K>\n }\n\n return null\n }\n}\n","import type {\n OptionReader,\n OptionResult\n} from './types.js'\nimport type {\n Merge,\n ReturnTypes,\n UnionMerge\n} from './utils.js'\nimport { argv } from './argv.js'\n\nfunction isOption(arg: string) {\n return /^--?[^-].*/.test(arg)\n}\n\nfunction removePrefix(arg: string) {\n return arg.replace(/^--?/, '')\n}\n\nfunction createOptionReader<T extends OptionReader[]>(optionReaders: [...T]) {\n const optionReader = optionReaders.reduceRight<OptionReader | null>(\n (readNextOption, readOption) => {\n if (!readNextOption) {\n return readOption\n }\n\n return (option, read, options) => readOption(option, read, options) ?? readNextOption(option, read, options)\n },\n null\n )\n\n return optionReader as OptionReader<UnionMerge<ReturnTypes<T>>> | null\n}\n\n/**\n * Read options from arguments.\n * @param optionReaders\n * @returns Options with values.\n */\nexport function readOptions<T extends OptionReader[]>(...optionReaders: [...T]): Partial<Merge<ReturnTypes<T>>> {\n if (!argv.length) {\n return {}\n }\n\n const readOption = createOptionReader(optionReaders)\n\n if (!readOption) {\n return {}\n }\n\n const options = {}\n let i = 0\n let arg = argv[i]\n let optionResult: OptionResult | null\n const next = () => {\n arg = argv[++i]\n }\n const remove = () => {\n argv.splice(i--, 1)\n }\n const read = () => {\n next()\n remove()\n\n if (!arg) {\n throw new Error('Unexpected end of arguments')\n }\n\n return arg\n }\n\n // oxlint-disable-next-line eslint/no-unmodified-loop-condition\n while (arg) {\n if (isOption(arg)) {\n optionResult = readOption(removePrefix(arg), read, options)\n\n if (optionResult) {\n remove()\n Object.assign(options, optionResult)\n }\n }\n\n next()\n }\n\n return options\n}\n"],"mappings":"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"}
|
package/dist/options.d.ts
CHANGED
package/dist/options.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EACV,KAAK,EACL,WAAW,EAEZ,MAAM,YAAY,CAAA;AA0BnB;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,YAAY,EAAE,EAAE,GAAG,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CA+C9G"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type SimpleArgRef<T extends string> = T;
|
|
2
2
|
export interface AliasArgRef<T extends string> {
|
|
3
3
|
name: T;
|
|
4
4
|
aliases: string[];
|
|
5
5
|
}
|
|
6
|
-
export
|
|
7
|
-
export
|
|
8
|
-
export
|
|
9
|
-
export
|
|
10
|
-
export
|
|
11
|
-
export
|
|
12
|
-
export
|
|
13
|
-
export
|
|
6
|
+
export type ArgRef<T extends string> = SimpleArgRef<T> | AliasArgRef<T>;
|
|
7
|
+
export type ArgRefName<T extends ArgRef<string>> = T extends AliasArgRef<string> ? T['name'] : T;
|
|
8
|
+
export type OptionsReaderState = Record<string, unknown>;
|
|
9
|
+
export type OptionsReaderRead = () => string;
|
|
10
|
+
export type PrimitiveConstructor = StringConstructor | NumberConstructor | ArrayConstructor | BooleanConstructor;
|
|
11
|
+
export type OptionValueType<T extends PrimitiveConstructor> = T extends StringConstructor ? string : T extends NumberConstructor ? number : T extends ArrayConstructor ? string[] : boolean;
|
|
12
|
+
export type OptionResult<T extends string = string, K extends PrimitiveConstructor = PrimitiveConstructor> = Record<T, OptionValueType<K>>;
|
|
13
|
+
export type OptionReader<T extends OptionResult = OptionResult> = (option: string, read: OptionsReaderRead, options: OptionsReaderState) => T | null;
|
|
14
14
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,CAAA;AAE9C,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,MAAM;IAC3C,IAAI,EAAE,CAAC,CAAA;IACP,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,MAAM,IAAI,YAAY,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;AAEvE,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,IAC7C,CAAC,SAAS,WAAW,CAAC,MAAM,CAAC,GACzB,CAAC,CAAC,MAAM,CAAC,GACT,CAAC,CAAA;AAEP,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAExD,MAAM,MAAM,iBAAiB,GAAG,MAAM,MAAM,CAAA;AAE5C,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,gBAAgB,GAAG,kBAAkB,CAAA;AAEhH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,oBAAoB,IACxD,CAAC,SAAS,iBAAiB,GACvB,MAAM,GACN,CAAC,SAAS,iBAAiB,GACzB,MAAM,GACN,CAAC,SAAS,gBAAgB,GACxB,MAAM,EAAE,GACR,OAAO,CAAA;AAEjB,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,SAAS,oBAAoB,GAAG,oBAAoB,IAAI,MAAM,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAA;AAE1I,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY,IAC5D,CACE,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,kBAAkB,KACxB,CAAC,GAAG,IAAI,CAAA"}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { ArgRef } from './types';
|
|
2
|
-
|
|
1
|
+
import type { ArgRef } from './types.js';
|
|
2
|
+
type FlatMerge<T> = T extends infer U ? {
|
|
3
3
|
[K in keyof U]: U[K];
|
|
4
4
|
} : never;
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
export
|
|
5
|
+
export type Merge<T extends readonly [...unknown[]]> = T extends [infer L, ...infer R] ? FlatMerge<NonNullable<L> & Merge<R>> : unknown;
|
|
6
|
+
export type UnionMerge<T extends readonly [...unknown[]]> = T extends [infer L, ...infer R] ? L | Merge<R> : any;
|
|
7
|
+
type AnyFunction = (...args: any[]) => any;
|
|
8
|
+
export type ReturnTypes<T extends readonly [...AnyFunction[]]> = T extends [infer L, ...infer R] ? L extends AnyFunction ? R extends AnyFunction[] ? [ReturnType<L>, ...ReturnTypes<R>] : [] : [] : [];
|
|
9
9
|
/**
|
|
10
10
|
* Match reference with argument.
|
|
11
11
|
* @param argRef
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAE,GAAG,KAAK,CAAA;AAExE,MAAM,MAAM,KAAK,CAAC,CAAC,SAAS,SAAS,CAAC,GAAG,OAAO,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,GAClF,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GACpC,OAAO,CAAA;AAEX,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,SAAS,CAAC,GAAG,OAAO,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,GACvF,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAEZ,GAAG,CAAA;AAGP,KAAK,WAAW,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAA;AAE1C,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,SAAS,CAAC,GAAG,WAAW,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,GAC5F,CAAC,SAAS,WAAW,GACnB,CAAC,SAAS,WAAW,EAAE,GACrB,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,GAClC,EAAE,GACJ,EAAE,GACJ,EAAE,CAAA;AAEN;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,YAc5E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,YAanF"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "argue-cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "
|
|
5
|
-
"description": "A thin and strongly typed CLI
|
|
4
|
+
"version": "3.0.0",
|
|
5
|
+
"description": "A thin and strongly typed CLI arguments parser for Node.js.",
|
|
6
6
|
"author": "dangreen",
|
|
7
7
|
"license": "MIT",
|
|
8
|
+
"funding": "https://ko-fi.com/dangreen",
|
|
8
9
|
"repository": {
|
|
9
10
|
"type": "git",
|
|
10
11
|
"url": "https://github.com/TrigenSoftware/Argue.git"
|
|
@@ -12,24 +13,6 @@
|
|
|
12
13
|
"bugs": {
|
|
13
14
|
"url": "https://github.com/TrigenSoftware/Argue/issues"
|
|
14
15
|
},
|
|
15
|
-
"main": "./dist/index.cjs",
|
|
16
|
-
"types": "./dist/index.d.ts",
|
|
17
|
-
"publishConfig": {
|
|
18
|
-
"main": "./dist/index.cjs",
|
|
19
|
-
"module": "./dist/index.js",
|
|
20
|
-
"exports": {
|
|
21
|
-
"import": {
|
|
22
|
-
"default": "./dist/index.js"
|
|
23
|
-
},
|
|
24
|
-
"require": {
|
|
25
|
-
"default": "./dist/index.cjs"
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
"directory": "package"
|
|
29
|
-
},
|
|
30
|
-
"engines": {
|
|
31
|
-
"node": ">=14.0.0"
|
|
32
|
-
},
|
|
33
16
|
"keywords": [
|
|
34
17
|
"cli",
|
|
35
18
|
"arguments",
|
|
@@ -37,18 +20,15 @@
|
|
|
37
20
|
"console",
|
|
38
21
|
"terminal"
|
|
39
22
|
],
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=24"
|
|
25
|
+
},
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js"
|
|
30
|
+
},
|
|
40
31
|
"files": [
|
|
41
32
|
"dist"
|
|
42
|
-
]
|
|
43
|
-
"readme": "",
|
|
44
|
-
"scripts": {},
|
|
45
|
-
"module": "./dist/index.js",
|
|
46
|
-
"exports": {
|
|
47
|
-
"import": {
|
|
48
|
-
"default": "./dist/index.js"
|
|
49
|
-
},
|
|
50
|
-
"require": {
|
|
51
|
-
"default": "./dist/index.cjs"
|
|
52
|
-
}
|
|
53
|
-
}
|
|
33
|
+
]
|
|
54
34
|
}
|
package/dist/index.cjs
DELETED
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
const ARGV_START_INDEX = 2;
|
|
6
|
-
/**
|
|
7
|
-
* Internal state of arguments.
|
|
8
|
-
*/ const argv = process.argv.slice(ARGV_START_INDEX);
|
|
9
|
-
/**
|
|
10
|
-
* Reset arguments state.
|
|
11
|
-
*/ function resetArgs() {
|
|
12
|
-
argv.splice(0, argv.length);
|
|
13
|
-
argv.push(...process.argv.slice(ARGV_START_INDEX));
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Set arguments state.
|
|
17
|
-
* @param args
|
|
18
|
-
*/ function setArgs(...args) {
|
|
19
|
-
argv.splice(0, argv.length);
|
|
20
|
-
argv.push(...args);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Match reference with argument.
|
|
25
|
-
* @param argRef
|
|
26
|
-
* @param arg
|
|
27
|
-
* @returns Full name or null.
|
|
28
|
-
*/ function matchArgName(argRef, arg) {
|
|
29
|
-
if (typeof argRef === 'string') {
|
|
30
|
-
return argRef === arg ? argRef : null;
|
|
31
|
-
}
|
|
32
|
-
if (argRef.name === arg) {
|
|
33
|
-
return argRef.name;
|
|
34
|
-
}
|
|
35
|
-
return argRef.aliases.includes(arg) ? argRef.name : null;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Find full argument name in references.
|
|
39
|
-
* @param argRefs
|
|
40
|
-
* @param arg
|
|
41
|
-
* @returns Found argument's full name or null.
|
|
42
|
-
*/ function findArgName(argRefs, arg) {
|
|
43
|
-
let argRef;
|
|
44
|
-
let argName;
|
|
45
|
-
for (argRef of argRefs){
|
|
46
|
-
argName = matchArgName(argRef, arg);
|
|
47
|
-
if (argName) {
|
|
48
|
-
return argName;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Read next argument.
|
|
56
|
-
* Throws error if no next argument.
|
|
57
|
-
* @returns Next argument.
|
|
58
|
-
*/ function read() {
|
|
59
|
-
const value = argv.shift();
|
|
60
|
-
if (!value) {
|
|
61
|
-
throw new Error('Unexpected end of arguments');
|
|
62
|
-
}
|
|
63
|
-
return value;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Expectation of the end.
|
|
67
|
-
* Throws an error if there are more arguments left.
|
|
68
|
-
*/ function end() {
|
|
69
|
-
if (argv.length) {
|
|
70
|
-
throw new Error(`Unexpected argument "${argv[0]}"`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Expect one of the given arguments.
|
|
75
|
-
* @param argRefs
|
|
76
|
-
* @returns Expected full argument name.
|
|
77
|
-
*/ function expect(...argRefs) {
|
|
78
|
-
const arg = read();
|
|
79
|
-
const argName = findArgName(argRefs, arg);
|
|
80
|
-
if (!argName) {
|
|
81
|
-
throw new Error(`Unexpected argument "${arg}"`);
|
|
82
|
-
}
|
|
83
|
-
return argName;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Describe argument with aliases.
|
|
88
|
-
* @param name - Main name.
|
|
89
|
-
* @param alias - Alias name.
|
|
90
|
-
* @param restAliases - Rest aliases.
|
|
91
|
-
* @returns Description of argument with aliases..
|
|
92
|
-
*/ function alias(name, alias1, ...restAliases) {
|
|
93
|
-
return {
|
|
94
|
-
name,
|
|
95
|
-
aliases: [
|
|
96
|
-
alias1,
|
|
97
|
-
...restAliases
|
|
98
|
-
]
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Describe option with value.
|
|
103
|
-
* @param argRef - Option name.
|
|
104
|
-
* @param type - Value type.
|
|
105
|
-
* @returns Option reader.
|
|
106
|
-
*/ function option(argRef, type) {
|
|
107
|
-
if (type === String) {
|
|
108
|
-
return (option1, read)=>{
|
|
109
|
-
const argName = matchArgName(argRef, option1);
|
|
110
|
-
if (argName) {
|
|
111
|
-
return {
|
|
112
|
-
[argName]: read()
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
return null;
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
if (type === Number) {
|
|
119
|
-
return (option2, read)=>{
|
|
120
|
-
const argName = matchArgName(argRef, option2);
|
|
121
|
-
if (argName) {
|
|
122
|
-
return {
|
|
123
|
-
[argName]: parseFloat(read())
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
return null;
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
if (type === Array) {
|
|
130
|
-
return (option3, read, options)=>{
|
|
131
|
-
const argName = matchArgName(argRef, option3);
|
|
132
|
-
if (argName) {
|
|
133
|
-
const prevValues = options[argName];
|
|
134
|
-
const values = read().split(',');
|
|
135
|
-
return {
|
|
136
|
-
[argName]: Array.isArray(prevValues) ? prevValues.concat(values) : values
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
return null;
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
return (option4)=>{
|
|
143
|
-
const argName = matchArgName(argRef, option4);
|
|
144
|
-
if (argName) {
|
|
145
|
-
return {
|
|
146
|
-
[argName]: true
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
return null;
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function isOption(arg) {
|
|
154
|
-
return /^--?[^-].*/.test(arg);
|
|
155
|
-
}
|
|
156
|
-
function removePrefix(arg) {
|
|
157
|
-
return arg.replace(/^--?/, '');
|
|
158
|
-
}
|
|
159
|
-
function createOptionReader(optionReaders) {
|
|
160
|
-
const optionReader = optionReaders.reduceRight((readNextOption, readOption)=>{
|
|
161
|
-
if (!readNextOption) {
|
|
162
|
-
return readOption;
|
|
163
|
-
}
|
|
164
|
-
var ref;
|
|
165
|
-
return (option, read, options)=>(ref = readOption(option, read, options)) !== null && ref !== void 0 ? ref : readNextOption(option, read, options)
|
|
166
|
-
;
|
|
167
|
-
}, null);
|
|
168
|
-
return optionReader;
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Read options from arguments.
|
|
172
|
-
* @param optionReaders
|
|
173
|
-
* @returns Options with values.
|
|
174
|
-
*/ function readOptions(...optionReaders) {
|
|
175
|
-
if (!argv.length) {
|
|
176
|
-
return {};
|
|
177
|
-
}
|
|
178
|
-
const readOption = createOptionReader(optionReaders);
|
|
179
|
-
if (!readOption) {
|
|
180
|
-
return {};
|
|
181
|
-
}
|
|
182
|
-
const options = {};
|
|
183
|
-
let i = 0;
|
|
184
|
-
let arg = argv[i];
|
|
185
|
-
let optionResult;
|
|
186
|
-
const next = ()=>{
|
|
187
|
-
arg = argv[++i];
|
|
188
|
-
};
|
|
189
|
-
const remove = ()=>{
|
|
190
|
-
argv.splice(i--, 1);
|
|
191
|
-
};
|
|
192
|
-
const read = ()=>{
|
|
193
|
-
next();
|
|
194
|
-
remove();
|
|
195
|
-
if (!arg) {
|
|
196
|
-
throw new Error('Unexpected end of arguments');
|
|
197
|
-
}
|
|
198
|
-
return arg;
|
|
199
|
-
};
|
|
200
|
-
// eslint-disable-next-line no-unmodified-loop-condition
|
|
201
|
-
while(arg){
|
|
202
|
-
if (isOption(arg)) {
|
|
203
|
-
optionResult = readOption(removePrefix(arg), read, options);
|
|
204
|
-
if (optionResult) {
|
|
205
|
-
remove();
|
|
206
|
-
Object.assign(options, optionResult);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
next();
|
|
210
|
-
}
|
|
211
|
-
return options;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
exports.alias = alias;
|
|
215
|
-
exports.argv = argv;
|
|
216
|
-
exports.end = end;
|
|
217
|
-
exports.expect = expect;
|
|
218
|
-
exports.option = option;
|
|
219
|
-
exports.read = read;
|
|
220
|
-
exports.readOptions = readOptions;
|
|
221
|
-
exports.resetArgs = resetArgs;
|
|
222
|
-
exports.setArgs = setArgs;
|
|
223
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/argv.ts","../src/utils.ts","../src/core.ts","../src/args.ts","../src/options.ts"],"sourcesContent":["\nconst ARGV_START_INDEX = 2\n\n/**\n * Internal state of arguments.\n */\nexport const argv = process.argv.slice(ARGV_START_INDEX)\n\n/**\n * Reset arguments state.\n */\nexport function resetArgs() {\n argv.splice(0, argv.length)\n argv.push(...process.argv.slice(ARGV_START_INDEX))\n}\n\n/**\n * Set arguments state.\n * @param args\n */\nexport function setArgs(...args: string[]) {\n argv.splice(0, argv.length)\n argv.push(...args)\n}\n","\nimport { ArgRef } from './types'\n\ntype FlatMerge<T> = T extends infer U ? { [K in keyof U]: U[K] } : never\n\nexport type Merge<T extends readonly [...unknown[]]> = T extends [infer L, ...infer R]\n ? FlatMerge<NonNullable<L> & Merge<R>>\n : unknown\n\nexport type UnionMerge<T extends readonly [...unknown[]]> = T extends [infer L, ...infer R]\n ? L | Merge<R>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n : any\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyFunction = (...args: any[]) => any\n\nexport type ReturnTypes<T extends readonly [...AnyFunction[]]> = T extends [infer L, ...infer R]\n ? L extends AnyFunction\n ? R extends AnyFunction[]\n ? [ReturnType<L>, ...ReturnTypes<R>]\n : []\n : []\n : []\n\n/**\n * Match reference with argument.\n * @param argRef\n * @param arg\n * @returns Full name or null.\n */\nexport function matchArgName<T extends string>(argRef: ArgRef<T>, arg: string) {\n if (typeof argRef === 'string') {\n return argRef === arg\n ? argRef\n : null\n }\n\n if (argRef.name === arg) {\n return argRef.name\n }\n\n return argRef.aliases.includes(arg)\n ? argRef.name\n : null\n}\n\n/**\n * Find full argument name in references.\n * @param argRefs\n * @param arg\n * @returns Found argument's full name or null.\n */\nexport function findArgName<T extends string>(argRefs: [...ArgRef<T>[]], arg: string) {\n let argRef: ArgRef<T>\n let argName: T | null\n\n for (argRef of argRefs) {\n argName = matchArgName(argRef, arg)\n\n if (argName) {\n return argName\n }\n }\n\n return null\n}\n","import { argv } from './argv'\nimport { ArgRef } from './types'\nimport { findArgName } from './utils'\n\n/**\n * Read next argument.\n * Throws error if no next argument.\n * @returns Next argument.\n */\nexport function read() {\n const value = argv.shift()\n\n if (!value) {\n throw new Error('Unexpected end of arguments')\n }\n\n return value\n}\n\n/**\n * Expectation of the end.\n * Throws an error if there are more arguments left.\n */\nexport function end() {\n if (argv.length) {\n throw new Error(`Unexpected argument \"${argv[0]}\"`)\n }\n}\n\n/**\n * Expect one of the given arguments.\n * @param argRefs\n * @returns Expected full argument name.\n */\nexport function expect<T extends string>(...argRefs: [...ArgRef<T>[]]) {\n const arg = read()\n const argName = findArgName(argRefs, arg)\n\n if (!argName) {\n throw new Error(`Unexpected argument \"${arg}\"`)\n }\n\n return argName\n}\n","import {\n AliasArgRef,\n ArgRef,\n PrimitiveConstructor,\n OptionsReaderState,\n OptionsReaderRead,\n OptionResult\n} from './types'\nimport { matchArgName } from './utils'\n\n/**\n * Describe argument with aliases.\n * @param name - Main name.\n * @param alias - Alias name.\n * @param restAliases - Rest aliases.\n * @returns Description of argument with aliases..\n */\nexport function alias<T extends string>(name: T, alias: string, ...restAliases: string[]): AliasArgRef<T> {\n return {\n name,\n aliases: [alias, ...restAliases]\n }\n}\n\n/**\n * Describe option with value.\n * @param argRef - Option name.\n * @param type - Value type.\n * @returns Option reader.\n */\nexport function option<T extends string, K extends PrimitiveConstructor>(argRef: ArgRef<T>, type: K) {\n if (type === String) {\n return (option: string, read: OptionsReaderRead) => {\n const argName = matchArgName(argRef, option)\n\n if (argName) {\n return {\n [argName]: read()\n } as OptionResult<T, K>\n }\n\n return null\n }\n }\n\n if (type === Number) {\n return (option: string, read: OptionsReaderRead) => {\n const argName = matchArgName(argRef, option)\n\n if (argName) {\n return {\n [argName]: parseFloat(read())\n } as OptionResult<T, K>\n }\n\n return null\n }\n }\n\n if (type === Array) {\n return (option: string, read: OptionsReaderRead, options: OptionsReaderState) => {\n const argName = matchArgName(argRef, option)\n\n if (argName) {\n const prevValues = options[argName]\n const values = read().split(',')\n\n return {\n [argName]: Array.isArray(prevValues)\n ? prevValues.concat(values)\n : values\n } as OptionResult<T, K>\n }\n\n return null\n }\n }\n\n return (option: string) => {\n const argName = matchArgName(argRef, option)\n\n if (argName) {\n return {\n [argName]: true\n } as OptionResult<T, K>\n }\n\n return null\n }\n}\n","import { argv } from './argv'\nimport { OptionReader, OptionResult } from './types'\nimport { Merge, ReturnTypes, UnionMerge } from './utils'\n\nfunction isOption(arg: string) {\n return /^--?[^-].*/.test(arg)\n}\n\nfunction removePrefix(arg: string) {\n return arg.replace(/^--?/, '')\n}\n\nfunction createOptionReader<T extends OptionReader[]>(optionReaders: [...T]) {\n const optionReader = optionReaders.reduceRight<OptionReader | null>(\n (readNextOption, readOption) => {\n if (!readNextOption) {\n return readOption\n }\n\n return (option, read, options) => readOption(option, read, options) ?? readNextOption(option, read, options)\n },\n null\n )\n\n return optionReader as OptionReader<UnionMerge<ReturnTypes<T>>> | null\n}\n\n/**\n * Read options from arguments.\n * @param optionReaders\n * @returns Options with values.\n */\nexport function readOptions<T extends OptionReader[]>(...optionReaders: [...T]): Partial<Merge<ReturnTypes<T>>> {\n if (!argv.length) {\n return {}\n }\n\n const readOption = createOptionReader(optionReaders)\n\n if (!readOption) {\n return {}\n }\n\n const options = {}\n let i = 0\n let arg = argv[i]\n let optionResult: OptionResult | null\n const next = () => {\n arg = argv[++i]\n }\n const remove = () => {\n argv.splice(i--, 1)\n }\n const read = () => {\n next()\n remove()\n\n if (!arg) {\n throw new Error('Unexpected end of arguments')\n }\n\n return arg\n }\n\n // eslint-disable-next-line no-unmodified-loop-condition\n while (arg) {\n if (isOption(arg)) {\n optionResult = readOption(removePrefix(arg), read, options)\n\n if (optionResult) {\n remove()\n Object.assign(options, optionResult)\n }\n }\n\n next()\n }\n\n return options\n}\n"],"names":["ARGV_START_INDEX","argv","process","slice","resetArgs","splice","length","push","setArgs","args","matchArgName","argRef","arg","name","aliases","includes","findArgName","argRefs","argName","read","value","shift","Error","end","expect","alias","restAliases","option","type","String","Number","parseFloat","Array","options","prevValues","values","split","isArray","concat","isOption","test","removePrefix","replace","createOptionReader","optionReaders","optionReader","reduceRight","readNextOption","readOption","readOptions","i","optionResult","next","remove","Object","assign"],"mappings":"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"}
|