49 lines
1.6 KiB
JavaScript
49 lines
1.6 KiB
JavaScript
// CLI dispatcher — recursively walks CLICommand tree and wires up yargs
|
|
import yargs from "yargs";
|
|
import { hideBin } from "yargs/helpers";
|
|
export class CLI {
|
|
prog;
|
|
description;
|
|
constructor(opts) {
|
|
this.prog = opts.prog;
|
|
this.description = opts.description;
|
|
}
|
|
registerCommand(y, CommandClass) {
|
|
const cmd = new CommandClass();
|
|
const subcommands = CommandClass._subcommands;
|
|
if (subcommands?.length) {
|
|
// Branch command with subcommands
|
|
y.command(cmd.name, cmd.help, (sub) => {
|
|
for (const Sub of subcommands) {
|
|
this.registerCommand(sub, Sub);
|
|
}
|
|
return sub.demandCommand(1, `Please specify a ${cmd.name} subcommand`);
|
|
}, () => { });
|
|
}
|
|
else {
|
|
// Leaf command
|
|
y.command(cmd.name, cmd.help, (sub) => cmd.addArguments(sub), async (args) => {
|
|
const code = await cmd.execute(args);
|
|
process.exit(code);
|
|
});
|
|
}
|
|
}
|
|
bootstrap(commands) {
|
|
const y = yargs(hideBin(process.argv))
|
|
.scriptName(this.prog)
|
|
.usage(`${this.description}\n\n$0 <command> [options]`)
|
|
.option("verbose", {
|
|
alias: "v",
|
|
type: "boolean",
|
|
description: "Enable verbose output",
|
|
default: false,
|
|
})
|
|
.demandCommand(1, "Please specify a command")
|
|
.strict()
|
|
.help();
|
|
for (const Cmd of commands) {
|
|
this.registerCommand(y, Cmd);
|
|
}
|
|
y.parse();
|
|
}
|
|
}
|