JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 25927
  • Score
    100M100P100Q149745F
  • License Apache-2.0

minimum viable argument parser

Package Exports

  • minargs
  • minargs/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (minargs) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

minargs

minargs is an argument parser with minimal configuration & assumptions. Argument parsing can take many shapes but the explicit goals of this library are as follows:

Goals

  • no usage
  • no validation
  • no types or type cohersion
  • no regular expressions
  • no strictness
  • no dependencies
  • no information loss
  • minimal assumptions
  • minimal configuration
  • consistant results/format
  • 100% test coverage

Mantras

  • Bring Your Own Usage™️
  • Bring Your Own Validation™️

Installation

npm install minargs

minargs([argv][, options])

  • argv (Array)
    • Default: process.argv
    • The argument strings to parse

Options

  • alias (Object)
    • Default: none
    • Define shorts & aliases to map to a canonical argument
    • Note: only single character aliases can be parsed as "shorts" (read more in the F.A.Q. below)
  • positionalValues (Boolean)
    • Default: false
    • Define whether or not to use positionals that follow bare flag definitions as values
  • recursive (Boolean)
    • Default: false
    • Define whether or not to end parsing when a bare -- marker is found

Returned Values

{
  args: {},
  positionals: [],
  remainder: [],
  argv: []
}

args

  • An Object of canonical argument keys with corresponding Array of parsed String values
  • Examples:
    • --foo will return [""] (note the empty string by default)
    • --foo=bar will return ["bar"]
    • --foo bar will return ["bar"] when positionalValues is true
      • Notably, bar is treated as a positional & returned in positionals if positionalValues is false

positionals

  • An Array of parsed positional String values

remainder

  • An Array of String values the follow the first bare -- when recursive is false
  • Notably, this is useful for recursively parsing arguments or passing along args to other processes (read more in the F.A.Q. below)

