
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@ashnazg/args
Advanced tools
I wrote this library because I like the gnu+posix style of the gnu/linux ecosystem, and I'm not interested in a parser that speaks --name val instead of --name=val. I also expect posix flags to be
clumpable: I'd rather write -abc than -a -b -c.
var args = require('@ashnazg/args');
args.help.summary = 'SUMMARY TEXT';
args.help.noun = 'FISH';
args.define({gnu: 'name', type: 'string', desc: 'helpful stuff', default: 'trout'});
args.define({gnu: 'count', type: 'int', desc: 'helpful stuff', default: 42});
args.define({gnu: 'weight', type: 'number', desc: 'helpful stuff', default: 4.2});
args.define({gnu: 'kingdom', type: ['animal', 'vegetable'], default: 'mineral'}); // note that validators don't run on defaults, just user inputs.
args.define({gnu: 'male', type: 'flag', desc: 'helpful stuff'}); // defaults really shouldn't be used on flags.
args.define({gnu: 'nicknames', type: 'csv', desc: 'helpful stuff', default: ['flipper', 'fishstick']});
args.define({gnu: 'manifest', type: 'file_in', desc: 'helpful stuff'});
args.define({gnu: 'report', type: 'file_out', desc: 'helpful stuff', default: `report-${new Date().toISOString()}.csv`});
var {params, opts} = args();
console.log(opts.kingdom);
params.map(console.log):
This library follows the convention that -- will cause all following terms to be parameters even if they look like options.
cli -a -- -b results in option a being turned on, and the one param is -b.
In the unixy world, most options follow the convention of allowing you to overrule an earlier setting:
cli --mode=foo ...[many options and params]... --mode=baz will pretend like foo never happened.
This is so that you can write stuff like aliases without needing a bunch of boilerplate wrapper code to allow you to turn an option off:
alias prettyprint="ls --color=always"
prettyprint /root/ --color=never
But in other cases, all values on the command line are preserved and processed. While this library defaults to 'overwrite', there's a multi flag in define() to switch to preserving all. (And type:csv
has this behavior implicitly.)
If there's no --help or errors, args() returns {opts:{}, params:[]}
For legacy support, you can also get at opts and params under their old weird name: args.opts and args.params
If there was an unrecognized option or a failed validator, args() will print the error and exit(1).
The library constructs a --help handler for you, using the defines(), plus summary and noun. If the caller adds --help args() will print that and exit(0);
The help page generated by the above sample setup looks like:
USAGE: yourscriptname [-opts] FISH
SUMMARY TEXT
-n, --name=STRING helpful stuff
-c, --count=INT helpful stuff
-w, --weight=NUMBER helpful stuff
-k, --kingdom=ENUM one of: animal, vegetable
-m, --male helpful stuff
--nicknames=CSV helpful stuff
--manifest=FILE_IN helpful stuff
-r, --report=FILE_OUT helpful stuff
Note that posix names weren't added for nicknames or manifest; that's because there already was a gnu param that had used that first letter. You can add a posix: 'Z' member to the define() config to
pick an arbitrary letter.
Small side feature (tucked here because this is the only truely CLI/serverside-only lib I maintain that has no deps-sensitivity, and this feature is too small to be a lib)
purpose: using debug and debug-extend to load .envs in an isolated-from-process.env style:
USAGE:
const {load} = require('@ashnazg/args/env');
const myconf = load(); // looks for PWD/.env, then in each parent
const myconf = load({path: 'child/.env'}); // only looks at specified path
const myconf = load({buf: 'KEY=VAL'}); // takes utf8 or buffer.
default: '' is no longer ignored."--help" system no longer forces exitCode to be zero. This is in support of the following etiquette:
tool --help is not a failed command.tool --key=nonsense could just bail out, but for errors that are directly related to missing or invalid options use, I like printing the usage guide as well:
FAIL: option A requires option B to be set
USAGE: tool ....
(blah blah blah; everything you see on --help)
function dieNoisily(why) {
console.error(why);
if (process.stdout.isTTY) {
console.log('');
process.exitCode = 1;
args(['--help']);
} else {
process.exit(1);
}
}
Now supports showing examples below the option table:
args.help.script = 'appname';
args.help.noun = 'paramthing';
args.help.summary = 'does things with things';
args.help.examples = `
use thing as such
or like this`;
args.define({gnu: 'slicer'});
args(['--help']);
Will output:
USAGE: appname [-opts] paramthing
does things with things
-s, --slicer=STRING
EXAMPLES:
use thing as such
or like this
{set: 'foo'} will cause all options with that key to output to 'foo' instead of their own name.
--quiet --verbose --quiet -> 'quiet 1', not 'quiet 2 verbose 1' or --markdown vs --jsonldefine({posix: 'v', type: 'flag', max: 2}) means that cli -v -v -v will only report two levels of verbosity instead of three.removed erroneous line from documentation.
posix: fields to all your defines to pin the legacy choices in place, instead of using auto-picked posix letters.{params, opts} and not just optsv1.1.0 now allows you to define() your CLI options using {module: style} instead of the very weird positional style used til now. (Weird in that when you send less than all parameters, the way the library maps your actual params to its various formal signatures crosses even my eyes, and I wrote it.) That weird style is pushing signature overloads so deep into stupid-clever territory that it should burn, but I'm not removing support for legacy usage til either a future 2.0.0.
args.define({gnu, posix, validator, desc, suffix});
json/yaml/lines/raw, then the option's value will be run through args.load[loader]()Flags don't accept values. The value of the option after parse is the count of times the flag was set. This allows cli -v -v to be distinguished from cli -v if needed.
Flags are allowed to be clumped together posix-style: -abc could be three flags, in which case it's the same meaning as -a -b -c, or b could be a non-flag option, in
which case option b has a value of c, making -abc the same as -a -bc. If -b is the short form of your app's --bees=STRING, then -abc is parsed as equivalent to -a --bees=c
clitool --entry=a --entry=b
clitool --entry=a,b
This of course means you can't use validator:'csv' if you want your entry values to include commas, as this will treat them as delimiters.
Because I'm often using file_in to read config files, I have some common file load-and-parse utilities. (If your file is too big to just pull into memory, don't use these.)
If a file a user specified
args.load.json('conf.json').then(obj => console.log(obj));
args.load.lines('file').then(lines => lines.map(console.log));
args.load.yaml('file.yml').then(yaml => console.log(yaml));
args.load.raw('file').then(rawstring => console.log("the whole file:", rawstring));
Each format() can take either a single filename as above, or an array of them, in which case it returns a map of filename:contents
args.load.json(['conf.json', 'manifest.json']).then(confs => {
console.log(confs['conf.json'].port);
console.log(confs['manifest.json'].rows);
});
--no-${option} as a way to clear the value of a non-multi.args.define('c', 'cat', 'string', 'stuff', 'NAME');
args.define('c', 'cat', 'string', 'stuff');
args.define( 'cat', 'string', 'stuff');
args.define( 'cat', 'string');
FAQs
a gnu/posix style CLI opts parser
We found that @ashnazg/args demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.