args-tokens 0.23.0 → 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/lib/resolver.d.ts CHANGED
@@ -1,3 +1,560 @@
1
- import "./parser-C6MbpZjd.js";
2
- import { ArgExplicitlyProvided, ArgResolveError, ArgResolveErrorType, ArgSchema, ArgValues, Args, ExtractOptionValue, FilterArgs, FilterPositionalArgs, ResolveArgValues, ResolveArgs, resolveArgs } from "./resolver-D64nGlCD.js";
1
+ import { ArgToken } from "./parser.js";
2
+
3
+ //#region src/resolver.d.ts
4
+ /**
5
+ * An argument schema definition for command-line argument parsing.
6
+ *
7
+ * This schema is similar to the schema of Node.js `util.parseArgs` but with extended features:
8
+ * - Additional `required` and `description` properties
9
+ * - Extended `type` support: 'string', 'boolean', 'number', 'enum', 'positional', 'custom'
10
+ * - Simplified `default` property (single type, not union types)
11
+ *
12
+ * @example
13
+ * Basic string argument:
14
+ * ```ts
15
+ * const schema: ArgSchema = {
16
+ * type: 'string',
17
+ * description: 'Server hostname',
18
+ * default: 'localhost'
19
+ * }
20
+ * ```
21
+ *
22
+ * @example
23
+ * Required number argument with alias:
24
+ * ```ts
25
+ * const schema: ArgSchema = {
26
+ * type: 'number',
27
+ * short: 'p',
28
+ * description: 'Port number to listen on',
29
+ * required: true
30
+ * }
31
+ * ```
32
+ *
33
+ * @example
34
+ * Enum argument with choices:
35
+ * ```ts
36
+ * const schema: ArgSchema = {
37
+ * type: 'enum',
38
+ * choices: ['info', 'warn', 'error'],
39
+ * description: 'Logging level',
40
+ * default: 'info'
41
+ * }
42
+ * ```
43
+ */
44
+ interface ArgSchema {
45
+ /**
46
+ * Type of the argument value.
47
+ *
48
+ * - `'string'`: Text value (default if not specified)
49
+ * - `'boolean'`: `true`/`false` flag (can be negatable with `--no-` prefix)
50
+ * - `'number'`: Numeric value (parsed as integer or float)
51
+ * - `'enum'`: One of predefined string values (requires `choices` property)
52
+ * - `'positional'`: Non-option argument by position
53
+ * - `'custom'`: Custom parsing with user-defined `parse` function
54
+ *
55
+ * @example
56
+ * Different argument types:
57
+ * ```ts
58
+ * {
59
+ * name: { type: 'string' }, // --name value
60
+ * verbose: { type: 'boolean' }, // --verbose or --no-verbose
61
+ * port: { type: 'number' }, // --port 3000
62
+ * level: { type: 'enum', choices: ['debug', 'info'] },
63
+ * file: { type: 'positional' }, // first positional arg
64
+ * config: { type: 'custom', parse: JSON.parse }
65
+ * }
66
+ * ```
67
+ */
68
+ type: 'string' | 'boolean' | 'number' | 'enum' | 'positional' | 'custom';
69
+ /**
70
+ * Single character alias for the long option name.
71
+ *
72
+ * As example, allows users to use `-x` instead of `--extended-option`.
73
+ * Only valid for non-positional argument types.
74
+ *
75
+ * @example
76
+ * Short alias usage:
77
+ * ```ts
78
+ * {
79
+ * verbose: {
80
+ * type: 'boolean',
81
+ * short: 'v' // Enables both --verbose and -v
82
+ * },
83
+ * port: {
84
+ * type: 'number',
85
+ * short: 'p' // Enables both --port 3000 and -p 3000
86
+ * }
87
+ * }
88
+ * ```
89
+ */
90
+ short?: string;
91
+ /**
92
+ * Human-readable description of the argument's purpose.
93
+ *
94
+ * Used for help text generation and documentation.
95
+ * Should be concise but descriptive enough to understand the argument's role.
96
+ *
97
+ * @example
98
+ * Descriptive help text:
99
+ * ```ts
100
+ * {
101
+ * config: {
102
+ * type: 'string',
103
+ * description: 'Path to configuration file'
104
+ * },
105
+ * timeout: {
106
+ * type: 'number',
107
+ * description: 'Request timeout in milliseconds'
108
+ * }
109
+ * }
110
+ * ```
111
+ */
112
+ description?: string;
113
+ /**
114
+ * Marks the argument as required.
115
+ *
116
+ * When `true`, the argument must be provided by the user.
117
+ * If missing, an `ArgResolveError` with type 'required' will be thrown.
118
+ *
119
+ * Note: Only `true` is allowed (not `false`) to make intent explicit.
120
+ *
121
+ * @example
122
+ * Required arguments:
123
+ * ```ts
124
+ * {
125
+ * input: {
126
+ * type: 'string',
127
+ * required: true, // Must be provided: --input file.txt
128
+ * description: 'Input file path'
129
+ * },
130
+ * source: {
131
+ * type: 'positional',
132
+ * required: true // First positional argument must exist
133
+ * }
134
+ * }
135
+ * ```
136
+ */
137
+ required?: true;
138
+ /**
139
+ * Allows the argument to accept multiple values.
140
+ *
141
+ * When `true`, the resolved value becomes an array.
142
+ * For options: can be specified multiple times (--tag foo --tag bar)
143
+ * For positional: collects remaining positional arguments
144
+ *
145
+ * Note: Only `true` is allowed (not `false`) to make intent explicit.
146
+ *
147
+ * @example
148
+ * Multiple values:
149
+ * ```ts
150
+ * {
151
+ * tags: {
152
+ * type: 'string',
153
+ * multiple: true, // --tags foo --tags bar → ['foo', 'bar']
154
+ * description: 'Tags to apply'
155
+ * },
156
+ * files: {
157
+ * type: 'positional',
158
+ * multiple: true // Collects all remaining positional args
159
+ * }
160
+ * }
161
+ * ```
162
+ */
163
+ multiple?: true;
164
+ /**
165
+ * Enables negation for boolean arguments using `--no-` prefix.
166
+ *
167
+ * When `true`, allows users to explicitly set the boolean to `false`
168
+ * using `--no-option-name`. When `false` or omitted, only positive
169
+ * form is available.
170
+ *
171
+ * Only applicable to `type: 'boolean'` arguments.
172
+ *
173
+ * @example
174
+ * Negatable boolean:
175
+ * ```ts
176
+ * {
177
+ * color: {
178
+ * type: 'boolean',
179
+ * negatable: true,
180
+ * default: true,
181
+ * description: 'Enable colorized output'
182
+ * }
183
+ * // Usage: --color (true), --no-color (false)
184
+ * }
185
+ * ```
186
+ */
187
+ negatable?: boolean;
188
+ /**
189
+ * Array of allowed string values for enum-type arguments.
190
+ *
191
+ * Required when `type: 'enum'`. The argument value must be one of these choices,
192
+ * otherwise an `ArgResolveError` with type 'type' will be thrown.
193
+ *
194
+ * Supports both mutable arrays and readonly arrays for type safety.
195
+ *
196
+ * @example
197
+ * Enum choices:
198
+ * ```ts
199
+ * {
200
+ * logLevel: {
201
+ * type: 'enum',
202
+ * choices: ['debug', 'info', 'warn', 'error'] as const,
203
+ * default: 'info',
204
+ * description: 'Logging verbosity level'
205
+ * },
206
+ * format: {
207
+ * type: 'enum',
208
+ * choices: ['json', 'yaml', 'toml'],
209
+ * description: 'Output format'
210
+ * }
211
+ * }
212
+ * ```
213
+ */
214
+ choices?: string[] | readonly string[];
215
+ /**
216
+ * Default value used when the argument is not provided.
217
+ *
218
+ * The type must match the argument's `type` property:
219
+ * - `string` type: string default
220
+ * - `boolean` type: boolean default
221
+ * - `number` type: number default
222
+ * - `enum` type: must be one of the `choices` values
223
+ * - `positional`/`custom` type: any appropriate default
224
+ *
225
+ * @example
226
+ * Default values by type:
227
+ * ```ts
228
+ * {
229
+ * host: {
230
+ * type: 'string',
231
+ * default: 'localhost' // string default
232
+ * },
233
+ * verbose: {
234
+ * type: 'boolean',
235
+ * default: false // boolean default
236
+ * },
237
+ * port: {
238
+ * type: 'number',
239
+ * default: 8080 // number default
240
+ * },
241
+ * level: {
242
+ * type: 'enum',
243
+ * choices: ['low', 'high'],
244
+ * default: 'low' // must be in choices
245
+ * }
246
+ * }
247
+ * ```
248
+ */
249
+ default?: string | boolean | number;
250
+ /**
251
+ * Converts the argument name from camelCase to kebab-case for CLI usage.
252
+ *
253
+ * When `true`, a property like `maxCount` becomes available as `--max-count`.
254
+ * This allows [CAC](https://github.com/cacjs/cac) user-friendly property names while maintaining CLI conventions.
255
+ *
256
+ * Can be overridden globally with `resolveArgs({ toKebab: true })`.
257
+ *
258
+ * Note: Only `true` is allowed (not `false`) to make intent explicit.
259
+ *
260
+ * @example
261
+ * Kebab-case conversion:
262
+ * ```ts
263
+ * {
264
+ * maxRetries: {
265
+ * type: 'number',
266
+ * toKebab: true, // Accessible as --max-retries
267
+ * description: 'Maximum retry attempts'
268
+ * },
269
+ * enableLogging: {
270
+ * type: 'boolean',
271
+ * toKebab: true // Accessible as --enable-logging
272
+ * }
273
+ * }
274
+ * ```
275
+ */
276
+ toKebab?: true;
277
+ /**
278
+ * Names of other options that conflict with this option.
279
+ *
280
+ * When this option is used together with any of the conflicting options,
281
+ * an `ArgResolveError` with type 'conflict' will be thrown.
282
+ *
283
+ * Conflicts only need to be defined on one side - if option A defines a conflict
284
+ * with option B, the conflict is automatically detected when both are used,
285
+ * regardless of whether B also defines a conflict with A.
286
+ *
287
+ * Supports both single option name or array of option names.
288
+ * Option names must match the property keys in the schema object exactly
289
+ * (no automatic conversion between camelCase and kebab-case).
290
+ *
291
+ * @example
292
+ * Single conflict (bidirectional definition):
293
+ * ```ts
294
+ * {
295
+ * summer: {
296
+ * type: 'boolean',
297
+ * conflicts: 'autumn' // Cannot use --summer with --autumn
298
+ * },
299
+ * autumn: {
300
+ * type: 'boolean',
301
+ * conflicts: 'summer' // Can define on both sides for clarity
302
+ * }
303
+ * }
304
+ * ```
305
+ *
306
+ * @example
307
+ * Single conflict (one-way definition):
308
+ * ```ts
309
+ * {
310
+ * summer: {
311
+ * type: 'boolean',
312
+ * conflicts: 'autumn' // Only defined on summer side
313
+ * },
314
+ * autumn: {
315
+ * type: 'boolean'
316
+ * // No conflicts defined, but still cannot use with --summer
317
+ * }
318
+ * }
319
+ * // Usage: --summer --autumn will throw error
320
+ * // Error: "Optional argument '--summer' conflicts with '--autumn'"
321
+ * ```
322
+ *
323
+ * @example
324
+ * Multiple conflicts:
325
+ * ```ts
326
+ * {
327
+ * port: {
328
+ * type: 'number',
329
+ * conflicts: ['socket', 'pipe'], // Cannot use with --socket or --pipe
330
+ * description: 'TCP port number'
331
+ * },
332
+ * socket: {
333
+ * type: 'string',
334
+ * conflicts: ['port', 'pipe'], // Cannot use with --port or --pipe
335
+ * description: 'Unix socket path'
336
+ * },
337
+ * pipe: {
338
+ * type: 'string',
339
+ * conflicts: ['port', 'socket'], // Cannot use with --port or --socket
340
+ * description: 'Named pipe path'
341
+ * }
342
+ * }
343
+ * // These three options are mutually exclusive
344
+ * ```
345
+ *
346
+ * @example
347
+ * With kebab-case conversion:
348
+ * ```ts
349
+ * {
350
+ * summerSeason: {
351
+ * type: 'boolean',
352
+ * toKebab: true, // Accessible as --summer-season
353
+ * conflicts: 'autumnSeason' // Must use property key, not CLI name
354
+ * },
355
+ * autumnSeason: {
356
+ * type: 'boolean',
357
+ * toKebab: true // Accessible as --autumn-season
358
+ * }
359
+ * }
360
+ * // Error: "Optional argument '--summer-season' conflicts with '--autumn-season'"
361
+ * ```
362
+ */
363
+ conflicts?: string | string[];
364
+ /**
365
+ * Custom parsing function for `type: 'custom'` arguments.
366
+ *
367
+ * Required when `type: 'custom'`. Receives the raw string value and must
368
+ * return the parsed result. Should throw an Error (or subclass) if parsing fails.
369
+ *
370
+ * The function's return type becomes the resolved argument type.
371
+ *
372
+ * @param value - Raw string value from command line
373
+ * @returns Parsed value of any type
374
+ * @throws Error or subclass when value is invalid
375
+ *
376
+ * @example
377
+ * Custom parsing functions:
378
+ * ```ts
379
+ * {
380
+ * config: {
381
+ * type: 'custom',
382
+ * parse: (value: string) => {
383
+ * try {
384
+ * return JSON.parse(value) // Parse JSON config
385
+ * } catch {
386
+ * throw new Error('Invalid JSON configuration')
387
+ * }
388
+ * },
389
+ * description: 'JSON configuration object'
390
+ * },
391
+ * date: {
392
+ * type: 'custom',
393
+ * parse: (value: string) => {
394
+ * const date = new Date(value)
395
+ * if (isNaN(date.getTime())) {
396
+ * throw new Error('Invalid date format')
397
+ * }
398
+ * return date
399
+ * }
400
+ * }
401
+ * }
402
+ * ```
403
+ */
404
+ parse?: (value: string) => any;
405
+ }
406
+ /**
407
+ * An object that contains {@link ArgSchema | argument schema}.
408
+ *
409
+ * This type is used to define the structure and validation rules for command line arguments.
410
+ */
411
+ interface Args {
412
+ [option: string]: ArgSchema;
413
+ }
414
+ /**
415
+ * An object that contains the values of the arguments.
416
+ *
417
+ * @typeParam T - {@link Args | Arguments} which is an object that defines the command line arguments.
418
+ */
419
+ type ArgValues<T> = T extends Args ? ResolveArgValues<T, { [Arg in keyof T]: ExtractOptionValue<T[Arg]> }> : {
420
+ [option: string]: string | boolean | number | (string | boolean | number)[] | undefined;
421
+ };
422
+ type IsFunction<T> = T extends ((...args: any[]) => any) ? true : false;
423
+ /**
424
+ * Extracts the value type from the argument schema.
425
+ *
426
+ * @typeParam A - {@link ArgSchema | Argument schema} which is an object that defines command line arguments.
427
+ *
428
+ * @internal
429
+ */
430
+ type ExtractOptionValue<A extends ArgSchema> = A['type'] extends 'string' ? ResolveOptionValue<A, string> : A['type'] extends 'boolean' ? ResolveOptionValue<A, boolean> : A['type'] extends 'number' ? ResolveOptionValue<A, number> : A['type'] extends 'positional' ? ResolveOptionValue<A, string> : A['type'] extends 'enum' ? A['choices'] extends string[] | readonly string[] ? ResolveOptionValue<A, A['choices'][number]> : never : A['type'] extends 'custom' ? IsFunction<A['parse']> extends true ? ResolveOptionValue<A, ReturnType<NonNullable<A['parse']>>> : never : ResolveOptionValue<A, string | boolean | number>;
431
+ type ResolveOptionValue<A extends ArgSchema, T> = A['multiple'] extends true ? T[] : T;
432
+ /**
433
+ * Resolved argument values.
434
+ *
435
+ * @typeParam A - {@link Arguments | Args} which is an object that defines the command line arguments.
436
+ * @typeParam V - Resolvable argument values.
437
+ *
438
+ * @internal
439
+ */
440
+ type ResolveArgValues<A extends Args, V extends Record<keyof A, unknown>> = { -readonly [Arg in keyof A]?: V[Arg] } & FilterArgs<A, V, 'default'> & FilterArgs<A, V, 'required'> & FilterPositionalArgs<A, V> extends infer P ? { [K in keyof P]: P[K] } : never;
441
+ /**
442
+ * Filters the arguments based on their default values.
443
+ *
444
+ * @typeParam A - {@link Args | Arguments}, which is an object that defines the command line arguments.
445
+ * @typeParam V - Resolvable argument values.
446
+ * @typeParam K - Key of the {@link ArgSchema | argument schema} to filter by.
447
+ *
448
+ * @internal
449
+ */
450
+ type FilterArgs<A extends Args, V extends Record<keyof A, unknown>, K extends keyof ArgSchema> = { [Arg in keyof A as A[Arg][K] extends {} ? Arg : never]: V[Arg] };
451
+ /**
452
+ * Filters positional arguments from the argument schema.
453
+ *
454
+ * @typeParam A - {@link Args | Arguments}, which is an object that defines the command line arguments.
455
+ * @typeParam V - Resolvable argument values.
456
+ *
457
+ * @internal
458
+ */
459
+ type FilterPositionalArgs<A extends Args, V extends Record<keyof A, unknown>> = { [Arg in keyof A as A[Arg]['type'] extends 'positional' ? Arg : never]: V[Arg] };
460
+ /**
461
+ * An arguments for {@link resolveArgs | resolve arguments}.
462
+ */
463
+ interface ResolveArgs {
464
+ /**
465
+ * Whether to group short arguments.
466
+ *
467
+ * @see guideline 5 in https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap12.html
468
+ *
469
+ * @default false
470
+ */
471
+ shortGrouping?: boolean;
472
+ /**
473
+ * Skip positional arguments index.
474
+ *
475
+ * @default -1
476
+ */
477
+ skipPositional?: number;
478
+ /**
479
+ * Whether to convert the argument name to kebab-case. This option is applied to all arguments as `toKebab: true`, if set to `true`.
480
+ *
481
+ * @default false
482
+ */
483
+ toKebab?: boolean;
484
+ }
485
+ /**
486
+ * Tracks which arguments were explicitly provided by the user.
487
+ *
488
+ * Each property indicates whether the corresponding argument was explicitly
489
+ * provided (true) or is using a default value or not provided (false).
490
+ *
491
+ * @typeParam A - {@link Args | Arguments}, which is an object that defines the command line arguments.
492
+ */
493
+ type ArgExplicitlyProvided<A extends Args> = { [K in keyof A]: boolean };
494
+ /**
495
+ * Resolve command line arguments.
496
+ *
497
+ * @typeParam A - {@link Args | Arguments}, which is an object that defines the command line arguments.
498
+ *
499
+ * @param args - An arguments that contains {@link ArgSchema | arguments schema}.
500
+ * @param tokens - An array of {@link ArgToken | tokens}.
501
+ * @param resolveArgs - An arguments that contains {@link ResolveArgs | resolve arguments}.
502
+ * @returns An object that contains the values of the arguments, positional arguments, rest arguments, {@link AggregateError | validation errors}, and explicit provision status.
503
+ *
504
+ * @example
505
+ * ```typescript
506
+ * // passed tokens: --port 3000
507
+ *
508
+ * const { values, explicit } = resolveArgs({
509
+ * port: {
510
+ * type: 'number',
511
+ * default: 8080
512
+ * },
513
+ * host: {
514
+ * type: 'string',
515
+ * default: 'localhost'
516
+ * }
517
+ * }, parsedTokens)
518
+ *
519
+ * values.port // 3000
520
+ * values.host // 'localhost'
521
+ *
522
+ * explicit.port // true (explicitly provided)
523
+ * explicit.host // false (not provided, fallback to default)
524
+ * ```
525
+ */
526
+ declare function resolveArgs<A extends Args>(args: A, tokens: ArgToken[], {
527
+ shortGrouping,
528
+ skipPositional,
529
+ toKebab
530
+ }?: ResolveArgs): {
531
+ values: ArgValues<A>;
532
+ positionals: string[];
533
+ rest: string[];
534
+ error: AggregateError | undefined;
535
+ explicit: ArgExplicitlyProvided<A>;
536
+ };
537
+ /**
538
+ * An error type for {@link ArgResolveError}.
539
+ */
540
+ type ArgResolveErrorType = 'type' | 'required' | 'conflict';
541
+ /**
542
+ * An error that occurs when resolving arguments.
543
+ * This error is thrown when the argument is not valid.
544
+ */
545
+ declare class ArgResolveError extends Error {
546
+ name: string;
547
+ schema: ArgSchema;
548
+ type: ArgResolveErrorType;
549
+ /**
550
+ * Create an `ArgResolveError` instance.
551
+ *
552
+ * @param message - the error message
553
+ * @param name - the name of the argument
554
+ * @param type - the type of the error, either 'type' or 'required'
555
+ * @param schema - the argument schema that caused the error
556
+ */
557
+ constructor(message: string, name: string, type: ArgResolveErrorType, schema: ArgSchema);
558
+ }
559
+ //#endregion
3
560
  export { ArgExplicitlyProvided, ArgResolveError, ArgResolveErrorType, ArgSchema, ArgValues, Args, ExtractOptionValue, FilterArgs, FilterPositionalArgs, ResolveArgValues, ResolveArgs, resolveArgs };