argv

  • An Array of Objects with corresponding indexs mapping back to the original process.argv or provided Array
  • Objects also contain the value parsed & type (ie. "argument", "short", "positional" or "value")
  • The type "value" will only ever be defined -- in place of "positional" -- when positionalValues=true
  • Notably, this is useful for recreating the original String values or extending the capabilities of this information (ref. https://github.com/pkgjs/parseargs/issues/84)

Example Usage

Basic

$ basic.js - --foo=bar -- --baz
#!/usr/bin/env node

// basic.js
const { minargs } = require('minargs')
const { args, positionals, remainder, argv } = minargs()

args          // { "foo": ["bar"] }
positionals   // ["-"]
remainder     // ["--baz"]
argv          // [ { index: 0, type: 'argument', value: { name: "foo", value: "bar" } } ... ]

Handling existence

Toggle Example
$ exists.js --foo
#!/usr/bin/env node

// exists.js
const { minargs } = require('minargs')
const { args } = minargs()
if (args.foo) {
  // ...
}

Handling last value define

Toggle Example
$ last-definition-.js --foo
#!/usr/bin/env node

// exists.js
const { minargs } = require('minargs')
const { args } = minargs()
if (args.foo) {
  // ...
}

Handling unknown args

Toggle Example
$ unknown.js --baz

Handling extension

#!/usr/bin/env node

// unknown.js
const { minargs } = require('minargs')
const { args } = minargs()
const known = ['foo', 'bar']
const unknown = Object.keys(args).filter(arg => !known.includes(arg))
if (unknown.length > 0) {
  console.error('unknown flags passed:', unknown)
  // stop the process & set an `exitCode` appropriately
  process.exit(1)
}

// ...

Handling validation

Toggle Example
$ validate.js --num=1337
#!/usr/bin/env node

// validate.js
const { minargs } = require('minargs')
const { args } = minargs()
const usage = {
  num: {
    validate: (value) => {
      if (!isNaN(value)) {
        return Number(value)
      }
      throw Error('Validation error!')
    }
  },
  force: {
    validate: (value) => {
      if (~['true','false'].indexOf(value.toLowerCase())) {
        return Boolean(value)
      }
      throw Error('Validation error!')
    }
  }
}

Object.keys(args).filter(name => args[name]).map(name => {
  usage[name].validate(args[name].pop())
})

// ...

Handling recursive parsing

Toggle Example
$ recursive-parse.js
#!/usr/bin/env node

// recursive-parse.js
const { minargs } = require('minargs')
console.log(minargs({ recursive: true }))
// ...

Handling sub process

Toggle Example
$ mkdir.js ./path/to/new/dir/ --force --verbose --parents
#!/usr/bin/env node

// mkdir.js
const known = ['force']
const { args, positionals } = minargs()
const cmd = (args.force) ? 'sudo mkdir' : 'mkdir'
const _args = Object.keys(flags).filter(f => known[f])

process('child_process').spawnSync(cmd, [..._args, ...positionals])

Handling robust options & usage

Toggle Example
$ usage.js -h
#!/usr/bin/env node

// usage.js
const { minargs } = require('minargs')
const usage = {
  help: {
    short: 'h',
    usage: 'cli --help',
    description: 'Print usage information'
  }
  force: {
    short: 'f',
    usage: 'cli --force',
    description: 'Run this cli tool with no restrictions'
  }
}
const opts = {
  alias: Object.keys(usage).filter(arg => usage[arg].short).reduce((o, k) => {
    o[usage[k].short] = k
    return o
  }, {})
}
const { args } = minargs(opts)

if (args.help) {
  Object.keys(usage).map(name => {
    let short = usage[name].short ? `-${usage[name].short}, ` : ''
    let row = [`  ${short}--${name}`, usage[name].usage, usage[name].description]
    console.log.apply(this, fill(columns, row))
  })
}

/// ...

F.A.Q.

Why isn't strictness supported?

  • Strictness is a function of usage. By default, minargs does not assume anything about "known" or "unknown" arguments or their intended values (ex. defaults/types). Usage examples above show how you can quickly & easily utilize minargs as the backbone for an application which does enforce strictness/validation & more.

Are shorts supported?

  • Yes.
  • Individual (ex. -a) & combined (ex. -aCdeFg) shorts are supported
  • -a=b will capture & return "b" as a value
  • -a b will capture & return "b" as a value if positionalValues is true

Are multiples supported?

  • Yes.
  • By default multiple definitions of the same argument will get consolidated into a single arg entry with a corresponding Array of String values
  • Getting the last defined value of an argument is as simple as running .pop() on the Array (ex. args.foo.pop())

What is an alias?

  • An alias can be any other string that maps to a canonical option; this includes single characters which will map shorts to a long-form (ex. alias: { f: foo } will parse -f as { args: { "foo": [""] } })

Is cmd --foo=bar baz the same as cmd baz --foo=bar?

  • Sort of.
  • The returned argv Array will change to reflect the differing positions of the arguments & positionals BUT args & positionals will remain consistent

Is value validation or type cohersion supported?

  • No.

Are usage errors supported?

  • No.

Does --no-foo coerce to --foo=false?

  • No.
  • --no-foo will parse to { args: { "no-foo": [""] } } & --foo-false to { args: { "no-foo": ["false"] } } respectively

Is --foo the same as --foo=true?

  • No.
  • --foo will parse to { args: { "foo": [""] } } & --foo=true to { args: { "foo": ["true"] } } respectively

Are environment variables supported?

  • No.

Does -- signal the end of flags/options?

  • Yes.
  • Any arguments following a bare -- definition will be returned in remainder.

Is a value stored to represent the existence of --?

  • No.
  • The only way to determine if -- was present & there were arguments passed afterward is to check the value of remainder

Is - a positional?

  • Yes.
  • A bare - is treated as & returned in positionals

Is -bar the same as --bar?

Is ---foo the same as --foo?

  • No.
  • ---foo returns { args: "-foo": [""] }
  • --foo returns { args: { "foo": [""] }

Is foo=bar a positional?

  • Yes.

Are negative numbers supported as positional values?

  • No.
  • minargs aligns with the POSIX Argument Syntax here (ie. "Arguments are options if they begin with a hyphen delimiter")
  • --number -2 will be parsed as { args: { "number": [""], "2": [""] } }
  • You will have to use explicit value setting to make this association (ex. --number=-2) & may further require validation/type coercion to determine if the value is a Number (as is shown in the usage examples above)

CLI

minargs has a companion CLI library: @minargs/cli

Installation

# install package globally & call bin...
npm install @minargs/cli -g && minargs

# or, use `npx` to install & call bin...
npx -- @minargs/cli "<args>" [<options>]

Usage

minargs "<args>" [<options>]

Options & more....

To learn more, check out the @minargs/cli GitHub repository or package page