-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
87 lines (71 loc) · 2.6 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import {get,isFunction,isEqualWith} from 'lodash';
export default function(condition, ctx){
return agregate(condition, cond => test(ctx, cond));
}
/**
* Agregate multiple conditions.
* use `test` to check the condition
*/
export function agregate(condition, test){
const fn = cond => agregate(cond, test);
if (Array.isArray(condition)) return condition.every(fn);
if (condition.and) return condition.and.every(fn);
if (condition.or) return condition.or.some(fn);
if (condition.nor) return !condition.nor.some(fn);
if (condition.nand) return !condition.nand.every(fn);
return test(condition);
}
/**
* Test a condition proposition
*/
export function test(ctx, condition){
const {left, right, operator, debug} = condition;
if (!('left' in condition && 'right' in condition )) throw new Error('Conditions must define both the left and right of a proposition');
const leftValue = getValue(left, ctx);
const rightValue = getValue(right, ctx);
if (debug) {
/*eslint-disable no-console */
console.info('Condition:', JSON.stringify(condition));
console.info('Left:', left, '-->', leftValue);
console.info('Operator:', operator || 'equals');
console.info('Right:', right, '-->', rightValue);
/*eslint-enable no-console */
}
return compare(leftValue, rightValue, operator);
}
function getValue(path, ctx){
if (typeof path === 'string' && /\.|\[/.test(path)) return get(ctx, path);
return path;
}
/**
* Compare two values
*/
export function compare(left,right,operator){
if (isFunction(operator)) return operator(left,right);
switch (operator){
case 'greaterThan':
case 'gt':
return +left > +right;
case 'greaterThanOrEqual':
case 'gte':
return +left >= +right;
case 'lesserThan':
case 'lt':
return +left < +right;
case 'lesserThanOrEqual':
case 'lte':
return +left <= +right;
case 'in':
if (Array.isArray(right)) return right.indexOf(left) !== -1;
throw new Error('Condition "in" requires right to be a function');
case 'exactly':
return left === right;
case 'equals':
case undefined:
return isEqualWith(left, right, equalNumbers);
default:
throw new Error('Unknown operator');
}
function isNumeric(obj){return typeof obj == 'number' || typeof obj == 'string' && !isNaN(parseFloat(obj));}
function equalNumbers(left, right){return [left,right].every(isNumeric) ? +left === +right : undefined;}
}