Comparing version 2020.8.10 to 2020.8.11
@@ -0,1 +1,7 @@ | ||
### 2020.8.11 | ||
* set errors in optional property instead of throwing | ||
* entire rhs of key-value = symbol is saved in value | ||
* also reject 'prototype' argument/options | ||
### 2020.8.10 | ||
@@ -2,0 +8,0 @@ |
63
index.js
@@ -10,7 +10,6 @@ const parse_arg = (arg) => { | ||
if (option.includes('=')) { | ||
const [key, value] = option.split('=') | ||
const [key, value] = option.split(/=(.*)/) | ||
if (key === '' || value === '') | ||
throw Error(`key-value has empty key or value (${arg}). Expected at least one, eg: --pet=cat`) | ||
return ['kv', [key, value]] | ||
return ['o', [option]] | ||
else return ['kv', [key, value]] | ||
} | ||
@@ -32,5 +31,2 @@ | ||
if (next.includes('__proto__')) | ||
throw Error(`__proto__ not allowed within an argument to prevent prototype pollution.`) | ||
const [kind, parsed] = acc.skip ? ['a', next] : parse_arg(next) | ||
@@ -69,8 +65,2 @@ | ||
const first_arg = (args) => Object.keys(args).reduce((acc, key) => { | ||
const [val] = args[key] | ||
const o = { [key]: val } | ||
return { ...o, ...acc } | ||
}, {}) | ||
const copy_alias_values = (parsed, names) => { | ||
@@ -86,17 +76,44 @@ names.forEach(name => { | ||
const trim_filter = (input) => input | ||
.filter(a => typeof a === 'string') | ||
.map(s => s.trim()) | ||
.filter(s => s.length) | ||
const first_arg = (args) => Object.keys(args).reduce((acc, key) => { | ||
const [val] = args[key] | ||
const o = { [key]: val } | ||
return { ...o, ...acc } | ||
}, {}) | ||
module.exports = (args = [], alias = []) => { | ||
const validate_input = (args, alias) => { | ||
if (!Array.isArray(args) || !Array.isArray(alias)) | ||
throw Error(`expected input to be array(s). Eg clia(process.argv.slice(2),['alias','names'])`) | ||
return [[], [], [`Expected input to be array(s). Eg clia(process.argv.slice(2),['alias','names'])`]] | ||
const parsed = combine_input(trim_filter(args)) | ||
const trim_filter = (input) => input | ||
.filter(a => typeof a === 'string') | ||
.filter(s => !s.includes('__proto__')) | ||
.filter(s => !s.includes('prototype')) | ||
.map(s => s.trim()) | ||
.filter(s => s.length) | ||
copy_alias_values(parsed, trim_filter(alias)) | ||
const filter_reason = `Not a string, string is empty or spaces only, string contains __proto__ or prototype.` | ||
return { | ||
const valid_args = trim_filter(args) | ||
const valid_alias = trim_filter(alias) | ||
const errors = [ | ||
valid_args.length < args.length ? | ||
`One or more args were excluded from parsing. Reason: ${filter_reason}` : '', | ||
valid_alias.length < alias.length ? | ||
`One or more aliases were excluded from parsing. Reason: ${filter_reason}` : ''] | ||
.filter(e => e.length) | ||
return [valid_args, valid_alias, errors] | ||
} | ||
module.exports = (args = [], alias = []) => { | ||
const [valid_args, valid_alias, errors] = validate_input(args, alias) | ||
const parsed = combine_input(valid_args) | ||
copy_alias_values(parsed, valid_alias) | ||
const result = { | ||
arg: first_arg(parsed.args), | ||
@@ -107,2 +124,4 @@ args: parsed.args, | ||
} | ||
return errors.length ? { ...{ errors }, ...result } : result | ||
} |
{ | ||
"name": "clia", | ||
"version": "2020.8.10", | ||
"version": "2020.8.11", | ||
"description": "Command line parser and t3st example project", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -38,10 +38,53 @@ # clia | ||
Empty or non-string inputs are ignored. Spaces are trimmed from inputs. | ||
Spaces are trimmed from inputs. | ||
Empty or non-string inputs are ignored. | ||
Inputs that contain `__proto__` or `prototype` are ignored. *(To prevent prototype pollution.)* | ||
If there are any errors, there will be an `errors` property in the return value | ||
Example *invalid* command line input: | ||
```bash | ||
node your-app.js valid --ok=yes prototype last-token | ||
``` | ||
yields | ||
```javascript | ||
{ | ||
errors: [ | ||
'One or more args were excluded from parsing. Reason: Not a string, string is empty or spaces only, string contains __proto__ or prototype.' | ||
], | ||
arg: { ok: 'yes' }, | ||
args: { ok: ['yes'] }, | ||
opt: {}, | ||
plain: ['valid', 'last-token'] | ||
} | ||
``` | ||
It is recommended that you check for any input errors. | ||
```javascript | ||
// in main.js/index.js | ||
const conf = clia(process.argv.slice(2)) | ||
if(conf.errors){ | ||
// graceful exit | ||
console.log('Could not parse command line input, errors:') | ||
console.log(conf.errors) | ||
require('process').exitCode(1) | ||
return | ||
} | ||
``` | ||
When `--` is encountered, it is ignored. All subsequent inputs are treated as arguments even if they start with `-`. | ||
An error is thrown when: | ||
* any argument containts `__proto__` *to prevent prototype pollution* | ||
* key-value pair with missing key or value, eg: `--store=` or `--=pet` | ||
Key-values with missing key or value are saved as-is: | ||
eg: | ||
option `--store=` yields: `{ .. opt: { 'store=': true }` | ||
option `--=pet` yields: `{ .. opt: { '=pet': true }` | ||
## alias | ||
@@ -90,2 +133,3 @@ | ||
[![OtherMetric](https://img.shields.io/npm/t3st/one.svg)](https://npmjs.com/one) | ||
[![OtherMetric](https://img.shields.io/npm/t3st/three.svg)](https://npmjs.com/three) | ||
--> |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
9524
97
133