yargs 10 Released

wow, I just noticed it’s been over a year since I wrote about a release of yargs. I’m excited about yargs@10 and I hope you’ll find it’s been worth the wait.

Commands are my favorite feature in yargs, they let you quickly hammer-out a CLI-application addressing both the problem of flow-control and human-readable help output:

  require('yargs')
  .command('append <w1> <w2>', 'append two strings', (yargs) => {}, (argv) => {
    console.log(argv.w1 + argv.w2)
  })
  .command('add <n1> <n2>', 'add two numbers', (yargs) => {}, (argv) => {
    console.log(argv.n1 + argv.n2)
  })
  .argv

Even though I love the feature, I had a couple major beefs with the API:

  • I like the positional argument DSL (<foo>, [bar], etc.), but positional arguments were missing many of the features available to flag arguments: you couldn’t set their type, configure a coerce method, etc.
  • there was a major disconnect between how you described the root-level entry-point to your application and the subcommands that your application accepts. .usage() hadn’t ever been updated to reflect a world in-which commands exist.

The goal of yargs@10 was to address the above issues.

.positional(<name>, <options>)

The new .positional() method allows you to provide the same parsing hints for positional arguments that you could already provide for flag arguments. Let’s look at an updated version of our example application:

  require('yargs')
  .command('append <w1> <w2>', 'append two strings', (yargs) => {
    yargs.positional('w1', {
      describe: 'the left-hand word',
      type: 'string'
    }).positional('w2', {
      describe: 'the right-hand word',
      type: 'string'
    })
  }, (argv) => {
    console.log(argv.w1 + argv.w2)
  })
  .command('add <n1> <n2>', 'add two numbers', (yargs) => {
    yargs.positional('n1', {
      describe: 'the left-hand number',
      type: 'number'
    }).positional('n2', {
      describe: 'the right-hand number',
      type: 'number'
    })
  }, (argv) => {
    console.log(argv.n1 + argv.n2)
  })
  .argv

To provide parsing hints for positional arguments, simply use the method .positional() in your command’s builder function. Positional arguments now go through the same parser that parses flag arguments and behavior will be identical.

.usage(<cmd>, [description], [builder], [handler])

If you provide more than one argument to the .usage() method, .usage() now acts as an alias for a default command. This allows you to configure a command that runs as the main entry-point to your application.

Let’s look at an example:

  require('yargs')
  .usage('$0 <name>', 'say hello', (yargs) => {
    yargs.positional('name', {
      describe: 'the person to say hello to',
      type: 'string'
    })
  }, (argv) => {
    console.info(`hello ${argv.name}`)
  })
  .argv

You can now use the same powerful command DSL for describing the root-entry point to your application as you use for subcommands!

Upgrading

There have been a couple breaking changes in this release:

  • .usage() previously accepted an object as a second argument, treating this as an alias for .option([obj]).
  • the API for defining hidden options has been made more explicit; rather than a falsy description representing a hidden option, the configuration value hidden: true should be set.
  • help is now only shown if help is the last positional argument.

For a complete list of changes, see our CHANGELOG.md

I hope you like what yargs@10 has to offer,

Ben.

« View More Posts