In my 'foo' sub command file (Eg. pm-foo.js) how do I get hold of the options passed?
pm.js:
...
program
.version('0.0.1')
.command('foo [name]', 'desc' {a:'b'})
.parse(process.argv);
I tried passing parameters after the description parameter, but how do you get hold of them in the pm-foo.js file? I tried printing out name in pm-foo.js too. Any help is appreciated.
Commander passes the remaining arguments to a child process running the sub command script. You can access them with process.argv
These are just the remaining arguments on the command-line. How do I get a hold of extra arguments passed after the description argument of command()? In pm-foo.js if I print out process.argv I get ['node', PATH_TO_PM_FOO]. No {'a': 'b'}.
Commander.command() doesn't actually call a subcommand. It just defines one.
.version('0.0.1')
.command('foo [name]', 'desc' {a:'b'})
.parse(process.argv);
is defining a subcommand called foo. The [name] argument is just for the help message. You're also missing a comma in your example. As for the options the only options mentioned in the docs are opts.noHelp and opts.isDefault, no other arguments are passed.
Your pm-foo.js file might look like this:
var subCommand = require('commander');
subCommand
.option('-a, --an-option')
.parse(process.argv);
var args = subCommand.args.slice(2);
var name = args.pop();
if (!name) // ...
if(!subCommand.anOption) // ...
the main options are not forwarded to the subcommands for example:
_pm.js_
program
.name('cli')
.option('-k, --key <apikey>')
_pm-foo.js_
program
.command('list')
.option('-l, --limit')
.action(options => {
console.log(program);
console.log(options);
console.log(program.options);
console.log(program.apikey);
})
cli -k 'ABCD' list
is possible to get the apikey from the "root" command?
Not sure how to comment on this with the exact syntax being use above, but I just ran into a similar issue. apikey wouldn't be property of options.apikey it would be nested in the parent property options.parent.apikey. Allows you to inherit options from the parent instead of repeating them it looks like. Logging out options will show the data structure
@PaulBeaudet can you share a working example? because in my parent property there are no root options, btw the code above is pseudo code, actually is not working it should be like in the example:
pm.js
program
.name('cli')
.option('-k, --key <apikey>')
.command('foo', 'a sub command')
.parse(process.argv)
pm.foo.js
program
.option('-l, --limit')
.parse(process.argv)
console.log(program)
console.log(program.parent) // undefined
In my previous message I did a wrong mesh up of something i'm doing which was very long and I cutted and pasted parts without verify if it was really working, actually the my real code is more like this below:
_pm.js_
program
.option('-k, --key', 'the api key')
.command('section', 'The section subcommands')
_pm-section.js_
program
.command('list', 'list section data')
.option('-l, --limit', 'some limit')
.action(options => {
console.log(options)
})
and than I use like: pm -k ABCD section list --limit 50
Looks like two sub commands there vs the parent and the sub like I just used https://github.com/PaulBeaudet/jitployClient/blob/master/jitploy.js#L227-L244
edit: Actually those links are relative to master, bad idea to post like that
cli.program
.usage('[options] <file ...>')
.option('-k, --key <key>', 'key to unlock service config')
.option('-t, --token <token>', 'config token to use service')
.option('-r, --repo <repo>', 'repo name')
.option('-s, --server <server>', 'jitploy server to connect to')
.option('-e, --env <env>', 'unlocks for x enviroment')
.action(cli.run);
cli.program
.command('lock')
.usage('[options] <directory ...>')
.description('encrypts configuration, on templates a decrypted file if its non existent')
.action(function encryptIt(dir, options){config.lock(dir, options.parent.env);});
That's as snippet of working code
@PaulBeaudet actually my issue is regarding the "git-style" subcommands, that's why your code is working, is not using it, see the two file names: _pm.js_ _pm-foo.js_ are two different files like in this example
but.. I can confirm the normal behavior (as you posted) it's working correctly
Git-style executable (sub)commands are spawned separate commands. There is not a direct way from the subcommand to get at options that were declared on the outer program, and they are not passed to the subcommand as arguments. (You do have access to the parent command options if you instead use an action handler to implement the command.)
An idea for passing the parent options implicitly is to add them as process environment variables.
pm.js
const program = require("commander");
program
.option('-k, --key <apikey>')
.on("option:key", (apikey) => {
process.env["key"] = apikey;
})
.command('foo', 'a sub command')
.parse(process.argv);
pm-foo.js
console.log(`key is ${process.env["key"]}`);
$ node pm.js foo
key is undefined
$ node pm.js -k hello foo
key is hello
Hello guys, i don't know if this can help but, after i upgraded the commander from my project i was not able to access subcommand options anymore, after digging the source i reached to this commit. Rolling back to a commit before that the code works just fine.
Any idea why?
Thanks.
@lucasdiedrich
That commit was in PR #1048, and described in PR #1030.
Are you using git-style executable sub-commands, or a .action handler? If you are using an action handler then your problem is not related to this issue, in which case open a new issue with some details about what your code looks like that was affected by the change.
@gitoutthere wondered about a hook with an opportunity to manipulate the arguments before calling the subcommand in #1137
@gitoutthere wondered about a hook with an opportunity to manipulate the arguments before calling the subcommand in #1137
I managed to make it work within my main command_file.js using below, it parses all the parameters from file and passes it to the sub-command file. Note that I include '--' below and not in the parameters file:
if(program.input) {
let inputArgs = []
try {
let inputArgsObj = JSON.parse(fs.readFileSync(program.input,'utf8'))
for (let key in inputArgsObj) {
// push parameters (key) and their values into inputArgs (process.argv) format
inputArgs.push('--'+key, (typeof inputArgsObj[key] === 'object') ? JSON.stringify(inputArgsObj[key]) : inputArgsObj[key])
}
// place inputArgs into process.argv at position 4. Position 1,2 and 3 is ignored by .parse()
process.argv.splice(3, 0, ...inputArgs)
} catch(error) {
console.error(error.message)
process.exit(1)
}
}
This issue has not seen a lot of activity over the years. It isn't likely to get acted on due to this report.
On a somewhat related note, see also: #1229
Feel free to open a new issue if it comes up again, with new information and renewed interest.
Thank you for your contributions.
Most helpful comment
the main options are not forwarded to the subcommands for example:
_pm.js_
_pm-foo.js_
cli -k 'ABCD' listis possible to get the apikey from the "root" command?