Dynamically create subcommands with options using Commander.js

639 views Asked by At

I am trying to create a CLI that can dynamically create subcommands with options. I have a main program named 'dashboard'. I want to create 'login' and a 'logout' subcommands that have options. I can't seem to get the subcommand options to run. It exits the code, saying the option doesn't exist. Ideally using the switch case, that would be the only place I would need to change If I wanted to add more commands. How can I create this dynamically?

I've tried using the .hook() on the main command to add options but it hasn't worked for me. I've tried creating a separate executable file, doesn't work. This is what I have so far

// main command
const program = new Command();

  program
    .name("dashboard")
    .description("CLI")
    .option("-d, --debug", "outputs extra debugging", false)
    .hook("preSubcommand", (commandObj) => {
      if (commandObj.args[1] === "login") {
        program.addOption(new Option("-e, --email")); // this doesn't work
      }
    });

  program.parse(process.argv);

//subcommands
 const commander = program.command("dashboard");
  const subcommand = program.args[1];

  try {
    let func: any;
    let description: string;
    let option: any;

    switch (subcommand) {
      case "login":
        description = "Logging you in!";
        func = (await import("./commands/login.js")).default;
        option = "-e, --email";
        break;
      case "logout":
        description = "Logging you out";
        func = (await import("./commands/logout.js")).default;
        break;
      default:
        description = "";
        func = null;
        break;
    }


    commander
      .command(subcommand)
      .on("command:login", () => console.log("Does this work?")) // No, it doesn't
      .hook("preSubcommand", () => {
        if (subcommand === "login") {
          console.log("What about this?"); // Still no
        }
      });
      .description(description)
      .option(option) // Tried adding the option from the switch case here, doesn't work
      .action(async (arg, option) => {
        console.log(" ~ file: index.ts:128 ~ .action ~ option:", option);
        console.log("test");
      await func(client);
    });
    console.log(" ~ file: index.ts:131 ~ main ~ commander:", commander.opts());
  } catch (err: unknown) {
    console.log(err);
  }
  program.parse();

When I run the command dashboard login -e, I get an error:

error: unknown option '-e'
 ELIFECYCLE  Command failed with exit code 1.

It will run the subcommand if there is not option given, so just dashboard login works fine. Otherwise, it throws that error above.

0

There are 0 answers