Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass arguments to executable sub-commands #1137

Closed
gitoutthere opened this issue Jan 2, 2020 · 7 comments
Closed

Pass arguments to executable sub-commands #1137

gitoutthere opened this issue Jan 2, 2020 · 7 comments

Comments

@gitoutthere
Copy link

gitoutthere commented Jan 2, 2020

I am implementing pass parameters by json file allowing users to provide -i and path to a json file which has options and their values. I have 10 sub-commands and I want this parameters from json file to be passed to sub-command file to be utilised.

I have currently achieved this by putting content of input file in process.env.inputFIle and within each sub-command file I unpack this var and shove it inside process.argv

funApp.js

program.version('2.1')
.command('add' [parameters], ' adding stuff')
.command('update' [parameters], ' update stuff')
.command('remove' [parameters], ' remove stuff')
[... etc]
.option('-i, --input <value>',' json param file')
[...]
program.on('option:input', function(inputFile) {
  const fileData = JSON.parse(fs.readFileSync(inputFile,'utf8'))
// Somehow pass these args to the funApp-add.js as args?!
})

That way my CLI could be funApp add -i params.json --overrideArg value --newArg value

@shadowspawn
Copy link
Collaborator

The open issue is: #563

I had the same idea as you, passing context using environment variables: #563 (comment)

You could perhaps treat environment variables as a first class source of options, like:
#1135 (comment)

@gitoutthere
Copy link
Author

Thank you for the prompt reply. Funny enough, I reviewed all those links before I posted mine. I am not fan of using env var as default value on .options since I would have less control (if env is not set and other issues)

I tried to insert the file arguments into rawArgs and other vars I thought relevant, I was hoping they get passed into subcommand as argv same way CLI options values gets passed to sub-commands.

Perhaps I can ask my question differently, can I manipulate the arguments before it is passed to the sub-command file? In my above example, can do manipulate values of --overrideArg and --newArg before they are passed to FunApp-add.js as argv?

@shadowspawn
Copy link
Collaborator

Good question. There is not currently support for modifying arguments before (for) passing to subcommands.

@evg656e
Copy link

evg656e commented Jan 19, 2020

I ran into the somewhat similar problem.

The use case is to have common options (e.g. verbosity level, config path etc.) for the subcommands. I found some workarounds, e.g. to create option setter function and call this function for each subcommand, or to use .on('option: handler and store common options in global variable, but all of these is quite messy.

I would like that options set before first command to be pass through somehow:

program
  // common options for all subcommands
  .option('-v, --verbose', 'show more info')
  .option('-c, --config <path>', 'path to config file')
  // subcommands
  .command('encode <path>')
  .option('-p, --preset <name>', 'preset name') // command specific options
  .action((path, opts, commonOpts) => {
    // const { preset } = opts;
    // const { verbose, config } = commonOpts;
  });

@shadowspawn
Copy link
Collaborator

shadowspawn commented Jan 20, 2020

@evg656e
If you are using an action handler with your command, you can access the global options on the program object, or from within an action handler on .parent on the passed command.

const commander = require('commander');

const program = new commander.Command();

program
  // common options for all subcommands
  .option('-v, --verbose', 'show more info')
  .option('-c, --config <path>', 'path to config file')
  // subcommands
  .command('encode <path>')
  .option('-p, --preset <name>', 'preset name') // command specific options
  .action((path, cmd) => {
    const { preset } = cmd;
    console.log(program.verbose, program.config);
    console.log(cmd.parent.verbose, cmd.parent.config);
  });

program.parse(process.argv);
% node index.js --verbose --config ccc encode --preset ppp bar
true ccc
true ccc

On a related note, @a-fas made a great enhancement suggestion to make it easier to get combined options of command and parent objects in future:
#1024 (comment)

@evg656e
Copy link

evg656e commented Jan 20, 2020

Thanks, that what i've been looking for.

@shadowspawn shadowspawn changed the title Pass arguments to sub-commands Pass arguments to executable sub-commands Jan 29, 2020
@shadowspawn
Copy link
Collaborator

Closing in favour of #563

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants