@alcyone-labs/arg-parser 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Nicolas Embleton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,584 @@
1
+ # ArgParser - Type-Safe Command Line Argument Parser
2
+
3
+ ArgParser is a powerful and flexible library for building command-line interfaces (CLIs) in TypeScript and JavaScript. It helps you define, parse, validate, and handle command-line arguments and sub-commands in a structured, type-safe way.
4
+
5
+ Whether you're building a simple script or a complex nested CLI application, ArgParser provides the tools to create robust and user-friendly interfaces.
6
+
7
+ ## TODOs
8
+
9
+ ### Features
10
+
11
+ - [] Publish as an open-source library
12
+ - [] Upgrade to Zod/V4
13
+ - [] Add support for locales / translations
14
+ - [] (potentially) support for async type function to enable more flexibility (but at the cost of a potentially much larger issue surface)
15
+ - [] (potentially) add support for fully typed parsed output, this has proven very challenging
16
+
17
+ ### (known) Bugs / DX improvement points
18
+
19
+ - [] When a flag with `flagOnly: false` is going to consume a value that appears like a valid flag from the set, raise the appropriate warning
20
+ - [] When a flag with `allowMultiple: false` and `flagOnly: true` is passed multiple times (regardless of the options, for example "-1" and later "--one", both being valid), raise the correct error
21
+
22
+ ## Features
23
+
24
+ - **Type Safety:** Define expected argument types (string, number, boolean, array, custom functions) and get type-safe parsed results.
25
+ - **Optionally Complex Dynamic Types** Provide a method to trigger arbitrary logic when a flag is encountered and return the output to the parsed flag.
26
+ - **Declarative API:** Configure your CLI structure, flags, and sub-commands using a clear, declarative syntax.
27
+ - **Automatic Help Generation:** Generate comprehensive and contextual help text based on your parser configuration.
28
+ - **Hierarchical Commands:** Easily define nested sub-commands to create complex command structures (e.g., `git commit`, `docker container ls`).
29
+ - **Handler Execution:** Associate handler functions with commands and have them executed automatically upon successful parsing (or manually control execution).
30
+ - **Validation:** Define custom validation rules for flag values.
31
+ - **Conditional Requirements:** Make flags mandatory based on the presence or values of other arguments.
32
+ - **Default Values:** Specify default values for flags if they are not provided on the command line.
33
+ - **Flag Inheritance:** Share common flags between parent and child commands with an intuitive inheritance mechanism.
34
+ - **Error Handling:** Built-in, user-friendly error reporting for common parsing issues, with an option to handle errors manually.
35
+ - **Debugging Tools:** Easily inspect your parser's configuration for complex setups.
36
+
37
+ ## Installation
38
+
39
+ You can install ArgParser using your preferred package manager:
40
+
41
+ ```bash
42
+ pnpm add @alcyone-labs/arg-parser
43
+ # or
44
+ npm install @alcyone-labs/arg-parser
45
+ # or
46
+ yarn add @alcyone-labs/arg-parser
47
+ # or
48
+ bun add @alcyone-labs/arg-parser
49
+ # or
50
+ deno install npm:@alcyone-labs/arg-parser
51
+ ```
52
+
53
+ ## Basic Usage
54
+
55
+ Here's a simple example demonstrating how to define flags and parse arguments:
56
+
57
+ ```typescript
58
+ import { ArgParser } from "@alcyone-labs/arg-parser";
59
+
60
+ const parser = new ArgParser({
61
+ appName: "Data Processor",
62
+ appCommandName: "data-proc", // Used in help text and error messages
63
+ description: "A tool for processing data phases",
64
+ // By default, if a handler is set, it will be executed after successful parsing.
65
+ // Set handler: () => { ... } here for a root command handler.
66
+ }).addFlags([
67
+ {
68
+ name: "phase",
69
+ options: ["--phase"],
70
+ type: String, // Use native types or typeof string equivalents ("string", "number", "boolean", etc.)
71
+ mandatory: true,
72
+ enum: ["chunking", "pairing", "analysis"],
73
+ description: "Processing phase to execute",
74
+ },
75
+ {
76
+ name: "batch",
77
+ options: ["-b", "--batch-number"],
78
+ type: "number",
79
+ mandatory: (args) => args.phase !== "analysis", // Mandatory based on another flag's value
80
+ defaultValue: 0,
81
+ description: "Batch number (required except for analysis phase)",
82
+ },
83
+ {
84
+ name: "verbose",
85
+ options: ["-v"],
86
+ flagOnly: true, // This flag does not expect a value
87
+ description: "Enable verbose logging",
88
+ },
89
+ ]);
90
+
91
+ // Parse command line arguments (excluding 'node' and script path)
92
+ // If parsing fails (e.g., missing mandatory flag), ArgParser handles the error
93
+ // by printing a message and exiting (process.exit(1)) by default.
94
+ const args = parser.parse(process.argv.slice(2));
95
+
96
+ // If parsing succeeds and no command handler was executed,
97
+ // execution continues here with the parsed args.
98
+ console.log("Parsing successful! Arguments:", args);
99
+
100
+ // Example of using parsed arguments:
101
+ if (args.phase === "chunking") {
102
+ if (args.verbose) {
103
+ console.debug("Starting the chunking phase...");
104
+ }
105
+ // Perform chunking logic...
106
+ }
107
+ ```
108
+
109
+ ## Core Concepts
110
+
111
+ ### Defining Flags
112
+
113
+ Flags are defined using the `.addFlag(flag)` method or by passing an array of flags as the second argument to the `ArgParser` constructor. Each flag is an object conforming to the `IFlag` interface:
114
+
115
+ ```typescript
116
+ interface IFlag {
117
+ name: string; // Internal name for accessing the value in parsed args
118
+ options: string[]; // Array of command-line options (e.g., ["-v", "--verbose"])
119
+ type:
120
+ | "string"
121
+ | "boolean"
122
+ | "number"
123
+ | "array"
124
+ | "object"
125
+ | ((value: string) => any)
126
+ | Constructor; // Expected type or a parsing function
127
+ description: string | string[]; // Text description for help output
128
+ mandatory?: boolean | ((args: TParsedArgs) => boolean); // Whether the flag is required, or a function that determines this
129
+ defaultValue?: any; // Default value if the flag is not provided
130
+ default?: any; // Alias for defaultValue
131
+ flagOnly?: boolean; // If true, the flag does not consume the next argument as its value (e.g., `--verbose`)
132
+ allowMultiple?: boolean; // If true, the flag can be provided multiple times (values are collected in an array)
133
+ enum?: any[]; // Array of allowed values. Parser validates input against this list.
134
+ validate?: (value: any) => boolean | string | void; // Custom validation function
135
+ required?: boolean | ((args: any) => boolean); // Alias for mandatory
136
+ }
137
+ ```
138
+
139
+ ### Type Handling and Validation
140
+
141
+ ArgParser handles type conversion automatically based on the `type` property. You can use standard string types (`"string"`, `"number"`, `"boolean"`, `"array"`, `"object`), native constructors (`String`, `Number`, `Boolean`, `Array`, `Object`), or provide a custom function:
142
+
143
+ ```typescript
144
+ .addFlag({
145
+ name: "count",
146
+ options: ["--count"],
147
+ type: Number, // Automatically converts value to a number
148
+ })
149
+ .addFlag({
150
+ name: "data",
151
+ options: ["--data"],
152
+ type: JSON.parse, // Use a function to parse complex types like JSON strings
153
+ description: "JSON data to process"
154
+ })
155
+ .addFlag({
156
+ name: "environment",
157
+ options: ["--env"],
158
+ type: "string",
159
+ enum: ["dev", "staging", "prod"], // Validate value against this list
160
+ description: "Deployment environment",
161
+ })
162
+ .addFlag({
163
+ name: "id",
164
+ options: ["--id"],
165
+ type: "string",
166
+ validate: (value) => /^[a-f0-9]+$/.test(value), // Custom validation function
167
+ description: "Hexadecimal ID",
168
+ })
169
+ .addFlag({
170
+ name: "config",
171
+ options: ["-c"],
172
+ allowMultiple: true,
173
+ type: path => require(path), // Load config from path (example)
174
+ description: "Load multiple configuration files"
175
+ })
176
+ ```
177
+
178
+ ### Mandatory Flags
179
+
180
+ Flags can be made mandatory using the `mandatory` property, or its alias "required". This can be a boolean or a function that receives the currently parsed arguments and returns a boolean.
181
+
182
+ ```typescript
183
+ .addFlag({
184
+ name: "input",
185
+ options: ["--in"],
186
+ type: String,
187
+ mandatory: true, // Always mandatory
188
+ description: "Input file path",
189
+ })
190
+ .addFlag({
191
+ name: "output",
192
+ options: ["--out"],
193
+ type: String,
194
+ mandatory: (args) => args.format === "json", // Mandatory only if --format is "json"
195
+ description: "Output file path (required for JSON output)",
196
+ })
197
+ ```
198
+
199
+ If a mandatory flag is missing and default error handling is enabled (`handleErrors: true`), the parser will print an error and exit.
200
+
201
+ ### Default Values
202
+
203
+ Set a `defaultValue` (or its alias `default`) for flags to provide a fallback value if the flag is not present in the arguments.
204
+
205
+ ```typescript
206
+ .addFlag({
207
+ name: "port",
208
+ options: ["-p", "--port"],
209
+ type: Number,
210
+ defaultValue: 3000, // Default port is 3000 if -p or --port is not used
211
+ description: "Server port",
212
+ })
213
+ ```
214
+
215
+ ### Flag-Only Flags
216
+
217
+ Flags that do not expect a value (like `--verbose` or `--force`) should have `flagOnly: true`. When `flagOnly` is false (the default), the parser expects the next argument to be the flag's value.
218
+
219
+ ```typescript
220
+ .addFlag({
221
+ name: "verbose",
222
+ options: ["-v"],
223
+ type: Boolean, // Typically boolean for flag-only flags
224
+ flagOnly: true,
225
+ description: "Enable verbose output",
226
+ })
227
+ ```
228
+
229
+ ### Alias Properties
230
+
231
+ For convenience, `ArgParser` supports aliases for some flag properties:
232
+
233
+ - `default` is an alias for `defaultValue`.
234
+ - `required` is an alias for `mandatory`.
235
+ If both the original property and its alias are provided, the original property (`defaultValue`, `mandatory`) takes precedence.
236
+
237
+ ## Hierarchical CLIs (Sub-Commands)
238
+
239
+ ArgParser excels at building CLIs with nested commands, like `git clone` or `docker build`.
240
+
241
+ ### Defining Sub-Commands
242
+
243
+ Define sub-commands using the `subCommands` option in the `ArgParser` constructor or the `.addSubCommand(subCommand)` method. Each sub-command requires a `name`, `description`, and a dedicated `ArgParser` instance for its own flags and nested sub-commands.
244
+
245
+ ```typescript
246
+ import {
247
+ ArgParser,
248
+ HandlerContext,
249
+ ISubCommand,
250
+ } from "@alcyone-labs/arg-parser";
251
+
252
+ const deployParser = new ArgParser().addFlags([
253
+ { name: "target", options: ["-t"], type: String, mandatory: true },
254
+ ]);
255
+
256
+ const monitorLogsParser = new ArgParser().addFlags([
257
+ { name: "follow", options: ["-f"], flagOnly: true, type: Boolean },
258
+ ]);
259
+
260
+ const monitorParser = new ArgParser().addSubCommand({
261
+ name: "logs",
262
+ description: "Show logs",
263
+ parser: monitorLogsParser,
264
+ handler: ({ args }) => {
265
+ console.log(`Showing logs... Follow: ${args.follow}`);
266
+ },
267
+ });
268
+
269
+ const cli = new ArgParser({
270
+ appName: "My CLI",
271
+ appCommandName: "my-cli",
272
+ description: "Manage application resources",
273
+ subCommands: [
274
+ {
275
+ name: "deploy",
276
+ description: "Deploy resources",
277
+ parser: deployParser,
278
+ handler: ({ args }) => {
279
+ console.log(`Deploying to ${args.target}`);
280
+ },
281
+ },
282
+ {
283
+ name: "monitor",
284
+ description: "Monitoring commands",
285
+ parser: monitorParser,
286
+ },
287
+ ],
288
+ });
289
+
290
+ // Example usage:
291
+ // my-cli deploy -t production
292
+ // my-cli monitor logs -f
293
+ ```
294
+
295
+ ### Handler Execution
296
+
297
+ A core feature is associating handler functions with commands. Handlers are functions (`(ctx: HandlerContext) => void`) that contain the logic to be executed when a specific command (root or sub-command) is successfully parsed and matched.
298
+
299
+ Handlers can be defined in the `ISubCommand` object or set/updated later using the `.setHandler()` method on the command's parser instance.
300
+
301
+ **By default, after successful parsing, ArgParser will execute the handler associated with the _final command_ matched in the argument chain.** For example, running `my-cli service start` will execute the handler for the `start` command, not `my-cli` or `service`.
302
+
303
+ If you need to parse arguments but _prevent_ handler execution, you can pass the `skipHandlers: true` option to the `parse()` method:
304
+
305
+ ```typescript
306
+ const args = parser.parse(process.argv.slice(2), { skipHandlers: true });
307
+ // Handlers will NOT be executed, you can inspect 'args' and decide what to do
308
+ ```
309
+
310
+ ### Handler Context
311
+
312
+ Handler functions receive a single argument, a `HandlerContext` object, containing information about the parsing result and the command chain:
313
+
314
+ ```typescript
315
+ type HandlerContext = {
316
+ args: TParsedArgs<any>; // Arguments parsed by and defined for the FINAL command's parser
317
+ parentArgs?: TParsedArgs<any>; // Combined arguments from PARENT parsers (less relevant with inheritParentFlags)
318
+ commandChain: string[]; // Array of command names from root to final command
319
+ };
320
+ ```
321
+
322
+ The `args` property is the most commonly used, containing flags and their values relevant to the handler's specific command. If `inheritParentFlags` is used, inherited flags appear directly in `args`.
323
+
324
+ ### Setting Handlers with `.setHandler()`
325
+
326
+ You can define or override a parser instance's handler after its creation:
327
+
328
+ ```typescript
329
+ const myCommandParser = new ArgParser().addFlags(/* ... */);
330
+
331
+ myCommandParser.setHandler((ctx) => {
332
+ console.log(`Executing handler for ${ctx.commandChain.join(" -> ")}`);
333
+ // ... command logic ...
334
+ });
335
+
336
+ // You can also retrieve a sub-parser and set its handler:
337
+ const subParser = cli.getSubCommand("deploy")?.parser;
338
+ if (subParser) {
339
+ subParser.setHandler((ctx) => {
340
+ console.log("Overridden deploy handler!");
341
+ // ... new deploy logic ...
342
+ });
343
+ }
344
+ ```
345
+
346
+ ### Accessing Sub-Parsers with `.getSubCommand()`
347
+
348
+ Use the `.getSubCommand(name)` method on a parser instance to retrieve the `ISubCommand` definition for a specific sub-command by name. This allows you to access its parser instance to set handlers, add flags dynamically, or inspect its configuration.
349
+
350
+ ```typescript
351
+ const deploySubCommand = cli.getSubCommand("deploy");
352
+ if (deploySubCommand) {
353
+ console.log(`Description of deploy command: ${deploySubCommand.description}`);
354
+ // Access the parser instance:
355
+ const deployParserInstance = deploySubCommand.parser;
356
+ // Add a flag specifically to the deploy command after initial setup:
357
+ deployParserInstance.addFlag({
358
+ name: "force",
359
+ options: ["--force"],
360
+ flagOnly: true,
361
+ type: Boolean,
362
+ });
363
+ }
364
+ ```
365
+
366
+ ### Flag Inheritance (`inheritParentFlags`)
367
+
368
+ Enable `inheritParentFlags: true` in a child parser's constructor options to automatically copy flags from its direct parent when added as a sub-command. This is useful for sharing common flags like `--verbose` across your CLI.
369
+
370
+ If a flag with the same name exists in both the parent and the child, the child's definition takes precedence. The built-in `--help` flag is never inherited.
371
+
372
+ ```typescript
373
+ const parentParser = new ArgParser().addFlags([
374
+ { name: "verbose", options: ["-v"], type: Boolean, flagOnly: true },
375
+ { name: "config", options: ["-c"], type: String }, // Common config flag
376
+ ]);
377
+
378
+ const childParser = new ArgParser({ inheritParentFlags: true }).addFlags([
379
+ { name: "local", options: ["-l"], type: String }, // Child-specific flag
380
+ { name: "config", options: ["--child-config"], type: Number }, // Override config flag
381
+ ]);
382
+
383
+ parentParser.addSubCommand({
384
+ name: "child",
385
+ description: "A child command",
386
+ parser: childParser,
387
+ });
388
+
389
+ // The 'child' parser now effectively has flags: --help, -v, -l, --child-config
390
+ // Running `parent child -v -l value --child-config 123` will parse all these flags.
391
+ ```
392
+
393
+ ## Automatic Help
394
+
395
+ ArgParser provides robust automatic help generation.
396
+
397
+ ### Global Help Flag (`--help`, `-h`)
398
+
399
+ A `--help` (and `-h`) flag is automatically added to every parser instance (root and sub-commands). When this flag is encountered during parsing:
400
+
401
+ 1. ArgParser stops processing arguments.
402
+ 2. Generates and prints the help text relevant to the current command/sub-command context.
403
+ 3. Exits the process with code 0.
404
+
405
+ This behavior is triggered automatically unless `skipHelpHandling: true` is passed to the `parse()` method.
406
+
407
+ ```bash
408
+ # Shows help for the root command
409
+ my-cli --help
410
+
411
+ # Shows help for the 'deploy' sub-command
412
+ my-cli deploy --help
413
+ ```
414
+
415
+ ### `helpText()` Method
416
+
417
+ You can manually generate the help text for any parser instance at any time using the `helpText()` method. This returns a string containing the formatted help output.
418
+
419
+ ```typescript
420
+ console.log(parser.helpText());
421
+ ```
422
+
423
+ ### Auto-Help on Empty Invocation
424
+
425
+ For the root command, if you invoke the script **without any arguments** and the root parser **does not have a handler defined**, ArgParser will automatically display the root help text and exit cleanly (code 0). This provides immediate guidance for users who just type the script name.
426
+
427
+ If the root parser _does_ have a handler, it's assumed that the handler will manage the empty invocation case, and auto-help will not trigger.
428
+
429
+ ## Error Handling
430
+
431
+ ArgParser includes built-in error handling for common parsing errors like missing mandatory flags, invalid types, or unknown commands.
432
+
433
+ By default (`handleErrors: true`):
434
+
435
+ 1. A descriptive, colored error message is printed to `stderr`.
436
+ 2. A suggestion to use `--help` is included, showing the correct command path.
437
+ 3. The process exits with status code 1.
438
+
439
+ ```typescript
440
+ // Example (assuming 'data-proc' is appCommandName and 'phase' is mandatory)
441
+ // Running `data-proc` would output:
442
+
443
+ // Error: Missing mandatory flags: phase
444
+ //
445
+ // Try 'data-proc --help' for usage details.
446
+ ```
447
+
448
+ You can disable this behavior by setting `handleErrors: false` in the `ArgParser` constructor options. When disabled, ArgParser will throw an `ArgParserError` exception on parsing errors, allowing you to catch and handle them programmatically.
449
+
450
+ ```typescript
451
+ import { ArgParser, ArgParserError } from "@alcyone-labs/arg-parser";
452
+
453
+ const parser = new ArgParser({
454
+ appCommandName: "my-app",
455
+ handleErrors: false, // Disable default handling
456
+ });
457
+
458
+ try {
459
+ const args = parser.parse(process.argv.slice(2));
460
+ // Process args if parsing succeeded
461
+ } catch (error) {
462
+ if (error instanceof ArgParserError) {
463
+ console.error(`\nCustom Parse Error: ${error.message}`);
464
+ // Implement custom logic (e.g., logging, different exit codes)
465
+ process.exit(1);
466
+ } else {
467
+ // Handle unexpected errors
468
+ console.error("An unexpected error occurred:", error);
469
+ process.exit(1);
470
+ }
471
+ }
472
+ ```
473
+
474
+ ## Debugging
475
+
476
+ The `printAll(filePath?: string)` method is useful for debugging complex parser configurations. It recursively outputs the structure, options, flags, and handlers of a parser instance and its sub-commands.
477
+
478
+ - `parser.printAll()`: Prints a colored, human-readable output to the console.
479
+ - `parser.printAll('./config.json')`: Writes the configuration as a pretty-printed JSON file.
480
+ - `parser.printAll('./config.log')`: Writes a plain text version to a file.
481
+
482
+ ```typescript
483
+ import { ArgParser } from "@alcyone-labs/arg-parser";
484
+
485
+ const parser = new ArgParser({ appName: "Debug App" })
486
+ .addFlags([
487
+ /* ... */
488
+ ])
489
+ .addSubCommand(/* ... */);
490
+
491
+ parser.printAll(); // Output to console
492
+ ```
493
+
494
+ ## API Reference
495
+
496
+ This section provides a quick overview of the main components. See the sections above for detailed explanations and examples.
497
+
498
+ ### `new ArgParser(options?, initialFlags?)`
499
+
500
+ Constructor for creating a parser instance.
501
+
502
+ - `options`: An object (`IArgParserParams`) configuring the parser.
503
+ - `appName?: string`: Display name.
504
+ - `appCommandName?: string`: Command name for help/errors.
505
+ - `description?: string`: Parser description.
506
+ - `handler?: (ctx: HandlerContext) => void`: Handler function for this parser.
507
+ - `subCommands?: ISubCommand[]`: Array of sub-command definitions.
508
+ - `handleErrors?: boolean`: Enable/disable default error handling (default: `true`).
509
+ - `throwForDuplicateFlags?: boolean`: Throw error for duplicate flags (default: `false`).
510
+ - `inheritParentFlags?: boolean`: Enable flag inheritance when this parser is a sub-command (default: `false`).
511
+ - `initialFlags`: Optional array of `IFlag` objects to add during initialization.
512
+
513
+ ### `parse(args, options?)`
514
+
515
+ Parses an array of command-line arguments.
516
+
517
+ - `args`: `string[]` - Array of arguments (usually `process.argv.slice(2)`).
518
+ - `options`: Optional object (`IParseOptions`).
519
+ - `skipHelpHandling?: boolean`: Prevents automatic help display/exit on `--help` (default: `false`).
520
+ - `skipHandlers?: boolean`: Prevents execution of any matched command handlers (default: `false`).
521
+ - Returns: `TParsedArgs & { $commandChain?: string[] }` - An object containing the parsed arguments and optionally the `$commandChain`. Throws `ArgParserError` if `handleErrors` is `false`.
522
+
523
+ ### `.addFlag(flag)`
524
+
525
+ Adds a single flag definition.
526
+
527
+ - `flag`: `IFlag` - The flag object.
528
+ - Returns: `this` for chaining.
529
+
530
+ ### `.addFlags(flags)`
531
+
532
+ Adds multiple flag definitions.
533
+
534
+ - `flags`: `IFlag[]` - Array of flag objects.
535
+ - Returns: `this` for chaining.
536
+
537
+ ### `.addSubCommand(subCommand)`
538
+
539
+ Adds a sub-command definition.
540
+
541
+ - `subCommand`: `ISubCommand` - The sub-command object.
542
+ - Returns: `this` for chaining.
543
+
544
+ ### `.setHandler(handler)`
545
+
546
+ Sets or overrides the handler function for this parser instance.
547
+
548
+ - `handler`: `(ctx: HandlerContext) => void` - The handler function.
549
+ - Returns: `this` for chaining.
550
+
551
+ ### `.getSubCommand(name)`
552
+
553
+ Retrieves a defined sub-command by name.
554
+
555
+ - `name`: `string` - The name of the sub-command.
556
+ - Returns: `ISubCommand | undefined` - The sub-command definition or `undefined` if not found.
557
+
558
+ ### `.hasFlag(name)`
559
+
560
+ Checks if a flag with the given name exists on this parser instance.
561
+
562
+ - `name`: `string` - The name of the flag.
563
+ - Returns: `boolean`.
564
+
565
+ ### `helpText()`
566
+
567
+ Generates the formatted help text for this parser instance.
568
+
569
+ - Returns: `string` - The generated help text.
570
+
571
+ ### `printAll(filePath?)`
572
+
573
+ Recursively prints the parser configuration.
574
+
575
+ - `filePath`: `string?` - Optional path to write output to file. `.json` extension saves as JSON.
576
+
577
+ ### Interfaces
578
+
579
+ - `IFlag`: Defines the structure of a command-line flag.
580
+ - `ISubCommand`: Defines the structure of a sub-command.
581
+ - `HandlerContext`: The object passed to handler functions.
582
+ - `IParseOptions`: Options for the `parse()` method.
583
+ - `IArgParserParams`: Options for the `ArgParser` constructor.
584
+ - `ArgParserError`: Custom error class thrown on parsing failures when `handleErrors` is `false`.