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 CHANGED
@@ -8,14 +8,19 @@
8
8
 
9
9
  ## cli-nano
10
10
 
11
- Super small custom CLI similar to `Yargs` but much smaller, it uses a similar approach to NodeJS `parseArgs()` to create command-line tool (aka CLI). It is much more complete than NodeJS `parseArgs()` since it supports Positional Arguments, negated flags and also accepts both syntax `--camelCase` and/or `--kebab-case`.
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
- - Converts flags to camelCase
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: 'unicorns',
36
- description: 'Show a list of unicorns',
40
+ name: 'serve',
41
+ description: 'Start a server with the given options',
37
42
  positional: [
38
43
  {
39
- name: 'inputs',
40
- description: 'unicorn inputs',
44
+ name: 'input',
45
+ description: 'serving files or directory',
41
46
  type: 'string',
42
- variadic: true, // one or more inputs could be provided
47
+ variadic: true, // 1 or more
43
48
  required: true,
44
49
  },
45
50
  {
46
- name: 'output',
47
- description: 'output directory',
48
- type: 'string',
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 copied, but do not actually copy any files',
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
- bar: {
79
- alias: 'b',
87
+ display: {
88
+ alias: 'D',
80
89
  required: true,
81
- description: 'a required bar option',
90
+ description: 'a required display option',
82
91
  }
83
92
  },
84
93
  version: '0.1.6',
85
94
  };
86
95
 
87
- const argv = parseArgs(config);
88
- console.log(argv);
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
- unicorns --help
106
+ # Show help guide (created by reading CLI config)
107
+ serve --help
108
+
109
+ # Show version (when defined)
110
+ serve --version
96
111
 
97
- # Show version
98
- unicorns --version
112
+ # Uses default port 5000
113
+ serve dist/index.html
99
114
 
100
115
  # With required and optional positionals
101
- unicorns file1.txt file2.txt output/ -b value
116
+ serve index1.html index2.html 8080 -D value
102
117
 
103
118
  # With boolean and array options
104
- unicorns file1.txt output/ --dryRun --exclude pattern1 --exclude pattern2 -b value
119
+ serve index.html 7000 --dryRun --exclude pattern1 --exclude pattern2 -D value
105
120
 
106
121
  # With negated boolean
107
- unicorns file1.txt output/ --no-dryRun -b value
122
+ serve index.html 7000 --no-dryRun -D value
108
123
 
109
124
  # With short aliases
110
- unicorns file1.txt output/ -d -e pattern1 -e pattern2 -b value
125
+ serve index.html 7000 -d -e pattern1 -e pattern2 -D value
111
126
 
112
127
  # With number option
113
- unicorns file1.txt output/ --up 2 -b value
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.
@@ -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,CAoM7D"}
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 (!value) {
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, check for any missing required options
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
- console.log(`${padString(' -v, --version', 21)} ${padString('Show version number', 64)} [boolean]`);
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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"}
@@ -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: string;
36
+ version?: string;
32
37
  }
33
38
  //# sourceMappingURL=interfaces.d.ts.map
@@ -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,cAAc;IAC7B,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE;QACX,uEAAuE;QACvE,IAAI,EAAE,MAAM,CAAC;QACb,sCAAsC;QACtC,WAAW,EAAE,MAAM,CAAC;QACpB,8BAA8B;QAC9B,IAAI,CAAC,EAAE,QAAQ,CAAC;QAChB,6EAA6E;QAC7E,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,8DAA8D;QAC9D,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,EAAE,CAAC;CACL;AAED,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,cAAc,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACzC,OAAO,EAAE,MAAM,CAAC;CACjB"}
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cli-nano",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "description": "Mini command-line tool similar to `yargs` or `parseArgs` from Node.js that accepts positional arguments, flags and options.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
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 (!value) {
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, check for any missing required options
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
- console.log(`${padString(' -v, --version', 21)} ${padString('Show version number', 64)} [boolean]`);
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: string;
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
- });