I’m trying to implement prompting users for missing required args/mandatory options.
I thought I could use a preSubcommand hook, change process.argv
with prompts, and then allow commander to parse the updated argv.
My hook gets executed before any exit however, After the complete of my hook’s callback, I will get this error: error: required option '--foo' not specified
.
It seems that parsing continues after the hook on the old process.argv.
For example my-cli subcommand --foo bar
will work fine.
my-cli subcommand
will prompt for foo
and push it to process.argv
inside the hook but then exit with the error above.
Any ideas? I tried to suppress this error with exitOverride
and re-calling parse
afterwards, but my callback is not being reached. Surrounding in try-catch doesn’t work either.
Here’s my code:
program
.name('cli')
.description('foo')
.version(version, '-v, --version')
.addCommand(sub)
.hook('preSubcommand', async (program, subcommand) => {
await promptForMissingArgs(program, subcommand);
console.log('here');
console.log(process.argv);
program.parse(process.argv); // called again with correct process.argv but still exits
})
.exitOverride((exitCode) => {
console.log(`Exiting with code ${exitCode.exitCode}`); // not reached
// if (exitCode.exitCode !== 0) {
// program.parse(process.argv);
// }
});
// parse command line arguments and execute command
try {
program.parse(process.argv);
} catch (error) {
console.log('here'); // doesn't reach here
console.error(error);
}
From the docs I see this: if the first arg is a subcommand call preSubcommand hooks pass remaining arguments to subcommand, and process same way
https://github.com/tj/commander.js/blob/HEAD/docs/parsing-and-hooks.md
Is it because my hook is async?
2
Answers
Instead of trying to change process.argv, I was able to set options during
preSubcommand
hook. I was not able to find a way to change argument values so I settled with optionsWith
promptForMissingArgs
implementation something like this:Commander does not support mutating the arguments to be parsed in the middle of parsing. Also, there isn’t an easy place to inject last-minute processing before the check for mandatory options.
What you can easily do is prompt for missing options without marking them as mandatory as such. A simple place to prompt is at the start of the action handler, but a hook may allow code reuse or separate your logic better. Here is an example with a hook in the spirit of your code.
(Disclaimer: I am a maintainer of Commander.)