vercel / arg Goto Github PK
View Code? Open in Web Editor NEWSimple argument parsing
Home Page: https://npmjs.com/arg
License: MIT License
Simple argument parsing
Home Page: https://npmjs.com/arg
License: MIT License
This is justified since Boolean
types already get a bit of special treatment.
In the case I want multiple levels of verbosity, for example, the following should work:
// ./my-program -vvvv
const arg = require('arg');
const args = arg({
'-v': [Boolean]
});
console.log(args);
/*
{
_: [],
'-v': 4
}
*/
Currently, you have to do -v -v -v -v
separately, and in turn you get [true, true, true, true]
, which isn't exactly elegant.
Is there a way to have optional flag values? Something like the following:
const arg = require('arg');
const args = arg({
'--port': Number, // --port <number>
'--host': String.optional, // --host [string]
});
Given --port 5432 --host localhost
it should return { _: [], port: 5432, host: 'localhost' }
,
given --port 5432 --host
it should return something like { _: [], port: 5432, host: true }
,
and given --port 5432
it should return { _: [], port: 5432 }
,
After checking out the new spec and reading about @rauchg's and @Qix-' arguments for this, I think it makes sense to try it out in more of our projects in the future.
However, in order for this to happen, we need a name that's not ZEIT-dependent. Open source projects that focus on the author won't make it far (no matter if it's the code or just the name). The name (just like the functionality) needs to be much more general and independent (see "chalk", "hazel", "serve", "release", "micro", etc). People won't be interested in contributing otherwise.
In addition, "zarg" (spelled "z-arg") is not that easy to say, imo.
Line 13 in 99b578e
The library takes the default argument vector from process.env
. As a result, the library does not work in the browser. Removing the default fixes this.
I understand that this is an unconventional use-case and that arg
is an opinionated library so this might be outside the scope, but if it isn't I'm more than happy to make a PR from my fork (that I currently use to work around this limitation).
As my realization, the {permissive: true}
should left the unknown option being unparsed and treat them as positional arguments, but currently the permissive will still split the unknown short options. Is this a expected behavor? or can we change this behavor?
const arg = require('arg')
const args = arg({}, {argv: '-abc', permissive: true})
console.assert(args._[0] != '-abc')
console.assert(args._.join(' ') == '-a -b -c')
Need to make sure all properties start with a hyphen
The current types in index.d.ts
produce an error when attempting to use them in a purely TypeScript project:
Exported variable 'args' has or is using name 'flagSymbol' from external module
"/path/to/project/node_modules/arg/index" but cannot be named.ts(4023)
After a brief bit of tweaking, I found that this can be fixed by moving flagSymbol
into the arg
namespace and exporting it along with other members. This makes the type accessible and resolves the error. I'm unsure if there is a better way to handle it, though this should be fine.
declare module "arg" {
function arg<T extends arg.Spec>(
spec: T,
options?: arg.Options
): arg.Result<T>;
namespace arg {
export const flagSymbol: unique symbol;
export function flag<T>(fn: T): T & { [arg.flagSymbol]: true };
export const COUNT: Handler<number> & { [arg.flagSymbol]: true };
export type Handler<T = any> = (
value: string,
name: string,
previousValue?: T
) => T;
export class ArgError extends Error {
constructor(message: string, code: string);
code: string;
}
export interface Spec {
[key: string]: string | Handler | [Handler];
}
export type Result<T extends Spec> = { _: string[] } & {
[K in keyof T]?: T[K] extends Handler
? ReturnType<T[K]>
: T[K] extends [Handler]
? Array<ReturnType<T[K][0]>>
: never;
};
export interface Options {
argv?: string[];
permissive?: boolean;
stopAtPositional?: boolean;
}
}
export = arg;
}
Note: This is occurring for me using typescript@^4.6.3
. I'm not sure if this is an issue with a new version of TypeScript or has always been a problem since I've typically only used arg
in JavaScript projects up until now.
CI should be added. @rauchg is ZEIT still in favor of tests-in-docker approach?
For example, I have this arg "--tte": [String],
so whenever I call the program I need to write myScript --tte event
is there a way to write multiple string without repeating --tte multiple times and splinting with commas?
Would it make sense to support required arguments? For example:
const args = arg({
'--help': Boolean,
'--port': arg.req(Number),
'--name': String,
'--tag': arg.req([String]),
});
Alternatively:
const args = arg({
'--help': Boolean,
'--path': String,
});
const {
'--help': printHelp = false,
'--path': thePath = arg.required('--path', String),
} = args;
arg.required()
would print an error message and exit Node.js. Downsides of this approach: Doesn’t handle aliases, redundancy.
If this is out of scope, it would be a good FAQ, because many shell argument parsing libraries support this feature.
Title speaks for itself (I believe). It would largely just work by using esm
Short args can't be used with =
. Is this intentional?
const arg = require('arg')
arg({
'-a': String
})
node example.js -a=a
Results in:
throw new TypeError(`Option requires argument (but was followed by another short argument): ${originalArgName}`);
^
TypeError: Option requires argument (but was followed by another short argument): -a
at arg (<path>/node_modules/arg/index.js:97:12)
at Object.<anonymous> (<path>/example.js:5:1)
A similar error happens for aliases:
const arg = require('arg')
arg({
'--a': String,
'-a': '--a'
})
It'd be sweet if this library also supported default arguments. The API could look like this:
arg({
'--help': Boolean,
'-h': '--help',
'--branch': String,
'-b': '--branch',
'--config': './config',
'-c': '--config'
})
You could distinguish between String
and a String argument with a default by doing:
if (value === String) {
// it's a string argument
}
if (typeof value === 'string') {
// it's a string argument with a default
}
In some projects, I need the ability to "stop early" when parsing the arguments. I want it to parse up until the first _
argument and then break. This is useful for projects such as https://github.com/TypeStrong/ts-node (like node.js core), where the arguments before the script file are part of the execution and after the script name part of the script arguments.
It seems like arg
is parsing quoted strings.
Here is an online example: https://repl.it/repls/IllegalTraumaticLifecycles
Input string
--string "ES_JAVA_OPTS=-Xms512m -Xmx512m"
Output
Error: Unknown or unexpected option: -X
I'm a huge fan of whitelists to make sure no garbage ever ends up in npm accidentally.
It would look approximately like this:
*
!index.js
!index.d.ts
🚨 You need to enable Continuous Integration on all branches of this repository. 🚨
To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.
Since we didn’t receive a CI status on the greenkeeper/initial
branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.
If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/
.
Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please delete the greenkeeper/initial
branch in this repository, and then remove and re-add this repository to the Greenkeeper App’s white list on Github. You'll find this list on your repo or organization’s settings page, under Installed GitHub Apps.
When implement the module in typescript and built it, I get the next error when I trying to run
const args = (0, arg_1.default)({ '--v': Boolean, '--a': Boolean, '-v': '--v', '-a': '--a' });
UnhandledPromiseRejectionWarning: TypeError: (0 , arg_1.default) is not a function
I'm looking for a package to help me write CLIs and very much like arg's simplicity for parsing args. I was thinking that if the spec format was a bit enhanced, it could perhaps help me print help as well, like this:
const spec = {
"--help": { type: Boolean, description: "Show help" },
"--port": { type: Number, description: "Port number" }
};
const args = arg(spec);
if (args['--help']) {
console.log(getHelp(spec));
}
What do you think? I know it might be out of the scope of this package but arg parsing and printing help are closely related things and I'd like to stay DRY.
I need the ability to get _
arguments and --
separately. Currently everything after --
gets placed into args._
so I can't tell which was after the --
argument or which was part of the command. This is required to use in projects such as https://github.com/Qard/onchange.
We've been using codecov.io
for this purpose with great results
Hi, I don't understand this part from Readme.md
// hello.js
const arg = require('arg');
const args = arg({
// Types
'--help': Boolean,
'--version': Boolean,
'--verbose': arg.COUNT, // Counts the number of times --verbose is passed
'--port': Number, // --port <number> or --port=<number>
'--name': String, // --name <string> or --name=<string>
'--tag': [String], // --tag <string> or --tag=<string>
// Aliases
'-v': '--verbose',
'-n': '--name', // -n <string>; result is stored in --name
'--label': '--name' // --label <string> or --label=<string>;
// result is stored in --name
});
console.log(args);
/*
{
_: ["foo", "bar", "--foobar"],
'--port': 1234,
'--verbose': 4,
'--name': "My name",
'--tag': ["qux", "qix"]
}
*/
I think --verbose
should be true
, not 4
, because I got true
from my practice.
// t.ts
const arg = require("arg");
const args = arg(
{
"--project": String,
"--pass": Boolean,
"-p": "--project"
},
{
argv: process.argv.slice(2)
}
);
// package.json
"start": "ts-node ./t.ts -p hello --pass"
// Result
{ _: [], '--project': 'hello', '--pass': true }
So, can someone tell me why it is 4
? If it should'be fixed, I'll send a pr.
When an arg has =
in the value, everything after (inc) =
gets stripped off from the arg.
Pass this command to arg()
—
yarn keystone dev --connect-to=mongodb://user:pass@localhost:27017/keystone?authSource=admin&w=1
Current output
--connect-to
= mongodb://user:pass@localhost:27017/keystone?authSource
Expected output
--connect-to
= mongodb://user:pass@localhost:27017/keystone?authSource=admin&w=1
This is essential for passing URLs as arg value.
Since we plan to accept no-space short arg parsing, we should enforce that single-hyphen arguments only have one character.
Consider:
now --debug scale --no-verify
We need to be able to parse this only with the known global options. For example:
{
"--debug": Boolean
}
When it inevitable throws on the unknown --no-verify
option, we need to recover everything else it was able to parse.
in node shell:
> const arg = require('arg')
undefined
> arg({"--int": parseInt}, {argv:["--int=-100"]})
{ _: [], '--int': -100 }
> arg({"--int": parseInt}, {argv:["--int -100"]})
Thrown:
{ Error: Unknown or unexpected option: --int -100
at arg (/run/media/karfau/hdd-data/dev/node-cli-arguments-options/arg/node_modules/arg/index.js:88:19) code: 'ARG_UNKNOWN_OPTION' }
> arg({"--num": parseFloat}, {argv:["--num=-1.0"]})
{ _: [], '--num': -1 }
> arg({"--num": parseFloat}, {argv:["--num -1.0"]})
Thrown:
{ Error: Unknown or unexpected option: --num -1.0
at arg (node-cli-arguments-options/arg/node_modules/arg/index.js:88:19) code: 'ARG_UNKNOWN_OPTION' }
I also tried to wrap the numbers with different kinds of quotes, but it didn't have any effect.
I don't know if this is a "feature" or a "bug".
Update: The example above is bad in the sense that argv
is different from what it would look like when using from the shell, which influences the error messages. A better example is:
> const arg = require('arg')
undefined
> arg({"--int": parseInt}, {argv:["--int", "-100"]})
Thrown:
Error: Option requires argument: --int
at arg (node-cli-arguments-options/arg/node_modules/arg/index.js:105:13)
> arg({"--float": parseFloat}, {argv:["--float", "-0.1"]})
Thrown:
Error: Option requires argument: --float
at arg (node-cli-arguments-options/arg/node_modules/arg/index.js:105:13)
Since the repo doesn't seem to be maintained (sorry for that, it's not true, must have switched the name with one of the other repos), just filing this to make people aware since I discovered it while comparing features of different argument parsers (WIP)
ReDoS vulnerability is an algorithmic complexity vulnerability that usually appears in backtracking-kind regex engines, e.g. the javascript default regex engine. The attacker can construct malicious input to trigger the worst-case time complexity of the regex engine to make a denial-of-service attack.
In this project, here has used the ReDoS vulnerable regex ^-?\d*(\.(?=\d))?\d*$
that can be triggered by the below PoC:
const arg = require('arg');
const args = arg(
{
'--foo': String
}, {
argv: ['hello', '--foo', '-' + '0'.repeat(60000) + '-']
}
);
The cause of this vulnerability is the use of the backtracking-kind regex engine. I recommend the author to use the RE2 regex engine developed by google, but it doesn't support lookaround and backreference extension features, so we need to change the original regex and add additional code constraints. Here is my repair solution:
function safeMatch(string) {
const RE2 = require("re2")
let re = new RE2(/^-?\d*(\.)?(\d*)$/)
let res = re.match(string)
if (res != null) {
group1 = res[1]
if (group1 !== null) {
group2 = res[2]
if (/^\d/.test(group2)) {
return res
} else {
return null
}
}
return res
}
return res
}
console.log(safeMatch("-1.1")) // [ '-1.1', '.', '1', index: 0, input: '-1.1', groups: undefined ]
console.log(safeMatch("-1.")) // null
console.log(safeMatch(".")) // null
Using this code snippet to replace the code in line 156 argv[i + 1].match(/^-?\d*(\.(?=\d))?\d*$/)
can repair this vulnerability. The match semantics of the new regex + code constraint above is equivalent to the original regex.
I hope the author can adopt this repair solution and I would be very grateful. Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.