args-tokens 0.22.6 → 0.23.1
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 +44 -6
- package/lib/index.d.ts +6 -3
- package/lib/index.js +6 -3
- package/lib/parser.d.ts +97 -1
- package/lib/parser.js +197 -1
- package/lib/resolver.d.ts +559 -2
- package/lib/resolver.js +286 -3
- package/lib/{utils-1LQrGCWG.js → utils-CxvkckUD.js} +1 -1
- package/lib/utils.js +1 -1
- package/package.json +26 -25
- package/lib/parser-DEYiqyo1.d.ts +0 -98
- package/lib/parser-M-ayhS1h.js +0 -199
- package/lib/resolver-7JOAwfSr.d.ts +0 -474
- package/lib/resolver-DBvNkaE7.js +0 -262
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[![Version][npm-version-src]][npm-version-href]
|
|
4
4
|
[![JSR][jsr-src]][jsr-href]
|
|
5
|
-
[![InstallSize][install-size-src]][install-size-
|
|
5
|
+
[![InstallSize][install-size-src]][install-size-href]
|
|
6
6
|
[![CI][ci-src]][ci-href]
|
|
7
7
|
|
|
8
8
|
> [`parseArgs` tokens](https://nodejs.org/api/util.html#parseargs-tokens) compatibility and more high-performance parser
|
|
@@ -95,7 +95,7 @@ Breaking changes might not follow SemVer, please pin Vitest's version when using
|
|
|
95
95
|
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
## ❓ What's different about parseArgs tokens?
|
|
98
|
+
## ❓ What's different about `parseArgs` tokens?
|
|
99
99
|
|
|
100
100
|
The token output for the short option `-x=v` is different:
|
|
101
101
|
|
|
@@ -184,7 +184,7 @@ bun add args-tokens
|
|
|
184
184
|
|
|
185
185
|
### Parse args to tokens
|
|
186
186
|
|
|
187
|
-
`parseArgs` will transform arguments into tokens. This function is useful if you want to analyze arguments yourself based on the tokens. It's faster than `node:util`
|
|
187
|
+
`parseArgs` will transform arguments into tokens. This function is useful if you want to analyze arguments yourself based on the tokens. It's faster than `parseArgs` of `node:util` because it only focuses on token transformation.
|
|
188
188
|
|
|
189
189
|
```js
|
|
190
190
|
import { parseArgs } from 'args-tokens' // for Node.js and Bun
|
|
@@ -239,7 +239,7 @@ console.log('positionals:', positionals)
|
|
|
239
239
|
|
|
240
240
|
## Convenient argument parsing
|
|
241
241
|
|
|
242
|
-
Using the `parse
|
|
242
|
+
Using the `parse` you can transform the arguments into tokens and resolve the argument values once:
|
|
243
243
|
|
|
244
244
|
```js
|
|
245
245
|
import { parse } from 'args-tokens' // for Node.js and Bun
|
|
@@ -302,7 +302,7 @@ const tokens = parseArgs(['-a=1'], { allowCompatible: true }) // add `allowCompa
|
|
|
302
302
|
deepStrictEqual(tokensNode, tokens)
|
|
303
303
|
```
|
|
304
304
|
|
|
305
|
-
## ArgSchema Reference
|
|
305
|
+
## `ArgSchema` Reference
|
|
306
306
|
|
|
307
307
|
The `ArgSchema` interface defines the configuration for command-line arguments. This schema is similar to Node.js `util.parseArgs` but with extended features.
|
|
308
308
|
|
|
@@ -533,6 +533,44 @@ Custom parsing function for `type: 'custom'` arguments. Required when `type: 'cu
|
|
|
533
533
|
}
|
|
534
534
|
```
|
|
535
535
|
|
|
536
|
+
#### `conflicts` (optional)
|
|
537
|
+
|
|
538
|
+
Specifies other options that cannot be used together with this option. When conflicting options are provided together, an `ArgResolveError` will be thrown.
|
|
539
|
+
|
|
540
|
+
Conflicts only need to be defined on one side - if option A defines a conflict with option B, the conflict is automatically detected when both are used.
|
|
541
|
+
|
|
542
|
+
<!-- eslint-skip -->
|
|
543
|
+
|
|
544
|
+
```js
|
|
545
|
+
{
|
|
546
|
+
// Single conflict
|
|
547
|
+
port: {
|
|
548
|
+
type: 'number',
|
|
549
|
+
conflicts: 'socket' // Cannot use --port with --socket
|
|
550
|
+
},
|
|
551
|
+
socket: {
|
|
552
|
+
type: 'string'
|
|
553
|
+
// No need to define conflicts: 'port' here
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Multiple conflicts (mutually exclusive options)
|
|
558
|
+
{
|
|
559
|
+
tcp: {
|
|
560
|
+
type: 'number',
|
|
561
|
+
conflicts: ['udp', 'unix'] // Cannot use with --udp or --unix
|
|
562
|
+
},
|
|
563
|
+
udp: {
|
|
564
|
+
type: 'number',
|
|
565
|
+
conflicts: ['tcp', 'unix']
|
|
566
|
+
},
|
|
567
|
+
unix: {
|
|
568
|
+
type: 'string',
|
|
569
|
+
conflicts: ['tcp', 'udp']
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
```
|
|
573
|
+
|
|
536
574
|
## 🙌 Contributing guidelines
|
|
537
575
|
|
|
538
576
|
If you are interested in contributing to `args-tokens`, I highly recommend checking out [the contributing guidelines](/CONTRIBUTING.md) here. You'll find all the relevant information such as [how to make a PR](/CONTRIBUTING.md#pull-request-guidelines), [how to setup development](/CONTRIBUTING.md#development-setup)) etc., there.
|
|
@@ -546,7 +584,7 @@ This project is inspired by:
|
|
|
546
584
|
|
|
547
585
|
## 🤝 Sponsors
|
|
548
586
|
|
|
549
|
-
The development of
|
|
587
|
+
The development of Gunshi is supported by my OSS sponsors!
|
|
550
588
|
|
|
551
589
|
<p align="center">
|
|
552
590
|
<a href="https://cdn.jsdelivr.net/gh/kazupon/sponsors/sponsors.svg">
|
package/lib/index.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { ArgToken, ParserOptions, parseArgs
|
|
2
|
-
import { ArgExplicitlyProvided, ArgResolveError
|
|
1
|
+
import { ArgToken, ParserOptions, parseArgs } from "./parser.js";
|
|
2
|
+
import { ArgExplicitlyProvided, ArgResolveError, ArgResolveErrorType, ArgSchema, ArgValues, Args, ResolveArgs, resolveArgs } from "./resolver.js";
|
|
3
3
|
|
|
4
4
|
//#region src/parse.d.ts
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
6
9
|
/**
|
|
7
10
|
* Parse options for {@link parse} function.
|
|
8
11
|
*
|
package/lib/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { parseArgs } from "./parser
|
|
2
|
-
import "./
|
|
3
|
-
import { ArgResolveError, resolveArgs } from "./resolver-DBvNkaE7.js";
|
|
1
|
+
import { parseArgs } from "./parser.js";
|
|
2
|
+
import { ArgResolveError, resolveArgs } from "./resolver.js";
|
|
4
3
|
|
|
5
4
|
//#region src/parse.ts
|
|
5
|
+
/**
|
|
6
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
6
9
|
const DEFAULT_OPTIONS = {
|
|
7
10
|
help: {
|
|
8
11
|
type: "boolean",
|
package/lib/parser.d.ts
CHANGED
|
@@ -1,2 +1,98 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/parser.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Entry point of argument parser.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* forked from `nodejs/node` (`pkgjs/parseargs`)
|
|
9
|
+
* repository url: https://github.com/nodejs/node (https://github.com/pkgjs/parseargs)
|
|
10
|
+
* code url: https://github.com/nodejs/node/blob/main/lib/internal/util/parse_args/parse_args.js
|
|
11
|
+
*
|
|
12
|
+
* @author kazuya kawaguchi (a.k.a. kazupon)
|
|
13
|
+
* @license MIT
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Argument token Kind.
|
|
17
|
+
*
|
|
18
|
+
* - `option`: option token, support short option (e.g. `-x`) and long option (e.g. `--foo`)
|
|
19
|
+
* - `option-terminator`: option terminator (`--`) token, see guideline 10 in https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html
|
|
20
|
+
* - `positional`: positional token
|
|
21
|
+
*/
|
|
22
|
+
type ArgTokenKind = 'option' | 'option-terminator' | 'positional';
|
|
23
|
+
/**
|
|
24
|
+
* Argument token.
|
|
25
|
+
*/
|
|
26
|
+
interface ArgToken {
|
|
27
|
+
/**
|
|
28
|
+
* Argument token kind.
|
|
29
|
+
*/
|
|
30
|
+
kind: ArgTokenKind;
|
|
31
|
+
/**
|
|
32
|
+
* Argument token index, e.g `--foo bar` => `--foo` index is 0, `bar` index is 1.
|
|
33
|
+
*/
|
|
34
|
+
index: number;
|
|
35
|
+
/**
|
|
36
|
+
* Option name, e.g. `--foo` => `foo`, `-x` => `x`.
|
|
37
|
+
*/
|
|
38
|
+
name?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Raw option name, e.g. `--foo` => `--foo`, `-x` => `-x`.
|
|
41
|
+
*/
|
|
42
|
+
rawName?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Option value, e.g. `--foo=bar` => `bar`, `-x=bar` => `bar`.
|
|
45
|
+
* If the `allowCompatible` option is `true`, short option value will be same as Node.js `parseArgs` behavior.
|
|
46
|
+
*/
|
|
47
|
+
value?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Inline value, e.g. `--foo=bar` => `true`, `-x=bar` => `true`.
|
|
50
|
+
*/
|
|
51
|
+
inlineValue?: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Parser Options.
|
|
55
|
+
*/
|
|
56
|
+
interface ParserOptions {
|
|
57
|
+
/**
|
|
58
|
+
* [Node.js parseArgs](https://nodejs.org/api/util.html#parseargs-tokens) tokens compatible mode.
|
|
59
|
+
*
|
|
60
|
+
* @default false
|
|
61
|
+
*/
|
|
62
|
+
allowCompatible?: boolean;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Parse command line arguments.
|
|
66
|
+
*
|
|
67
|
+
* @param args - command line arguments
|
|
68
|
+
* @param options - parse options, about details see {@link ParserOptions}
|
|
69
|
+
* @returns Argument tokens.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```js
|
|
73
|
+
* import { parseArgs } from 'args-tokens' // for Node.js and Bun
|
|
74
|
+
* // import { parseArgs } from 'jsr:@kazupon/args-tokens' // for Deno
|
|
75
|
+
*
|
|
76
|
+
* const tokens = parseArgs(['--foo', 'bar', '-x', '--bar=baz'])
|
|
77
|
+
* // do something with using tokens
|
|
78
|
+
* // ...
|
|
79
|
+
* console.log('tokens:', tokens)
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
declare function parseArgs(args: string[], options?: ParserOptions): ArgToken[];
|
|
83
|
+
/**
|
|
84
|
+
* Check if `arg` is a short option (e.g. `-f`).
|
|
85
|
+
*
|
|
86
|
+
* @param arg - An argument to check
|
|
87
|
+
* @returns Whether `arg` is a short option.
|
|
88
|
+
*/
|
|
89
|
+
declare function isShortOption(arg: string): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Check if `arg` is a long option prefix (e.g. `--`).
|
|
92
|
+
*
|
|
93
|
+
* @param arg - An argument to check
|
|
94
|
+
* @returns Whether `arg` is a long option prefix.
|
|
95
|
+
*/
|
|
96
|
+
declare function hasLongOptionPrefix(arg: string): boolean;
|
|
97
|
+
//#endregion
|
|
2
98
|
export { ArgToken, ParserOptions, hasLongOptionPrefix, isShortOption, parseArgs };
|
package/lib/parser.js
CHANGED
|
@@ -1,3 +1,199 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/parser.ts
|
|
2
|
+
const HYPHEN_CHAR = "-";
|
|
3
|
+
const HYPHEN_CODE = HYPHEN_CHAR.codePointAt(0);
|
|
4
|
+
const EQUAL_CHAR = "=";
|
|
5
|
+
const EQUAL_CODE = EQUAL_CHAR.codePointAt(0);
|
|
6
|
+
const TERMINATOR = "--";
|
|
7
|
+
const SHORT_OPTION_PREFIX = HYPHEN_CHAR;
|
|
8
|
+
const LONG_OPTION_PREFIX = "--";
|
|
9
|
+
/**
|
|
10
|
+
* Parse command line arguments.
|
|
11
|
+
*
|
|
12
|
+
* @param args - command line arguments
|
|
13
|
+
* @param options - parse options, about details see {@link ParserOptions}
|
|
14
|
+
* @returns Argument tokens.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```js
|
|
18
|
+
* import { parseArgs } from 'args-tokens' // for Node.js and Bun
|
|
19
|
+
* // import { parseArgs } from 'jsr:@kazupon/args-tokens' // for Deno
|
|
20
|
+
*
|
|
21
|
+
* const tokens = parseArgs(['--foo', 'bar', '-x', '--bar=baz'])
|
|
22
|
+
* // do something with using tokens
|
|
23
|
+
* // ...
|
|
24
|
+
* console.log('tokens:', tokens)
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
function parseArgs(args, options = {}) {
|
|
28
|
+
const { allowCompatible = false } = options;
|
|
29
|
+
const tokens = [];
|
|
30
|
+
const remainings = [...args];
|
|
31
|
+
let index = -1;
|
|
32
|
+
let groupCount = 0;
|
|
33
|
+
let hasShortValueSeparator = false;
|
|
34
|
+
while (remainings.length > 0) {
|
|
35
|
+
const arg = remainings.shift();
|
|
36
|
+
if (arg == void 0) break;
|
|
37
|
+
const nextArg = remainings[0];
|
|
38
|
+
if (groupCount > 0) groupCount--;
|
|
39
|
+
else index++;
|
|
40
|
+
if (arg === TERMINATOR) {
|
|
41
|
+
tokens.push({
|
|
42
|
+
kind: "option-terminator",
|
|
43
|
+
index
|
|
44
|
+
});
|
|
45
|
+
const mapped = remainings.map((arg) => {
|
|
46
|
+
return {
|
|
47
|
+
kind: "positional",
|
|
48
|
+
index: ++index,
|
|
49
|
+
value: arg
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
tokens.push(...mapped);
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
if (isShortOption(arg)) {
|
|
56
|
+
const shortOption = arg.charAt(1);
|
|
57
|
+
let value;
|
|
58
|
+
let inlineValue;
|
|
59
|
+
if (groupCount) {
|
|
60
|
+
tokens.push({
|
|
61
|
+
kind: "option",
|
|
62
|
+
name: shortOption,
|
|
63
|
+
rawName: arg,
|
|
64
|
+
index,
|
|
65
|
+
value,
|
|
66
|
+
inlineValue
|
|
67
|
+
});
|
|
68
|
+
if (groupCount === 1 && hasOptionValue(nextArg)) {
|
|
69
|
+
value = remainings.shift();
|
|
70
|
+
if (hasShortValueSeparator) {
|
|
71
|
+
inlineValue = true;
|
|
72
|
+
hasShortValueSeparator = false;
|
|
73
|
+
}
|
|
74
|
+
tokens.push({
|
|
75
|
+
kind: "option",
|
|
76
|
+
index,
|
|
77
|
+
value,
|
|
78
|
+
inlineValue
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
} else tokens.push({
|
|
82
|
+
kind: "option",
|
|
83
|
+
name: shortOption,
|
|
84
|
+
rawName: arg,
|
|
85
|
+
index,
|
|
86
|
+
value,
|
|
87
|
+
inlineValue
|
|
88
|
+
});
|
|
89
|
+
if (value != null) ++index;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (isShortOptionGroup(arg)) {
|
|
93
|
+
const expanded = [];
|
|
94
|
+
let shortValue = "";
|
|
95
|
+
for (let i = 1; i < arg.length; i++) {
|
|
96
|
+
const shortableOption = arg.charAt(i);
|
|
97
|
+
if (hasShortValueSeparator) shortValue += shortableOption;
|
|
98
|
+
else if (!allowCompatible && shortableOption.codePointAt(0) === EQUAL_CODE) hasShortValueSeparator = true;
|
|
99
|
+
else expanded.push(`${SHORT_OPTION_PREFIX}${shortableOption}`);
|
|
100
|
+
}
|
|
101
|
+
if (shortValue) expanded.push(shortValue);
|
|
102
|
+
remainings.unshift(...expanded);
|
|
103
|
+
groupCount = expanded.length;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (isLongOption(arg)) {
|
|
107
|
+
const longOption = arg.slice(2);
|
|
108
|
+
tokens.push({
|
|
109
|
+
kind: "option",
|
|
110
|
+
name: longOption,
|
|
111
|
+
rawName: arg,
|
|
112
|
+
index,
|
|
113
|
+
value: void 0,
|
|
114
|
+
inlineValue: void 0
|
|
115
|
+
});
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (isLongOptionAndValue(arg)) {
|
|
119
|
+
const equalIndex = arg.indexOf(EQUAL_CHAR);
|
|
120
|
+
const longOption = arg.slice(2, equalIndex);
|
|
121
|
+
const value = arg.slice(equalIndex + 1);
|
|
122
|
+
tokens.push({
|
|
123
|
+
kind: "option",
|
|
124
|
+
name: longOption,
|
|
125
|
+
rawName: `${LONG_OPTION_PREFIX}${longOption}`,
|
|
126
|
+
index,
|
|
127
|
+
value,
|
|
128
|
+
inlineValue: true
|
|
129
|
+
});
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
tokens.push({
|
|
133
|
+
kind: "positional",
|
|
134
|
+
index,
|
|
135
|
+
value: arg
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return tokens;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Check if `arg` is a short option (e.g. `-f`).
|
|
142
|
+
*
|
|
143
|
+
* @param arg - An argument to check
|
|
144
|
+
* @returns Whether `arg` is a short option.
|
|
145
|
+
*/
|
|
146
|
+
function isShortOption(arg) {
|
|
147
|
+
return arg.length === 2 && arg.codePointAt(0) === HYPHEN_CODE && arg.codePointAt(1) !== HYPHEN_CODE;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Check if `arg` is a short option group (e.g. `-abc`).
|
|
151
|
+
*
|
|
152
|
+
* @param arg - An argument to check
|
|
153
|
+
* @returns Whether `arg` is a short option group.
|
|
154
|
+
*/
|
|
155
|
+
function isShortOptionGroup(arg) {
|
|
156
|
+
if (arg.length <= 2) return false;
|
|
157
|
+
if (arg.codePointAt(0) !== HYPHEN_CODE) return false;
|
|
158
|
+
if (arg.codePointAt(1) === HYPHEN_CODE) return false;
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Check if `arg` is a long option (e.g. `--foo`).
|
|
163
|
+
*
|
|
164
|
+
* @param arg - An argument to check
|
|
165
|
+
* @returns Whether `arg` is a long option.
|
|
166
|
+
*/
|
|
167
|
+
function isLongOption(arg) {
|
|
168
|
+
return hasLongOptionPrefix(arg) && !arg.includes(EQUAL_CHAR, 3);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Check if `arg` is a long option with value (e.g. `--foo=bar`).
|
|
172
|
+
*
|
|
173
|
+
* @param arg - An argument to check
|
|
174
|
+
* @returns Whether `arg` is a long option.
|
|
175
|
+
*/
|
|
176
|
+
function isLongOptionAndValue(arg) {
|
|
177
|
+
return hasLongOptionPrefix(arg) && arg.includes(EQUAL_CHAR, 3);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Check if `arg` is a long option prefix (e.g. `--`).
|
|
181
|
+
*
|
|
182
|
+
* @param arg - An argument to check
|
|
183
|
+
* @returns Whether `arg` is a long option prefix.
|
|
184
|
+
*/
|
|
185
|
+
function hasLongOptionPrefix(arg) {
|
|
186
|
+
return arg.length > 2 && ~arg.indexOf(LONG_OPTION_PREFIX);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Check if a `value` is an option value.
|
|
190
|
+
*
|
|
191
|
+
* @param value - A value to check
|
|
192
|
+
* @returns Whether a `value` is an option value.
|
|
193
|
+
*/
|
|
194
|
+
function hasOptionValue(value) {
|
|
195
|
+
return !(value == null) && value.codePointAt(0) !== HYPHEN_CODE;
|
|
196
|
+
}
|
|
2
197
|
|
|
198
|
+
//#endregion
|
|
3
199
|
export { hasLongOptionPrefix, isShortOption, parseArgs };
|