4.5 KiB
command
(no submodules)
Purpose
Command is the core routing primitive for @suaveplan/cli. It models a single CLI command that can carry options, positional arguments, and an action handler, or act as a router that delegates to named sub-commands. Every App is backed by a root Command.
The class exposes a fluent builder API: chain .description(), .option(), .argument(), .command(), and .action() calls before calling .execute() at runtime. Sub-commands are registered via .command(name) which returns the child Command, enabling identical fluent chaining for nested hierarchies.
Features
- Fluent builder:
.description(),.option(),.argument(),.action(),.command(),.alias(),.hidden(),.example() - Sub-command routing: first non-flag token in
argvis matched against registered names and aliases - Option parsing delegated to
parseArgs— inherits full flag semantics (boolean, string, number,--no-*, short flags,=syntax,--rest) - OTel span on every
execute()call: span namecli.command.execute, attributecli.commandset to the full qualified name CliError(CLI_CODES.COMMAND.NO_ACTION)when no action is registered and no sub-command is foundCliError(CLI_CODES.COMMAND.UNKNOWN_SUBCOMMAND)when an unknown first token is provided and sub-commands are registered- Automatic
--help/-hhandling: printshelpText()and returns without error helpText(parentName?)generates a formatted usage block with options and sub-command listing
Usage: Basic Example
import { Command } from "@suaveplan/cli/command/command";
const cmd = new Command("greet")
.description("Greet a user")
.option("--name <name>", "Name to greet", "World")
.action(async (ctx) => {
console.log(`Hello, ${ctx.options.name}!`);
});
await cmd.execute(["--name", "Alice"]);
// → Hello, Alice!
Usage: Advanced Example
import { Command } from "@suaveplan/cli/command/command";
const root = new Command("deploy")
.description("Deployment toolkit");
root
.command("up")
.description("Bring services up")
.option("--env <env>", "Target environment", "staging")
.action(async (ctx) => {
console.log(`Deploying to ${ctx.options.env}`);
});
root
.command("down")
.alias("d")
.description("Tear services down")
.action(async () => {
console.log("Tearing down...");
});
// Route: "deploy up --env production"
await root.execute(["up", "--env", "production"]);
// Route by alias: "deploy d"
await root.execute(["d"]);
API Reference
new Command(name: string)
Creates a new command with the given name.
.description(text: string): this
Sets the human-readable description shown in help text.
.option(flags: string, description?: string, defaultValue?: unknown): this
Registers an option. flags follows parseOptionFlags syntax: "--name <value>", "-v, --verbose".
.argument(spec: string, description?: string): this
Registers a positional argument. spec follows parseArgumentSpec syntax: "<file>", "[file]", "<files...>".
.action(fn: ActionFn): this
Sets the action handler. fn receives an ActionContext with options, args (positionals), rest, and command info.
.command(name: string): Command
Registers a named sub-command and returns it for further chaining.
.alias(name: string): this
Adds an alias for this command, recognised during routing.
.hidden(): this
Marks the command as hidden — it is excluded from help text listings.
.example(text: string): this
Adds an example line shown in help text.
.helpText(parentName?: string): string
Returns formatted multi-line help text including usage, options, sub-commands, and examples.
.getParserConfig(): ParserConfig
Returns the ParserConfig derived from registered options and arguments. Used internally by execute().
.execute(argv: string[], parentName?: string): Promise<void>
Parses argv, routes to sub-commands or calls the action. Wraps the execution in an OTel span. Throws CliError on routing or parse failures.
Implementation Notes
Sub-command alias resolution scans all registered sub-commands for an _aliases entry matching the first token. An OTel span covers the full execute() lifecycle including sub-command delegation — the span status is set to ERROR if any exception propagates. The --help / -h shortcut is handled before sub-command routing and before the action call, so it always works even if no action is registered.