Search code examples
javascriptnode.jscommand-linecommand-line-argumentsyargs

"yargs" won't trigger any command of a script


I have a NodeJs script in which I need parse command line arguments.

I've written this code:

import yargs from "yargs";
import { hideBin } from 'yargs/helpers';

  //....
  yargs(hideBin(process.argv)).command('--add-item <val1> <val2>', 'desc', {},
      async (argv) => {
        const { val1, val2 } = argv;
        if (val1 && val2) {
          /**/
        } else {
          console.log('Wrong command line arguments');
        }
    })
    .command('--print <val1>', 'description 123', {},
      async (argv) => {
        const { val1 } = argv;
        if (val1) {
            /**/
        } else {
           console.log('Wrong command line arguments');
        }
    })
    .demandCommand(1, 'You need to provide at least one command')
    .help()
    .alias('help', 'h')
    .parse();
    //......

Then I'll run it:

$ node my_script.js --add-item 1 2
// or
// $ node my_script.js --print 33

And will always get:

my_script.js <command>

Commands:
my_script.js --add-item <val1> <val2>
// ...........

That is, it'll show the help info; none of the commands will get triggered.

the version is 17.x

What's the matter?

update #1

I've removed 2 dashes:

.command('add-item <val1> <val2>', 'desc', {},

Yet, it won't work:

 $ node my_script.js add-item --val1 3 --val2 55
 // or 
 // $ node my_script.js add-item  3  55

===>

  (1) Not enough non-option arguments: got 0, need at least 2
  (2) (silence)

Solution

  • .command('add-item <val1> <val2>' means, "A command named add-item that has 2 required arguments". Arguments are plain text, not flags.

    If you run it like:

    node my_script.js 123 456
    

    argv will be:

    {
      _: [ 'add-item' ],
      '$0': 'my_script.js',
      val1: 123,
      val2: 456,
    }
    

    Any additional flags will also be put in argv, e.g.

    node my_script.js add-item 123 456 --val3=789 --val4=whatever
    

    argv will be:

    {
      _: [ 'add-item' ],
      '$0': 'my_script.js',
      val1: 123,
      val2: 456,
      val3: 789,
      val4: 'whatever',
    }
    

    If instead you want val1 and val2 to be flags, don't make them part of the command:

    import yargs from 'yargs'
    import { hideBin } from 'yargs/helpers'
    
    void yargs(hideBin(process.argv))
      .command(
        'add-item',
        'desc',
        {
          val1: {
            demand: true,
            desc: 'the first value',
            type: 'string',
          },
          val2: {
            demand: true,
            desc: 'the second value',
            type: 'number',
          },
        },
        async (argv) => {
          console.log('***** argv:', argv)
        },
      )
      .demandCommand(1, 'You need to provide at least one command')
      .help()
      .alias('help', 'h')
      .parse()
    

    Then you can call it like:

    node my_script.js add-item --val1=3 --val2=55
    

    and argv will be:

    {
      _: ['add-item'],
      $0: 'my_script.js',
      val1: 3,
      val2: 55,
    }