Skip to content

Commit 7611c12

Browse files
committed
Added support for custom validation
1 parent 84449de commit 7611c12

File tree

5 files changed

+74
-3
lines changed

5 files changed

+74
-3
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ Args.configure({
143143
type: string_or_primitive, // example: 'boolean' or Boolean
144144
alias: string,
145145
allowMultipleValues: true/false,
146-
options: [...]
146+
options: [...],
147+
validate: function(){}/RegExp
147148
}, {
148149
...
149150
}
@@ -159,6 +160,7 @@ _Purpose:_
159160
- `aliases` - Support for multiple aliases.
160161
- `allowMultipleValues` - If a flag is specified more than once, capture all values (instead of only the last one specified).
161162
- `options` - An array of valid values for the flag.
163+
- `validate` - This is a function or regular expression that determines whether the value of the flag is valid or not. A function receives the value as the only argument and is expected to return `true` or `false` (where `true` means the value is valid). If a RegExp is provided, the [RegExp.test()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test) method is executed against the flag value. The validate feature is used **in addition** to other validation mechanisms (options, typing, etc).
162164

163165
### Using Individual Methods
164166

flag.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export default class Flag {
1212
#value = null
1313
#violations = new Set()
1414
#recognized = false
15+
#validator = null
1516

1617
constructor (cfg = {}) {
1718
if (typeof cfg === 'string') {
@@ -60,6 +61,14 @@ export default class Flag {
6061
if (cfg.hasOwnProperty('options')) {
6162
this.options = cfg.options
6263
}
64+
65+
if (cfg.hasOwnProperty('validate')) {
66+
if (!(cfg.validate instanceof RegExp || typeof cfg.validate === 'function')) {
67+
throw new Error(`The "validate" configuration attribute for ${this.#rawName} is invalid. Only RegExp and functions are supported (received ${typeof cfg.validate})`)
68+
}
69+
70+
this.#validator = cfg.validate
71+
}
6372
}
6473

6574
get inputName () {
@@ -124,6 +133,25 @@ export default class Flag {
124133
}
125134
}
126135
}
136+
137+
if (this.#validator !== null) {
138+
if (typeof this.#validator === 'function') {
139+
if (!this.#validator(value)) {
140+
this.#violations.add(`"${value}" is invalid (failed custom validation).`)
141+
return false
142+
}
143+
} else {
144+
if (typeof value !== 'string' && this.#validator instanceof RegExp) {
145+
this.#violations.add(`"${value}" is invalid (failed custom validation).`)
146+
return false
147+
}
148+
149+
if (!this.#validator.test(value)) {
150+
this.#violations.add(`"${value}" is invalid (failed custom validation).`)
151+
return false
152+
}
153+
}
154+
}
127155

128156
return true
129157
}

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@author.io/arg",
3-
"version": "1.2.6",
3+
"version": "1.3.0",
44
"description": "An argument parser for CLI applications.",
55
"main": "index.js",
66
"scripts": {

test/01-sanity.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,46 @@ test('Escaped parameters', t => {
2121
, 'Parsed complex input'
2222
)
2323

24+
console.log(new Parser('cfw run -r -hdr "CF-IPCountry=US" -kv "test=something" -kv "a=test" demo.js', {
25+
kv: {
26+
allowMultipleValues: true
27+
},
28+
header: {
29+
alias: 'hdr',
30+
allowMultipleValues: true
31+
}
32+
}).data)
33+
34+
t.end()
35+
})
36+
37+
test('Support custom validation methods', t => {
38+
const input = 'test -v ok -b notok'
39+
const cfg = {
40+
value: {
41+
alias: 'v',
42+
validate: value => value === 'ok'
43+
}
44+
}
45+
46+
let Args = new Parser(input, cfg)
47+
t.ok(Args.violations.length === 0, `Expected no violations, recognized ${Args.violations.length}.`)
48+
49+
cfg.bad = {
50+
alias: 'b',
51+
validate: value => value === 'ok'
52+
}
53+
54+
Args = new Parser(input, cfg)
55+
t.ok(Args.violations.length === 1, `Expected 1 violation, recognized ${Args.violations.length}.`)
56+
57+
Args = new Parser('test --pass abbbbc', {
58+
pass: {
59+
validate: /^a.*c$/gi
60+
}
61+
})
62+
63+
t.ok(Args.violations.length === 0, `Expected no violations, recognized ${Args.violations.length}.`)
64+
2465
t.end()
2566
})

0 commit comments

Comments
 (0)