cli-nano 0.2.1 → 0.3.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 +47 -29
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -10
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +18 -13
- package/dist/interfaces.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +35 -11
- package/src/interfaces.ts +19 -13
- package/src/__tests__/parse-args.spec.ts +0 -502
package/README.md
CHANGED
|
@@ -8,14 +8,19 @@
|
|
|
8
8
|
|
|
9
9
|
## cli-nano
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Simple library to create command-line tool (aka CLI) which is quite similar to [`Yargs`](https://github.com/yargs/yargs), it is as configurable as Yargs but is a fraction of its size. The library is also inspired by NodeJS `parseArgs()` but is again more configurable so that we really get what we would expect from a more complete CLI builder.
|
|
12
12
|
|
|
13
13
|
### Features
|
|
14
14
|
- Parses arguments
|
|
15
|
-
-
|
|
15
|
+
- Supports defining Positional arguments
|
|
16
|
+
- Supports Variadic args (1 or more positional args)
|
|
17
|
+
- Automatically converts flags to camelCase
|
|
18
|
+
- accepts both `--camelCase` and `--kebab-case`
|
|
16
19
|
- Negates flags when using the `--no-` prefix
|
|
17
|
-
- Outputs version when `--version`
|
|
18
|
-
- Outputs description and supplied help text when `--help`
|
|
20
|
+
- Outputs version, when defined, when using `--version`
|
|
21
|
+
- Outputs description and supplied help text when using `--help`
|
|
22
|
+
- Supports defining `required` options
|
|
23
|
+
- Supports `default` values
|
|
19
24
|
- No dependencies!
|
|
20
25
|
|
|
21
26
|
### Install
|
|
@@ -32,29 +37,31 @@ import { type Config, parseArgs } from 'cli-nano';
|
|
|
32
37
|
|
|
33
38
|
const config: Config = {
|
|
34
39
|
command: {
|
|
35
|
-
name: '
|
|
36
|
-
description: '
|
|
40
|
+
name: 'serve',
|
|
41
|
+
description: 'Start a server with the given options',
|
|
37
42
|
positional: [
|
|
38
43
|
{
|
|
39
|
-
name: '
|
|
40
|
-
description: '
|
|
44
|
+
name: 'input',
|
|
45
|
+
description: 'serving files or directory',
|
|
41
46
|
type: 'string',
|
|
42
|
-
variadic: true, //
|
|
47
|
+
variadic: true, // 1 or more
|
|
43
48
|
required: true,
|
|
44
49
|
},
|
|
45
50
|
{
|
|
46
|
-
name: '
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
name: 'port',
|
|
52
|
+
type: 'number',
|
|
53
|
+
description: 'port to bind on',
|
|
49
54
|
required: false,
|
|
50
|
-
|
|
55
|
+
default: 5000, // optional default value
|
|
56
|
+
},
|
|
51
57
|
],
|
|
52
58
|
},
|
|
53
59
|
options: {
|
|
54
60
|
dryRun: {
|
|
55
61
|
alias: 'd',
|
|
56
62
|
type: 'boolean',
|
|
57
|
-
description: 'Show what would be
|
|
63
|
+
description: 'Show what would be done, but do not actually start the server',
|
|
64
|
+
default: false, // optional default value
|
|
58
65
|
},
|
|
59
66
|
exclude: {
|
|
60
67
|
alias: 'e',
|
|
@@ -65,6 +72,7 @@ const config: Config = {
|
|
|
65
72
|
type: 'boolean',
|
|
66
73
|
alias: 'r',
|
|
67
74
|
description: 'Enable rainbow mode',
|
|
75
|
+
default: true,
|
|
68
76
|
},
|
|
69
77
|
verbose: {
|
|
70
78
|
alias: 'V',
|
|
@@ -74,51 +82,61 @@ const config: Config = {
|
|
|
74
82
|
up: {
|
|
75
83
|
type: 'number',
|
|
76
84
|
description: 'slice a path off the bottom of the paths',
|
|
85
|
+
default: 1,
|
|
77
86
|
},
|
|
78
|
-
|
|
79
|
-
alias: '
|
|
87
|
+
display: {
|
|
88
|
+
alias: 'D',
|
|
80
89
|
required: true,
|
|
81
|
-
description: 'a required
|
|
90
|
+
description: 'a required display option',
|
|
82
91
|
}
|
|
83
92
|
},
|
|
84
93
|
version: '0.1.6',
|
|
85
94
|
};
|
|
86
95
|
|
|
87
|
-
const
|
|
88
|
-
console.log(
|
|
96
|
+
const args = parseArgs(config);
|
|
97
|
+
console.log(args);
|
|
98
|
+
|
|
99
|
+
// do something with parse arguments, for example
|
|
100
|
+
// startServer(args);
|
|
89
101
|
```
|
|
90
102
|
|
|
91
103
|
#### Example CLI Calls
|
|
92
104
|
|
|
93
105
|
```sh
|
|
94
|
-
# Show help
|
|
95
|
-
|
|
106
|
+
# Show help guide (created by reading CLI config)
|
|
107
|
+
serve --help
|
|
108
|
+
|
|
109
|
+
# Show version (when defined)
|
|
110
|
+
serve --version
|
|
96
111
|
|
|
97
|
-
#
|
|
98
|
-
|
|
112
|
+
# Uses default port 5000
|
|
113
|
+
serve dist/index.html
|
|
99
114
|
|
|
100
115
|
# With required and optional positionals
|
|
101
|
-
|
|
116
|
+
serve index1.html index2.html 8080 -D value
|
|
102
117
|
|
|
103
118
|
# With boolean and array options
|
|
104
|
-
|
|
119
|
+
serve index.html 7000 --dryRun --exclude pattern1 --exclude pattern2 -D value
|
|
105
120
|
|
|
106
121
|
# With negated boolean
|
|
107
|
-
|
|
122
|
+
serve index.html 7000 --no-dryRun -D value
|
|
108
123
|
|
|
109
124
|
# With short aliases
|
|
110
|
-
|
|
125
|
+
serve index.html 7000 -d -e pattern1 -e pattern2 -D value
|
|
111
126
|
|
|
112
127
|
# With number option
|
|
113
|
-
|
|
128
|
+
serve index.html 7000 --up 2 -D value
|
|
114
129
|
```
|
|
115
130
|
|
|
116
131
|
#### Notes
|
|
117
132
|
|
|
133
|
+
- **Default values**: Use the `default` property in an option or positional argument to specify a value if the user does not provide one.
|
|
134
|
+
- Example for option: `{ type: 'boolean', default: false }`
|
|
135
|
+
- Example for positional: `{ name: 'port', type: 'number', default: 5000 }`
|
|
118
136
|
- **Variadic positionals**: Use `variadic: true` for arguments that accept multiple values.
|
|
119
137
|
- **Required options**: Add `required: true` to enforce presence of an option.
|
|
120
138
|
- **Negated booleans**: Use `--no-flag` to set a boolean option to `false`.
|
|
121
139
|
- **Array options**: Repeat the flag to collect multiple values (e.g., `--exclude a --exclude b`).
|
|
122
140
|
- **Aliases**: Use `alias` for short flags (e.g., `-d` for `--dryRun`).
|
|
123
141
|
|
|
124
|
-
See [examples/](examples/) for more usage patterns.
|
|
142
|
+
See [examples/](examples/) for more usage patterns.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAG/D,mBAAmB,iBAAiB,CAAC;AAErC,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAG/D,mBAAmB,iBAAiB,CAAC;AAErC,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA0N7D"}
|
package/dist/index.js
CHANGED
|
@@ -19,13 +19,23 @@ export function parseArgs(config) {
|
|
|
19
19
|
printHelp(config);
|
|
20
20
|
process.exit(0);
|
|
21
21
|
}
|
|
22
|
-
if (args.includes('--version') || args.includes('-v')) {
|
|
23
|
-
console.log(version);
|
|
22
|
+
if ((version && args.includes('--version')) || args.includes('-v')) {
|
|
23
|
+
console.log(version || 'No version specified');
|
|
24
24
|
process.exit(0);
|
|
25
25
|
}
|
|
26
|
+
// Validate: required positionals must come before optional ones
|
|
27
|
+
const positionals = command.positional ?? [];
|
|
28
|
+
let foundOptional = false;
|
|
29
|
+
for (const pos of positionals) {
|
|
30
|
+
if (!pos.required) {
|
|
31
|
+
foundOptional = true;
|
|
32
|
+
}
|
|
33
|
+
if (foundOptional && pos.required) {
|
|
34
|
+
throw new Error(`Invalid positional argument configuration: required positional "${pos.name}" cannot follow optional positional(s).`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
26
37
|
// Handle positional arguments
|
|
27
38
|
let argIndex = 0;
|
|
28
|
-
const positionals = command.positional ?? [];
|
|
29
39
|
const nonOptionArgs = [];
|
|
30
40
|
while (argIndex < args.length && !args[argIndex].startsWith('-')) {
|
|
31
41
|
nonOptionArgs.push(args[argIndex]);
|
|
@@ -41,16 +51,25 @@ export function parseArgs(config) {
|
|
|
41
51
|
const usagePositionals = positionals.map(posArg => `<${posArg.name}>`).join(' ');
|
|
42
52
|
throw new Error(`Missing required positional argument, i.e.: "${command.name} ${usagePositionals}"`);
|
|
43
53
|
}
|
|
44
|
-
result[pos.name] = values;
|
|
54
|
+
result[pos.name] = !pos.required && values.length === 0 && pos.default !== undefined ? pos.default : values;
|
|
45
55
|
nonOptionIndex += values.length;
|
|
46
56
|
}
|
|
47
57
|
else {
|
|
48
|
-
const value = nonOptionArgs[nonOptionIndex
|
|
49
|
-
if
|
|
58
|
+
const value = nonOptionArgs[nonOptionIndex];
|
|
59
|
+
// Check if there are enough args left for required positionals
|
|
60
|
+
const requiredLeft = positionals.slice(i).filter(p => p.required).length;
|
|
61
|
+
const argsLeft = nonOptionArgs.length - nonOptionIndex;
|
|
62
|
+
if (value !== undefined && (argsLeft > requiredLeft - (pos.required ? 1 : 0) || pos.required)) {
|
|
63
|
+
result[pos.name] = value;
|
|
64
|
+
nonOptionIndex++;
|
|
65
|
+
}
|
|
66
|
+
else if (!pos.required && pos.default !== undefined) {
|
|
67
|
+
result[pos.name] = pos.default;
|
|
68
|
+
}
|
|
69
|
+
else if (pos.required) {
|
|
50
70
|
const usagePositionals = positionals.map(posArg => `<${posArg.name}>`).join(' ');
|
|
51
71
|
throw new Error(`Missing required positional argument, i.e.: "${command.name} ${usagePositionals}"`);
|
|
52
72
|
}
|
|
53
|
-
result[pos.name] = value;
|
|
54
73
|
}
|
|
55
74
|
}
|
|
56
75
|
// Handle options
|
|
@@ -180,8 +199,12 @@ export function parseArgs(config) {
|
|
|
180
199
|
}
|
|
181
200
|
argIndex++;
|
|
182
201
|
}
|
|
183
|
-
// After all parsing,
|
|
202
|
+
// After all parsing, assign any `default` CLI options when undefined
|
|
203
|
+
// and check for any missing `required` CLI options
|
|
184
204
|
Object.entries(options).forEach(([key, opt]) => {
|
|
205
|
+
if (result[key] === undefined && opt.default !== undefined) {
|
|
206
|
+
result[key] = opt.default;
|
|
207
|
+
}
|
|
185
208
|
if (opt.required && result[key] === undefined) {
|
|
186
209
|
const aliasStr = opt.alias ? `-${opt.alias}, ` : '';
|
|
187
210
|
throw new Error(`Missing required option: ${aliasStr}--${key}`);
|
|
@@ -191,7 +214,7 @@ export function parseArgs(config) {
|
|
|
191
214
|
}
|
|
192
215
|
/** print CLI help documentation to the screen */
|
|
193
216
|
function printHelp(config) {
|
|
194
|
-
const { command, options } = config;
|
|
217
|
+
const { command, options, version } = config;
|
|
195
218
|
// Build usage string for positionals
|
|
196
219
|
const usagePositionals = (command.positional ?? [])
|
|
197
220
|
.map(p => {
|
|
@@ -219,7 +242,9 @@ function printHelp(config) {
|
|
|
219
242
|
// Print default options (help and version)
|
|
220
243
|
console.log('\nDefault options:');
|
|
221
244
|
console.log(`${padString(' -h, --help', 21)} ${padString('Show help', 64)} [boolean]`);
|
|
222
|
-
|
|
245
|
+
if (version) {
|
|
246
|
+
console.log(`${padString(' -v, --version', 21)} ${padString('Show version number', 64)} [boolean]`);
|
|
247
|
+
}
|
|
223
248
|
console.log('\n');
|
|
224
249
|
}
|
|
225
250
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/interfaces.d.ts
CHANGED
|
@@ -5,29 +5,34 @@ export interface ArgumentOptions {
|
|
|
5
5
|
description: string;
|
|
6
6
|
/** defaults to undefined, provide shorter aliases as command options */
|
|
7
7
|
alias?: string | string[];
|
|
8
|
+
/** default value for the option if not provided */
|
|
9
|
+
default?: any;
|
|
8
10
|
/** defaults to false, is the option required? */
|
|
9
11
|
required?: boolean;
|
|
10
12
|
}
|
|
13
|
+
export interface PositionalArgument {
|
|
14
|
+
/** positional argument name (it will be displayed in the help docs) */
|
|
15
|
+
name: string;
|
|
16
|
+
/** positional argument description */
|
|
17
|
+
description: string;
|
|
18
|
+
/** postional argument type */
|
|
19
|
+
type?: 'string' | 'boolean' | 'number' | 'array';
|
|
20
|
+
/** defaults to false, allows multiple values for this positional argument */
|
|
21
|
+
variadic?: boolean;
|
|
22
|
+
/** default value for the option if not provided */
|
|
23
|
+
default?: any;
|
|
24
|
+
/** defaults to false, is the positional argument required? */
|
|
25
|
+
required?: boolean;
|
|
26
|
+
}
|
|
11
27
|
export interface CommandOptions {
|
|
12
28
|
/** CLI command name, used in the help docs */
|
|
13
29
|
name: string;
|
|
14
30
|
description: string;
|
|
15
|
-
positional?:
|
|
16
|
-
/** positional argument name (it will be displayed in the help docs) */
|
|
17
|
-
name: string;
|
|
18
|
-
/** positional argument description */
|
|
19
|
-
description: string;
|
|
20
|
-
/** postional argument type */
|
|
21
|
-
type?: 'string';
|
|
22
|
-
/** defaults to false, allows multiple values for this positional argument */
|
|
23
|
-
variadic?: boolean;
|
|
24
|
-
/** defaults to false, is the positional argument required? */
|
|
25
|
-
required?: boolean;
|
|
26
|
-
}[];
|
|
31
|
+
positional?: PositionalArgument[];
|
|
27
32
|
}
|
|
28
33
|
export interface Config {
|
|
29
34
|
command: CommandOptions;
|
|
30
35
|
options: Record<string, ArgumentOptions>;
|
|
31
|
-
version
|
|
36
|
+
version?: string;
|
|
32
37
|
}
|
|
33
38
|
//# sourceMappingURL=interfaces.d.ts.map
|
package/dist/interfaces.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,0BAA0B;IAC1B,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;IACjD,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,0BAA0B;IAC1B,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;IACjD,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,mDAAmD;IACnD,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;IACjD,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mDAAmD;IACnD,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,kBAAkB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,cAAc,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -25,21 +25,32 @@ export function parseArgs(config: Config): Record<string, any> {
|
|
|
25
25
|
printHelp(config);
|
|
26
26
|
process.exit(0);
|
|
27
27
|
}
|
|
28
|
-
if (args.includes('--version') || args.includes('-v')) {
|
|
29
|
-
console.log(version);
|
|
28
|
+
if ((version && args.includes('--version')) || args.includes('-v')) {
|
|
29
|
+
console.log(version || 'No version specified');
|
|
30
30
|
process.exit(0);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
// Validate: required positionals must come before optional ones
|
|
34
|
+
const positionals = command.positional ?? [];
|
|
35
|
+
let foundOptional = false;
|
|
36
|
+
for (const pos of positionals) {
|
|
37
|
+
if (!pos.required) {
|
|
38
|
+
foundOptional = true;
|
|
39
|
+
}
|
|
40
|
+
if (foundOptional && pos.required) {
|
|
41
|
+
throw new Error(`Invalid positional argument configuration: required positional "${pos.name}" cannot follow optional positional(s).`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
33
45
|
// Handle positional arguments
|
|
34
46
|
let argIndex = 0;
|
|
35
|
-
const positionals = command.positional ?? [];
|
|
36
47
|
const nonOptionArgs: string[] = [];
|
|
37
48
|
while (argIndex < args.length && !args[argIndex].startsWith('-')) {
|
|
38
49
|
nonOptionArgs.push(args[argIndex]);
|
|
39
50
|
argIndex++;
|
|
40
51
|
}
|
|
41
|
-
let nonOptionIndex = 0;
|
|
42
52
|
|
|
53
|
+
let nonOptionIndex = 0;
|
|
43
54
|
for (let i = 0; i < positionals.length; i++) {
|
|
44
55
|
const pos = positionals[i];
|
|
45
56
|
if (pos.variadic) {
|
|
@@ -49,15 +60,22 @@ export function parseArgs(config: Config): Record<string, any> {
|
|
|
49
60
|
const usagePositionals = positionals.map(posArg => `<${posArg.name}>`).join(' ');
|
|
50
61
|
throw new Error(`Missing required positional argument, i.e.: "${command.name} ${usagePositionals}"`);
|
|
51
62
|
}
|
|
52
|
-
result[pos.name] = values;
|
|
63
|
+
result[pos.name] = !pos.required && values.length === 0 && pos.default !== undefined ? pos.default : values;
|
|
53
64
|
nonOptionIndex += values.length;
|
|
54
65
|
} else {
|
|
55
|
-
const value = nonOptionArgs[nonOptionIndex
|
|
56
|
-
if
|
|
66
|
+
const value = nonOptionArgs[nonOptionIndex];
|
|
67
|
+
// Check if there are enough args left for required positionals
|
|
68
|
+
const requiredLeft = positionals.slice(i).filter(p => p.required).length;
|
|
69
|
+
const argsLeft = nonOptionArgs.length - nonOptionIndex;
|
|
70
|
+
if (value !== undefined && (argsLeft > requiredLeft - (pos.required ? 1 : 0) || pos.required)) {
|
|
71
|
+
result[pos.name] = value;
|
|
72
|
+
nonOptionIndex++;
|
|
73
|
+
} else if (!pos.required && pos.default !== undefined) {
|
|
74
|
+
result[pos.name] = pos.default;
|
|
75
|
+
} else if (pos.required) {
|
|
57
76
|
const usagePositionals = positionals.map(posArg => `<${posArg.name}>`).join(' ');
|
|
58
77
|
throw new Error(`Missing required positional argument, i.e.: "${command.name} ${usagePositionals}"`);
|
|
59
78
|
}
|
|
60
|
-
result[pos.name] = value;
|
|
61
79
|
}
|
|
62
80
|
}
|
|
63
81
|
|
|
@@ -190,8 +208,12 @@ export function parseArgs(config: Config): Record<string, any> {
|
|
|
190
208
|
argIndex++;
|
|
191
209
|
}
|
|
192
210
|
|
|
193
|
-
// After all parsing,
|
|
211
|
+
// After all parsing, assign any `default` CLI options when undefined
|
|
212
|
+
// and check for any missing `required` CLI options
|
|
194
213
|
Object.entries(options).forEach(([key, opt]) => {
|
|
214
|
+
if (result[key] === undefined && opt.default !== undefined) {
|
|
215
|
+
result[key] = opt.default;
|
|
216
|
+
}
|
|
195
217
|
if (opt.required && result[key] === undefined) {
|
|
196
218
|
const aliasStr = opt.alias ? `-${opt.alias}, ` : '';
|
|
197
219
|
throw new Error(`Missing required option: ${aliasStr}--${key}`);
|
|
@@ -203,7 +225,7 @@ export function parseArgs(config: Config): Record<string, any> {
|
|
|
203
225
|
|
|
204
226
|
/** print CLI help documentation to the screen */
|
|
205
227
|
function printHelp(config: Config) {
|
|
206
|
-
const { command, options } = config;
|
|
228
|
+
const { command, options, version } = config;
|
|
207
229
|
|
|
208
230
|
// Build usage string for positionals
|
|
209
231
|
const usagePositionals = (command.positional ?? [])
|
|
@@ -236,6 +258,8 @@ function printHelp(config: Config) {
|
|
|
236
258
|
// Print default options (help and version)
|
|
237
259
|
console.log('\nDefault options:');
|
|
238
260
|
console.log(`${padString(' -h, --help', 21)} ${padString('Show help', 64)} [boolean]`);
|
|
239
|
-
|
|
261
|
+
if (version) {
|
|
262
|
+
console.log(`${padString(' -v, --version', 21)} ${padString('Show version number', 64)} [boolean]`);
|
|
263
|
+
}
|
|
240
264
|
console.log('\n');
|
|
241
265
|
}
|
package/src/interfaces.ts
CHANGED
|
@@ -5,30 +5,36 @@ export interface ArgumentOptions {
|
|
|
5
5
|
description: string;
|
|
6
6
|
/** defaults to undefined, provide shorter aliases as command options */
|
|
7
7
|
alias?: string | string[];
|
|
8
|
+
/** default value for the option if not provided */
|
|
9
|
+
default?: any;
|
|
8
10
|
/** defaults to false, is the option required? */
|
|
9
11
|
required?: boolean;
|
|
10
12
|
}
|
|
11
13
|
|
|
14
|
+
export interface PositionalArgument {
|
|
15
|
+
/** positional argument name (it will be displayed in the help docs) */
|
|
16
|
+
name: string;
|
|
17
|
+
/** positional argument description */
|
|
18
|
+
description: string;
|
|
19
|
+
/** postional argument type */
|
|
20
|
+
type?: 'string' | 'boolean' | 'number' | 'array';
|
|
21
|
+
/** defaults to false, allows multiple values for this positional argument */
|
|
22
|
+
variadic?: boolean;
|
|
23
|
+
/** default value for the option if not provided */
|
|
24
|
+
default?: any;
|
|
25
|
+
/** defaults to false, is the positional argument required? */
|
|
26
|
+
required?: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
12
29
|
export interface CommandOptions {
|
|
13
30
|
/** CLI command name, used in the help docs */
|
|
14
31
|
name: string;
|
|
15
32
|
description: string;
|
|
16
|
-
positional?:
|
|
17
|
-
/** positional argument name (it will be displayed in the help docs) */
|
|
18
|
-
name: string;
|
|
19
|
-
/** positional argument description */
|
|
20
|
-
description: string;
|
|
21
|
-
/** postional argument type */
|
|
22
|
-
type?: 'string';
|
|
23
|
-
/** defaults to false, allows multiple values for this positional argument */
|
|
24
|
-
variadic?: boolean;
|
|
25
|
-
/** defaults to false, is the positional argument required? */
|
|
26
|
-
required?: boolean;
|
|
27
|
-
}[];
|
|
33
|
+
positional?: PositionalArgument[];
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
export interface Config {
|
|
31
37
|
command: CommandOptions;
|
|
32
38
|
options: Record<string, ArgumentOptions>;
|
|
33
|
-
version
|
|
39
|
+
version?: string;
|
|
34
40
|
}
|
|
@@ -1,502 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { parseArgs } from '../index.js';
|
|
4
|
-
import type { Config } from '../interfaces.js';
|
|
5
|
-
|
|
6
|
-
const config: Config = {
|
|
7
|
-
command: {
|
|
8
|
-
name: 'copyfiles',
|
|
9
|
-
description: 'Copy files from a source to a destination directory',
|
|
10
|
-
positional: [
|
|
11
|
-
{
|
|
12
|
-
name: 'inFile',
|
|
13
|
-
description: 'source files',
|
|
14
|
-
type: 'string',
|
|
15
|
-
required: true,
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
name: 'outDirectory',
|
|
19
|
-
description: 'destination directory',
|
|
20
|
-
required: true,
|
|
21
|
-
},
|
|
22
|
-
],
|
|
23
|
-
},
|
|
24
|
-
options: {
|
|
25
|
-
all: {
|
|
26
|
-
alias: 'a',
|
|
27
|
-
type: 'boolean',
|
|
28
|
-
description: 'include files & directories begining with a dot (.)',
|
|
29
|
-
},
|
|
30
|
-
dryRun: {
|
|
31
|
-
alias: 'd',
|
|
32
|
-
type: 'boolean',
|
|
33
|
-
description: 'Show what would be copied, but do not actually copy any files',
|
|
34
|
-
},
|
|
35
|
-
exclude: {
|
|
36
|
-
alias: 'e',
|
|
37
|
-
type: 'array',
|
|
38
|
-
description: 'pattern or glob to exclude (may be passed multiple times)',
|
|
39
|
-
},
|
|
40
|
-
up: {
|
|
41
|
-
type: 'number',
|
|
42
|
-
description: 'slice a path off the bottom of the paths',
|
|
43
|
-
},
|
|
44
|
-
bar: {
|
|
45
|
-
alias: 'b',
|
|
46
|
-
required: true,
|
|
47
|
-
description: 'a required bar option',
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
version: '0.1.6',
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
describe('parseArgs', () => {
|
|
54
|
-
beforeEach(() => {
|
|
55
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...[]]);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
afterEach(() => {
|
|
59
|
-
vi.restoreAllMocks();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should parse positional arguments correctly', () => {
|
|
63
|
-
const args = ['file1.txt', 'output/', '--bar', 'value'];
|
|
64
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
65
|
-
|
|
66
|
-
const result = parseArgs(config);
|
|
67
|
-
|
|
68
|
-
expect(result.inFile).toBe('file1.txt');
|
|
69
|
-
expect(result.outDirectory).toBe('output/');
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('should parse camelCase boolean options correctly', () => {
|
|
73
|
-
const args = ['file1.txt', 'output/', '--all', '--no-dryRun', '--bar', 'value'];
|
|
74
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
75
|
-
|
|
76
|
-
const result = parseArgs(config);
|
|
77
|
-
|
|
78
|
-
expect(result.inFile).toBe('file1.txt');
|
|
79
|
-
expect(result.outDirectory).toBe('output/');
|
|
80
|
-
expect(result.all).toBe(true);
|
|
81
|
-
expect(result.dryRun).toBe(false);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('should parse kebab-case boolean options correctly', () => {
|
|
85
|
-
const args = ['file1.txt', 'output/', '--all', '--no-dry-run', '--bar', 'value'];
|
|
86
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
87
|
-
|
|
88
|
-
const result = parseArgs(config);
|
|
89
|
-
|
|
90
|
-
expect(result.inFile).toBe('file1.txt');
|
|
91
|
-
expect(result.outDirectory).toBe('output/');
|
|
92
|
-
expect(result.all).toBe(true);
|
|
93
|
-
expect(result.dryRun).toBe(false);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('should parse string options correctly', () => {
|
|
97
|
-
const args = ['file1.txt', 'output/', '--up', '2', '--bar', 'value'];
|
|
98
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
99
|
-
const result = parseArgs(config);
|
|
100
|
-
expect(result.up).toBe(2);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it('should parse string options correctly with an alias', () => {
|
|
104
|
-
const args = ['file1.txt', 'output/', '--up', '2', '-b', 'value'];
|
|
105
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
106
|
-
const result = parseArgs(config);
|
|
107
|
-
expect(result.up).toBe(2);
|
|
108
|
-
expect(result.bar).toBe('value');
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('should parse array options correctly when defined at the end of the command options', () => {
|
|
112
|
-
const args = ['file1.txt', 'output/', '-b', 'value', '--exclude', 'pattern1', '--exclude', 'pattern2'];
|
|
113
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
114
|
-
const result = parseArgs(config);
|
|
115
|
-
expect(result.exclude).toEqual(['pattern1', 'pattern2']);
|
|
116
|
-
expect(result.bar).toBe('value');
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('should parse array options correctly when defined in the middle of the command options with camelCase arguments', () => {
|
|
120
|
-
const args = ['file1.txt', 'output/', '--exclude', 'pattern1', '--exclude', 'pattern2', '-b', 'value', '--dryRun'];
|
|
121
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
122
|
-
const result = parseArgs(config);
|
|
123
|
-
expect(result.exclude).toEqual(['pattern1', 'pattern2']);
|
|
124
|
-
expect(result.dryRun).toBe(true);
|
|
125
|
-
expect(result.bar).toBe('value');
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it('should parse array options correctly when defined in the middle of the command options with kebab-case arguments', () => {
|
|
129
|
-
const args = ['file1.txt', 'output/', '--exclude', 'pattern1', '--exclude', 'pattern2', '-b', 'value', '--dry-run'];
|
|
130
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
131
|
-
const result = parseArgs(config);
|
|
132
|
-
expect(result.exclude).toEqual(['pattern1', 'pattern2']);
|
|
133
|
-
expect(result.dryRun).toBe(true);
|
|
134
|
-
expect(result.bar).toBe('value');
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('should throw an error for unknown options', () => {
|
|
138
|
-
const args = ['file1.txt', 'output/', '-b', 'value', '--unknown'];
|
|
139
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
140
|
-
expect(() => parseArgs(config)).toThrowError('Unknown option: unknown');
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('should throw an error for unknown kebab-case options', () => {
|
|
144
|
-
const args = ['file1.txt', 'output/', '-b', 'value', '--unknown-kebab'];
|
|
145
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
146
|
-
expect(() => parseArgs(config)).toThrowError('Unknown option: unknown-kebab');
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it('should throw an error for unknown camelCase options', () => {
|
|
150
|
-
const args = ['file1.txt', 'output/', '-b', 'value', '--unknownCamel'];
|
|
151
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
152
|
-
expect(() => parseArgs(config)).toThrowError('Unknown option: unknownCamel');
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('should throw when truthy and --no camelCase prefix arguments are both provided', () => {
|
|
156
|
-
const args = ['file1.txt', 'output/', '--all', '--dryRun', '--no-dryRun', '-b', 'value'];
|
|
157
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
158
|
-
expect(() => parseArgs(config)).toThrowError('Providing same negated and truthy argument are not allowed');
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('should throw when truthy and --no kebab-case prefix arguments are both provided', () => {
|
|
162
|
-
const args = ['file1.txt', 'output/', '--all', '--dryRun', '--no-dry-run', '-b', 'value'];
|
|
163
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
164
|
-
expect(() => parseArgs(config)).toThrowError('Providing same negated and truthy argument are not allowed');
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it('should throw when --no prefix and truthy arguments are both provided', () => {
|
|
168
|
-
const args = ['file1.txt', 'output/', '--all', '--no-dryRun', '--dryRun', '-b', 'value'];
|
|
169
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
170
|
-
expect(() => parseArgs(config)).toThrowError('Providing same negated and truthy argument are not allowed');
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it('should throw when positional arguments are missing', () => {
|
|
174
|
-
const args = ['file1.txt', '--all', '--dryRun'];
|
|
175
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
176
|
-
|
|
177
|
-
expect(() => parseArgs(config)).toThrow('Missing required positional argument, i.e.: "copyfiles <inFile> <outDirectory>');
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it('should throw when positional arguments are missing and it will not try to read "value" as positional argument either', () => {
|
|
181
|
-
const args = ['file1.txt', '--all', '--dryRun', '-b', 'value'];
|
|
182
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
183
|
-
|
|
184
|
-
expect(() => parseArgs(config)).toThrow('Missing required positional argument, i.e.: "copyfiles <inFile> <outDirectory>');
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it('should throw when required options are missing', () => {
|
|
188
|
-
const args = ['file1.txt', 'output', '--all', '--dryRun'];
|
|
189
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
190
|
-
|
|
191
|
-
expect(() => parseArgs(config)).toThrow('Missing required option: -b, --bar');
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it('should throw if the same alias is defined for multiple options', () => {
|
|
195
|
-
const configWithDupAlias: Config = {
|
|
196
|
-
...config,
|
|
197
|
-
options: {
|
|
198
|
-
foo: { alias: 'x', type: 'boolean', description: '' },
|
|
199
|
-
bar: { alias: 'x', type: 'boolean', description: '' },
|
|
200
|
-
},
|
|
201
|
-
};
|
|
202
|
-
expect(() => parseArgs(configWithDupAlias)).toThrow('Duplicate alias detected: "x" used for both "foo" and "bar"');
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it('should handle help command', () =>
|
|
206
|
-
new Promise((done: any) => {
|
|
207
|
-
const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
|
|
208
|
-
const args = ['--help'];
|
|
209
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
210
|
-
try {
|
|
211
|
-
parseArgs(config);
|
|
212
|
-
} catch (error: any) {
|
|
213
|
-
expect(error.message).toBe('process.exit unexpectedly called with "0"');
|
|
214
|
-
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('Usage:'));
|
|
215
|
-
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
216
|
-
expect.stringContaining('copyfiles <inFile> <outDirectory> [options] Copy files from a source to a destination directory'),
|
|
217
|
-
);
|
|
218
|
-
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('\nPositionals:'));
|
|
219
|
-
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
220
|
-
expect.stringContaining(' inFile source files [string]'),
|
|
221
|
-
);
|
|
222
|
-
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
223
|
-
expect.stringContaining(' -d, --dryRun Show what would be copied, but do not actually copy any files [boolean]'),
|
|
224
|
-
);
|
|
225
|
-
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
226
|
-
expect.stringContaining(
|
|
227
|
-
' -b, --bar a required bar option [string][required]',
|
|
228
|
-
),
|
|
229
|
-
);
|
|
230
|
-
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('\nDefault options:'));
|
|
231
|
-
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
232
|
-
expect.stringContaining(' -h, --help Show help [boolean]'),
|
|
233
|
-
);
|
|
234
|
-
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
235
|
-
expect.stringContaining(' -v, --version Show version number [boolean]'),
|
|
236
|
-
);
|
|
237
|
-
done();
|
|
238
|
-
}
|
|
239
|
-
}));
|
|
240
|
-
|
|
241
|
-
it('should handle version command', () =>
|
|
242
|
-
new Promise((done: any) => {
|
|
243
|
-
const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
|
|
244
|
-
const args = ['--version'];
|
|
245
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
246
|
-
try {
|
|
247
|
-
parseArgs(config);
|
|
248
|
-
} catch (error: any) {
|
|
249
|
-
expect(error.message).toBe('process.exit unexpectedly called with "0"');
|
|
250
|
-
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('0.1.6'));
|
|
251
|
-
done();
|
|
252
|
-
}
|
|
253
|
-
}));
|
|
254
|
-
|
|
255
|
-
it('should parse optional variadic positional arguments (zero or more)', () => {
|
|
256
|
-
const config: Config = {
|
|
257
|
-
command: {
|
|
258
|
-
name: 'test',
|
|
259
|
-
description: 'Test optional variadic',
|
|
260
|
-
positional: [
|
|
261
|
-
{
|
|
262
|
-
name: 'inputs',
|
|
263
|
-
description: 'input files',
|
|
264
|
-
type: 'string',
|
|
265
|
-
variadic: true,
|
|
266
|
-
required: false,
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
name: 'outDir',
|
|
270
|
-
description: 'output directory',
|
|
271
|
-
required: true,
|
|
272
|
-
},
|
|
273
|
-
],
|
|
274
|
-
},
|
|
275
|
-
options: {},
|
|
276
|
-
version: '1.0.0',
|
|
277
|
-
};
|
|
278
|
-
// No inputs
|
|
279
|
-
let args = ['dist'];
|
|
280
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
281
|
-
let result = parseArgs(config);
|
|
282
|
-
expect(result.inputs).toEqual([]);
|
|
283
|
-
expect(result.outDir).toBe('dist');
|
|
284
|
-
|
|
285
|
-
// Multiple inputs
|
|
286
|
-
args = ['file1', 'file2', 'dist'];
|
|
287
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
288
|
-
result = parseArgs(config);
|
|
289
|
-
expect(result.inputs).toEqual(['file1', 'file2']);
|
|
290
|
-
expect(result.outDir).toBe('dist');
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
it('should parse a single optional variadic positional arguments (zero or more)', () => {
|
|
294
|
-
const config: Config = {
|
|
295
|
-
command: {
|
|
296
|
-
name: 'test',
|
|
297
|
-
description: 'Test optional variadic',
|
|
298
|
-
positional: [
|
|
299
|
-
{
|
|
300
|
-
name: 'inputs',
|
|
301
|
-
description: 'input files',
|
|
302
|
-
type: 'string',
|
|
303
|
-
variadic: true,
|
|
304
|
-
required: true,
|
|
305
|
-
},
|
|
306
|
-
],
|
|
307
|
-
},
|
|
308
|
-
options: {},
|
|
309
|
-
version: '1.0.0',
|
|
310
|
-
};
|
|
311
|
-
// No inputs
|
|
312
|
-
let args: string[] = [];
|
|
313
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
314
|
-
expect(() => parseArgs(config)).toThrow('Missing required positional argument, i.e.: "test <inputs>');
|
|
315
|
-
|
|
316
|
-
// Multiple inputs
|
|
317
|
-
args = ['file1', 'file2'];
|
|
318
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
319
|
-
const result = parseArgs(config);
|
|
320
|
-
expect(result.inputs).toEqual(['file1', 'file2']);
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
it('should print usage with required variadic positional argument using <inFile..>', () => {
|
|
324
|
-
const configWithVariadic: Config = {
|
|
325
|
-
...config,
|
|
326
|
-
command: {
|
|
327
|
-
...config.command,
|
|
328
|
-
positional: [
|
|
329
|
-
{
|
|
330
|
-
name: 'inFile',
|
|
331
|
-
description: 'source files',
|
|
332
|
-
type: 'string',
|
|
333
|
-
variadic: true,
|
|
334
|
-
required: true,
|
|
335
|
-
},
|
|
336
|
-
{
|
|
337
|
-
name: 'outDirectory',
|
|
338
|
-
description: 'destination directory',
|
|
339
|
-
required: true,
|
|
340
|
-
},
|
|
341
|
-
],
|
|
342
|
-
},
|
|
343
|
-
};
|
|
344
|
-
const spy = vi.spyOn(console, 'log').mockImplementation(() => {});
|
|
345
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', '--help']);
|
|
346
|
-
try {
|
|
347
|
-
parseArgs(configWithVariadic);
|
|
348
|
-
} catch {}
|
|
349
|
-
expect(spy).toHaveBeenCalledWith(expect.stringContaining('<inFile..>'));
|
|
350
|
-
spy.mockRestore();
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
it('should print usage without any positional argument defined', () => {
|
|
354
|
-
const configWithoutPositional: Config = {
|
|
355
|
-
...config,
|
|
356
|
-
command: {
|
|
357
|
-
...config.command,
|
|
358
|
-
},
|
|
359
|
-
options: {
|
|
360
|
-
file: {
|
|
361
|
-
description: 'source files',
|
|
362
|
-
type: 'string',
|
|
363
|
-
},
|
|
364
|
-
},
|
|
365
|
-
};
|
|
366
|
-
const spy = vi.spyOn(console, 'log').mockImplementation(() => {});
|
|
367
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', '--help']);
|
|
368
|
-
try {
|
|
369
|
-
parseArgs(configWithoutPositional);
|
|
370
|
-
} catch {}
|
|
371
|
-
expect(spy).toHaveBeenCalledWith(expect.stringContaining('--file'));
|
|
372
|
-
expect(spy).toHaveBeenCalledWith(expect.stringContaining('source files'));
|
|
373
|
-
expect(spy).toHaveBeenCalledWith(expect.stringContaining('[string]'));
|
|
374
|
-
spy.mockRestore();
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
it('should throw if required boolean flag is missing', () => {
|
|
378
|
-
const config: Config = {
|
|
379
|
-
command: {
|
|
380
|
-
name: 'test',
|
|
381
|
-
description: 'Test required flag',
|
|
382
|
-
},
|
|
383
|
-
options: {
|
|
384
|
-
force: {
|
|
385
|
-
alias: 'f',
|
|
386
|
-
type: 'boolean',
|
|
387
|
-
required: true,
|
|
388
|
-
description: 'Force operation',
|
|
389
|
-
},
|
|
390
|
-
},
|
|
391
|
-
version: '1.0.0',
|
|
392
|
-
};
|
|
393
|
-
const args: string[] = [];
|
|
394
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
395
|
-
expect(() => parseArgs(config)).toThrow('Missing required option: -f, --force');
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
it('should parse kebab-case long option when alias is camelCase', () => {
|
|
399
|
-
const configWithCamelAlias: Config = {
|
|
400
|
-
...config,
|
|
401
|
-
options: {
|
|
402
|
-
...config.options,
|
|
403
|
-
testOption: {
|
|
404
|
-
alias: 'testAliasCamel',
|
|
405
|
-
type: 'boolean',
|
|
406
|
-
description: 'A test option with camelCase alias',
|
|
407
|
-
},
|
|
408
|
-
},
|
|
409
|
-
};
|
|
410
|
-
const args = ['file1.txt', 'output/', '--test-alias-camel', '-b', 'value'];
|
|
411
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
412
|
-
const result = parseArgs(configWithCamelAlias);
|
|
413
|
-
expect(result.testOption).toBe(true);
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
it('should parse camelCase long option when alias is kebab-case', () => {
|
|
417
|
-
const configWithKebabAlias: Config = {
|
|
418
|
-
...config,
|
|
419
|
-
options: {
|
|
420
|
-
...config.options,
|
|
421
|
-
testOption: {
|
|
422
|
-
alias: 'test-alias-kebab',
|
|
423
|
-
type: 'boolean',
|
|
424
|
-
description: 'A test option with kebab-case alias',
|
|
425
|
-
},
|
|
426
|
-
},
|
|
427
|
-
};
|
|
428
|
-
const args = ['file1.txt', 'output/', '--testAliasKebab', '-b', 'value'];
|
|
429
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
430
|
-
const result = parseArgs(configWithKebabAlias);
|
|
431
|
-
expect(result.testOption).toBe(true);
|
|
432
|
-
});
|
|
433
|
-
|
|
434
|
-
it('should throw if too many positional arguments are provided', () => {
|
|
435
|
-
const args = ['file1.txt', 'output/', 'extra.txt', '-b', 'value'];
|
|
436
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
437
|
-
expect(() => parseArgs(config)).toThrow('Unknown argument: extra.txt');
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
it('should throw if array option is missing a value', () => {
|
|
441
|
-
const args = ['file1.txt', 'output/', '--exclude', '-b', 'value'];
|
|
442
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
443
|
-
expect(() => parseArgs(config)).toThrow('Missing value for array option: exclude');
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
it('should throw if string option is missing a value', () => {
|
|
447
|
-
const args = ['file1.txt', 'output/', '--bar'];
|
|
448
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
449
|
-
expect(() => parseArgs(config)).toThrow('Missing value for option: bar');
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
it('should throw if number option is missing a value', () => {
|
|
453
|
-
const args = ['file1.txt', 'output/', '--up'];
|
|
454
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
455
|
-
expect(() => parseArgs(config)).toThrow('Missing value for option: up');
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
it('should throw unknown option when short flag does not match any alias', () => {
|
|
459
|
-
const configWithNoAlias: Config = {
|
|
460
|
-
...config,
|
|
461
|
-
options: {
|
|
462
|
-
...config.options,
|
|
463
|
-
noAliasOpt: {
|
|
464
|
-
type: 'boolean',
|
|
465
|
-
description: 'Option with no alias',
|
|
466
|
-
},
|
|
467
|
-
},
|
|
468
|
-
};
|
|
469
|
-
const args = ['file1.txt', 'output/', '-x', '-b', 'value'];
|
|
470
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', ...args]);
|
|
471
|
-
expect(() => parseArgs(configWithNoAlias)).toThrow('Unknown option: x');
|
|
472
|
-
});
|
|
473
|
-
|
|
474
|
-
it('should print usage with optional positional argument', () => {
|
|
475
|
-
const configWithOptional: Config = {
|
|
476
|
-
...config,
|
|
477
|
-
command: {
|
|
478
|
-
...config.command,
|
|
479
|
-
positional: [
|
|
480
|
-
{
|
|
481
|
-
name: 'inFile',
|
|
482
|
-
description: 'source files',
|
|
483
|
-
type: 'string',
|
|
484
|
-
required: false, // <-- optional positional
|
|
485
|
-
},
|
|
486
|
-
{
|
|
487
|
-
name: 'outDirectory',
|
|
488
|
-
description: 'destination directory',
|
|
489
|
-
required: true,
|
|
490
|
-
},
|
|
491
|
-
],
|
|
492
|
-
},
|
|
493
|
-
};
|
|
494
|
-
const spy = vi.spyOn(console, 'log').mockImplementation(() => {});
|
|
495
|
-
vi.spyOn(process, 'argv', 'get').mockReturnValue(['node', 'cli.js', '--help']);
|
|
496
|
-
try {
|
|
497
|
-
parseArgs(configWithOptional);
|
|
498
|
-
} catch {}
|
|
499
|
-
expect(spy).toHaveBeenCalledWith(expect.stringContaining('[inFile]'));
|
|
500
|
-
spy.mockRestore();
|
|
501
|
-
});
|
|
502
|
-
});
|