v8n
Version:
Dead simple fluent JavaScript validation library
83 lines (72 loc) • 1.75 kB
JavaScript
class Rule {
constructor(name, fn, args, modifiers) {
this.name = name;
this.fn = fn;
this.args = args;
this.modifiers = modifiers;
}
_test(value) {
let fn = this.fn;
try {
testAux(this.modifiers.slice(), fn, this)(value);
} catch (ex) {
fn = () => false;
}
try {
return testAux(this.modifiers.slice(), fn, this)(value);
} catch (ex) {
return false;
}
}
_check(value) {
try {
testAux(this.modifiers.slice(), this.fn, this)(value);
} catch (ex) {
if (testAux(this.modifiers.slice(), it => it, this)(false)) {
return;
}
}
if (!testAux(this.modifiers.slice(), this.fn, this)(value)) {
throw null;
}
}
_testAsync(value) {
return new Promise((resolve, reject) => {
testAsyncAux(
this.modifiers.slice(),
this.fn,
this,
)(value)
.then(valid => {
if (valid) {
resolve(value);
} else {
reject(null);
}
})
.catch(ex => reject(ex));
});
}
}
function pickFn(fn, variant = 'simple') {
return typeof fn === 'object' ? fn[variant] : fn;
}
function testAux(modifiers, fn, rule) {
if (modifiers.length) {
const modifier = modifiers.shift();
const nextFn = testAux(modifiers, fn, rule);
return modifier.perform(nextFn, rule);
} else {
return pickFn(fn);
}
}
function testAsyncAux(modifiers, fn, rule) {
if (modifiers.length) {
const modifier = modifiers.shift();
const nextFn = testAsyncAux(modifiers, fn, rule);
return modifier.performAsync(nextFn, rule);
} else {
return value => Promise.resolve(pickFn(fn, 'async')(value));
}
}
export default Rule;