New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

json-rules-engine

Package Overview
Dependencies
Maintainers
1
Versions
82
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

json-rules-engine - npm Package Compare versions

Comparing version 2.1.0 to 2.2.0-alpha1

test/performance.test.js

103

dist/almanac.js

@@ -19,4 +19,2 @@ 'use strict';

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -68,7 +66,3 @@

value: function _getFact(factId) {
var fact = this.factMap.get(factId);
if (fact === undefined) {
throw new _errors.UndefinedFactError('Undefined fact: ' + factId);
}
return fact;
return this.factMap.get(factId);
}

@@ -100,5 +94,2 @@

var factValue = Promise.resolve(value);
factValue.then(function (val) {
return debug('almanac::factValue fact:' + fact.id + ' calculated as: ' + JSON.stringify(val) + '<' + (typeof val === 'undefined' ? 'undefined' : _typeof(val)) + '>');
});
if (cacheKey) {

@@ -134,64 +125,38 @@ this.factResultsCache.set(cacheKey, factValue);

key: 'factValue',
value: function () {
var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee(factId) {
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
var factValue, fact, cacheKey, cacheVal;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
factValue = void 0;
fact = this._getFact(factId);
cacheKey = fact.getCacheKey(params);
cacheVal = cacheKey && this.factResultsCache.get(cacheKey);
value: function factValue(factId) {
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
if (!cacheVal) {
_context.next = 11;
break;
}
_context.next = 7;
return cacheVal;
case 7:
factValue = _context.sent;
debug('almanac::factValue cache hit for fact:' + factId + ' value: ' + JSON.stringify(factValue) + '<' + (typeof factValue === 'undefined' ? 'undefined' : _typeof(factValue)) + '>');
_context.next = 15;
break;
case 11:
verbose('almanac::factValue cache miss for fact:' + factId + '; calculating');
_context.next = 14;
return this._setFactValue(fact, params, fact.calculate(params, this));
case 14:
factValue = _context.sent;
case 15:
if (path) {
if (isObjectLike(factValue)) {
factValue = selectn(path)(factValue);
debug('condition::evaluate extracting object property ' + path + ', received: ' + factValue);
} else {
warn('condition::evaluate could not compute object path(' + path + ') of non-object: ' + factValue + ' <' + (typeof factValue === 'undefined' ? 'undefined' : _typeof(factValue)) + '>; continuing with ' + factValue);
}
}
return _context.abrupt('return', factValue);
case 17:
case 'end':
return _context.stop();
}
var factValuePromise = void 0;
var fact = this._getFact(factId);
if (fact === undefined) {
return Promise.reject(new _errors.UndefinedFactError('Undefined fact: ' + factId));
}
if (fact.isConstant()) {
factValuePromise = Promise.resolve(fact.calculate(params, this));
} else {
var cacheKey = fact.getCacheKey(params);
var cacheVal = cacheKey && this.factResultsCache.get(cacheKey);
if (cacheVal) {
factValuePromise = Promise.resolve(cacheVal);
debug('almanac::factValue cache hit for fact:' + factId);
} else {
verbose('almanac::factValue cache miss for fact:' + factId + '; calculating');
factValuePromise = this._setFactValue(fact, params, fact.calculate(params, this));
}
}
if (path) {
return factValuePromise.then(function (factValue) {
if (isObjectLike(factValue)) {
var pathValue = selectn(path)(factValue);
debug('condition::evaluate extracting object property ' + path + ', received: ' + pathValue);
return pathValue;
} else {
warn('condition::evaluate could not compute object path(' + path + ') of non-object: ' + factValue + ' <' + (typeof factValue === 'undefined' ? 'undefined' : _typeof(factValue)) + '>; continuing with ' + factValue);
return factValue;
}
}, _callee, this);
}));
function factValue(_x2) {
return _ref.apply(this, arguments);
});
}
return factValue;
}()
return factValuePromise;
}
}]);

@@ -198,0 +163,0 @@

@@ -9,4 +9,2 @@ 'use strict';

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -98,40 +96,11 @@

key: '_getValue',
value: function () {
var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee(almanac) {
var value;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
value = this.value;
if (!(isObjectLike(value) && value.hasOwnProperty('fact'))) {
_context.next = 5;
break;
}
_context.next = 4;
return almanac.factValue(value.fact, value.params, value.path);
case 4:
value = _context.sent;
case 5:
return _context.abrupt('return', value);
case 6:
case 'end':
return _context.stop();
}
}
}, _callee, this);
}));
function _getValue(_x2) {
return _ref.apply(this, arguments);
value: function _getValue(almanac) {
var value = this.value;
if (isObjectLike(value) && value.hasOwnProperty('fact')) {
// value: { fact: 'xyz' }
return almanac.factValue(value.fact, value.params, value.path);
}
return Promise.resolve(value);
}
return _getValue;
}()
/**

@@ -149,73 +118,22 @@ * Takes the fact result and compares it to the condition 'value', using the operator

key: 'evaluate',
value: function () {
var _ref2 = _asyncToGenerator(regeneratorRuntime.mark(function _callee2(almanac, operatorMap) {
var op, rightHandSideValue, leftHandSideValue, result;
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
if (almanac) {
_context2.next = 2;
break;
}
value: function evaluate(almanac, operatorMap) {
var _this = this;
throw new Error('almanac required');
if (!almanac) return Promise.reject(new Error('almanac required'));
if (!operatorMap) return Promise.reject(new Error('operatorMap required'));
if (this.isBooleanOperator()) return Promise.reject(new Error('Cannot evaluate() a boolean condition'));
case 2:
if (operatorMap) {
_context2.next = 4;
break;
}
var op = operatorMap.get(this.operator);
if (!op) return Promise.reject(new Error('Unknown operator: ' + this.operator));
throw new Error('operatorMap required');
return this._getValue(almanac) // todo - parallelize
.then(function (rightHandSideValue) {
return almanac.factValue(_this.fact, _this.params, _this.path).then(function (leftHandSideValue) {
var result = op.evaluate(leftHandSideValue, rightHandSideValue);
debug('condition::evaluate <' + leftHandSideValue + ' ' + _this.operator + ' ' + rightHandSideValue + '?> (' + result + ')');
return { result: result, leftHandSideValue: leftHandSideValue, rightHandSideValue: rightHandSideValue, operator: _this.operator };
});
});
}
case 4:
if (!this.isBooleanOperator()) {
_context2.next = 6;
break;
}
throw new Error('Cannot evaluate() a boolean condition');
case 6:
op = operatorMap.get(this.operator);
if (op) {
_context2.next = 9;
break;
}
throw new Error('Unknown operator: ' + this.operator);
case 9:
_context2.next = 11;
return this._getValue(almanac);
case 11:
rightHandSideValue = _context2.sent;
_context2.next = 14;
return almanac.factValue(this.fact, this.params, this.path);
case 14:
leftHandSideValue = _context2.sent;
result = op.evaluate(leftHandSideValue, rightHandSideValue);
debug('condition::evaluate <' + leftHandSideValue + ' ' + this.operator + ' ' + rightHandSideValue + '?> (' + result + ')');
return _context2.abrupt('return', { result: result, leftHandSideValue: leftHandSideValue, rightHandSideValue: rightHandSideValue, operator: this.operator });
case 18:
case 'end':
return _context2.stop();
}
}
}, _callee2, this);
}));
function evaluate(_x3, _x4) {
return _ref2.apply(this, arguments);
}
return evaluate;
}()
/**

@@ -222,0 +140,0 @@ * Returns the boolean operator for the condition

@@ -36,4 +36,2 @@ 'use strict';

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -213,42 +211,23 @@

key: 'evaluateRules',
value: function () {
var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee(ruleArray, almanac) {
var _this2 = this;
value: function evaluateRules(ruleArray, almanac) {
var _this2 = this;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
return _context.abrupt('return', Promise.all(ruleArray.map(function (rule) {
if (_this2.status !== RUNNING) {
debug('engine::run status:' + _this2.status + '; skipping remaining rules');
return;
}
return rule.evaluate(almanac).then(function (ruleResult) {
debug('engine::run ruleResult:' + ruleResult.result);
if (ruleResult.result) {
_this2.emit('success', rule.event, almanac, ruleResult);
_this2.emit(rule.event.type, rule.event.params, almanac, ruleResult);
almanac.factValue('success-events', { event: rule.event });
} else {
_this2.emit('failure', rule.event, almanac, ruleResult);
}
});
})));
case 1:
case 'end':
return _context.stop();
}
return Promise.all(ruleArray.map(function (rule) {
if (_this2.status !== RUNNING) {
debug('engine::run status:' + _this2.status + '; skipping remaining rules');
return;
}
return rule.evaluate(almanac).then(function (ruleResult) {
debug('engine::run ruleResult:' + ruleResult.result);
if (ruleResult.result) {
_this2.emit('success', rule.event, almanac, ruleResult);
_this2.emit(rule.event.type, rule.event.params, almanac, ruleResult);
almanac.factValue('success-events', { event: rule.event });
} else {
_this2.emit('failure', rule.event, almanac, ruleResult);
}
}, _callee, this);
});
}));
}
function evaluateRules(_x3, _x4) {
return _ref.apply(this, arguments);
}
return evaluateRules;
}()
/**

@@ -263,50 +242,30 @@ * Runs the rules engine

key: 'run',
value: function () {
var _ref2 = _asyncToGenerator(regeneratorRuntime.mark(function _callee2() {
var _this3 = this;
value: function run() {
var _this3 = this;
var runtimeFacts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var almanac, orderedSets, cursor;
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
debug('engine::run started');
debug('engine::run runtimeFacts:', runtimeFacts);
runtimeFacts['success-events'] = new _fact2.default('success-events', (0, _engineFacts.SuccessEventFact)(), { cache: false });
this.status = RUNNING;
almanac = new _almanac2.default(this.facts, runtimeFacts);
orderedSets = this.prioritizeRules();
cursor = Promise.resolve();
// for each rule set, evaluate in parallel,
// before proceeding to the next priority set.
var runtimeFacts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return _context2.abrupt('return', new Promise(function (resolve, reject) {
orderedSets.map(function (set) {
cursor = cursor.then(function () {
return _this3.evaluateRules(set, almanac);
}).catch(reject);
return cursor;
});
cursor.then(function () {
_this3.status = FINISHED;
debug('engine::run completed');
resolve(almanac.factValue('success-events'));
}).catch(reject);
}));
case 8:
case 'end':
return _context2.stop();
}
}
}, _callee2, this);
}));
function run() {
return _ref2.apply(this, arguments);
}
return run;
}()
debug('engine::run started');
debug('engine::run runtimeFacts:', runtimeFacts);
runtimeFacts['success-events'] = new _fact2.default('success-events', (0, _engineFacts.SuccessEventFact)(), { cache: false });
this.status = RUNNING;
var almanac = new _almanac2.default(this.facts, runtimeFacts);
var orderedSets = this.prioritizeRules();
var cursor = Promise.resolve();
// for each rule set, evaluate in parallel,
// before proceeding to the next priority set.
return new Promise(function (resolve, reject) {
orderedSets.map(function (set) {
cursor = cursor.then(function () {
return _this3.evaluateRules(set, almanac);
}).catch(reject);
return cursor;
});
cursor.then(function () {
_this3.status = FINISHED;
debug('engine::run completed');
resolve(almanac.factValue('success-events'));
}).catch(reject);
});
}
}]);

@@ -313,0 +272,0 @@

@@ -38,4 +38,6 @@ 'use strict';

this.value = valueOrMethod;
this.type = this.constructor.CONSTANT;
} else {
this.calculationMethod = valueOrMethod;
this.type = this.constructor.DYNAMIC;
}

@@ -54,11 +56,21 @@

/**
* Return the fact value, based on provided parameters
* @param {object} params
* @param {Almanac} almanac
* @return {any} calculation method results
*/
_createClass(Fact, [{
key: 'isConstant',
value: function isConstant() {
return this.type === this.constructor.CONSTANT;
}
}, {
key: 'isDynamic',
value: function isDynamic() {
return this.type === this.constructor.DYNAMIC;
}
/**
* Return the fact value, based on provided parameters
* @param {object} params
* @param {Almanac} almanac
* @return {any} calculation method results
*/
_createClass(Fact, [{
}, {
key: 'calculate',

@@ -107,3 +119,4 @@ value: function calculate(params, almanac) {

var cacheProperties = this.cacheKeyMethod(this.id, params);
return Fact.hashFromObject(cacheProperties);
var _hash = Fact.hashFromObject(cacheProperties);
return _hash;
}

@@ -122,2 +135,5 @@ }

Fact.CONSTANT = 'CONSTANT';
Fact.DYNAMIC = 'DYNAMIC';
exports.default = Fact;
'use strict';
require('./generator-runtime');
module.exports = require('./json-rules-engine');

@@ -21,4 +21,2 @@ 'use strict';

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -189,324 +187,142 @@

key: 'evaluate',
value: function () {
var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee6(almanac) {
var _this3 = this;
value: function evaluate(almanac) {
var _this3 = this;
var ruleResult, evaluateCondition, evaluateConditions, prioritizeAndRun, any, all, processResult, result, _result;
var ruleResult = new _ruleResult2.default(this.conditions, this.event, this.priority);
return regeneratorRuntime.wrap(function _callee6$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
ruleResult = new _ruleResult2.default(this.conditions, this.event, this.priority);
/**
* Evaluates the rule conditions
* @param {Condition} condition - condition to evaluate
* @return {Promise(true|false)} - resolves with the result of the condition evaluation
*/
var evaluateCondition = function evaluateCondition(condition) {
if (condition.isBooleanOperator()) {
var subConditions = condition[condition.operator];
var comparisonPromise = void 0;
if (condition.operator === 'all') {
comparisonPromise = all(subConditions);
} else {
comparisonPromise = any(subConditions);
}
// for booleans, rule passing is determined by the all/any result
return comparisonPromise.then(function (comparisonValue) {
var passes = comparisonValue === true;
condition.result = passes;
return passes;
});
} else {
return condition.evaluate(almanac, _this3.engine.operators).then(function (evaluationResult) {
var passes = evaluationResult.result;
condition.factResult = evaluationResult.leftHandSideValue;
condition.result = passes;
return passes;
}).catch(function (err) {
// any condition raising an undefined fact error is considered falsey when allowUndefinedFacts is enabled
if (_this3.engine.allowUndefinedFacts && err.code === 'UNDEFINED_FACT') return false;
throw err;
});
}
};
/**
* Evaluates the rule conditions
* @param {Condition} condition - condition to evaluate
* @return {Promise(true|false)} - resolves with the result of the condition evaluation
*/
/**
* Evalutes an array of conditions, using an 'every' or 'some' array operation
* @param {Condition[]} conditions
* @param {string(every|some)} array method to call for determining result
* @return {Promise(boolean)} whether conditions evaluated truthy or falsey based on condition evaluation + method
*/
var evaluateConditions = function evaluateConditions(conditions, method) {
if (!Array.isArray(conditions)) conditions = [conditions];
evaluateCondition = function () {
var _ref2 = _asyncToGenerator(regeneratorRuntime.mark(function _callee(condition) {
var comparisonValue, passes, subConditions, evaluationResult;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
comparisonValue = void 0;
passes = void 0;
return Promise.all(conditions.map(function (condition) {
return evaluateCondition(condition);
})).then(function (conditionResults) {
debug('rule::evaluateConditions results', conditionResults);
return method.call(conditionResults, function (result) {
return result === true;
});
});
};
if (!condition.isBooleanOperator()) {
_context.next = 16;
break;
}
/**
* Evaluates a set of conditions based on an 'all' or 'any' operator.
* First, orders the top level conditions based on priority
* Iterates over each priority set, evaluating each condition
* If any condition results in the rule to be guaranteed truthy or falsey,
* it will short-circuit and not bother evaluating any additional rules
* @param {Condition[]} conditions - conditions to be evaluated
* @param {string('all'|'any')} operator
* @return {Promise(boolean)} rule evaluation result
*/
var prioritizeAndRun = function prioritizeAndRun(conditions, operator) {
if (conditions.length === 0) {
return Promise.resolve(true);
}
var method = Array.prototype.some;
if (operator === 'all') {
method = Array.prototype.every;
}
var orderedSets = _this3.prioritizeConditions(conditions);
var cursor = Promise.resolve();
orderedSets.forEach(function (set) {
var stop = false;
cursor = cursor.then(function (setResult) {
// after the first set succeeds, don't fire off the remaining promises
if (operator === 'any' && setResult === true || stop) {
debug('prioritizeAndRun::detected truthy result; skipping remaining conditions');
stop = true;
return true;
}
subConditions = condition[condition.operator];
// after the first set fails, don't fire off the remaining promises
if (operator === 'all' && setResult === false || stop) {
debug('prioritizeAndRun::detected falsey result; skipping remaining conditions');
stop = true;
return false;
}
// all conditions passed; proceed with running next set in parallel
return evaluateConditions(set, method);
});
});
return cursor;
};
if (!(condition.operator === 'all')) {
_context.next = 10;
break;
}
/**
* Runs an 'any' boolean operator on an array of conditions
* @param {Condition[]} conditions to be evaluated
* @return {Promise(boolean)} condition evaluation result
*/
var any = function any(conditions) {
return prioritizeAndRun(conditions, 'any');
};
_context.next = 7;
return all(subConditions);
/**
* Runs an 'all' boolean operator on an array of conditions
* @param {Condition[]} conditions to be evaluated
* @return {Promise(boolean)} condition evaluation result
*/
var all = function all(conditions) {
return prioritizeAndRun(conditions, 'all');
};
case 7:
comparisonValue = _context.sent;
_context.next = 13;
break;
/**
* Emits based on rule evaluation result, and decorates ruleResult with 'result' property
* @param {Boolean} result
*/
var processResult = function processResult(result) {
ruleResult.setResult(result);
case 10:
_context.next = 12;
return any(subConditions);
if (result) _this3.emit('success', ruleResult.event, almanac, ruleResult);else _this3.emit('failure', ruleResult.event, almanac, ruleResult);
return ruleResult;
};
case 12:
comparisonValue = _context.sent;
case 13:
// for booleans, rule passing is determined by the all/any result
passes = comparisonValue === true;
_context.next = 31;
break;
case 16:
_context.prev = 16;
_context.next = 19;
return condition.evaluate(almanac, _this3.engine.operators, comparisonValue);
case 19:
evaluationResult = _context.sent;
passes = evaluationResult.result;
condition.factResult = evaluationResult.leftHandSideValue;
_context.next = 31;
break;
case 24:
_context.prev = 24;
_context.t0 = _context['catch'](16);
if (!(_this3.engine.allowUndefinedFacts && _context.t0.code === 'UNDEFINED_FACT')) {
_context.next = 30;
break;
}
passes = false;
_context.next = 31;
break;
case 30:
throw _context.t0;
case 31:
condition.result = passes;
return _context.abrupt('return', passes);
case 33:
case 'end':
return _context.stop();
}
}
}, _callee, _this3, [[16, 24]]);
}));
return function evaluateCondition(_x3) {
return _ref2.apply(this, arguments);
};
}();
/**
* Evalutes an array of conditions, using an 'every' or 'some' array operation
* @param {Condition[]} conditions
* @param {string(every|some)} array method to call for determining result
* @return {Promise(boolean)} whether conditions evaluated truthy or falsey based on condition evaluation + method
*/
evaluateConditions = function () {
var _ref3 = _asyncToGenerator(regeneratorRuntime.mark(function _callee2(conditions, method) {
var conditionResults;
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
if (!Array.isArray(conditions)) conditions = [conditions];
_context2.next = 3;
return Promise.all(conditions.map(function (condition) {
return evaluateCondition(condition);
}));
case 3:
conditionResults = _context2.sent;
debug('rule::evaluateConditions results', conditionResults);
return _context2.abrupt('return', method.call(conditionResults, function (result) {
return result === true;
}));
case 6:
case 'end':
return _context2.stop();
}
}
}, _callee2, _this3);
}));
return function evaluateConditions(_x4, _x5) {
return _ref3.apply(this, arguments);
};
}();
/**
* Evaluates a set of conditions based on an 'all' or 'any' operator.
* First, orders the top level conditions based on priority
* Iterates over each priority set, evaluating each condition
* If any condition results in the rule to be guaranteed truthy or falsey,
* it will short-circuit and not bother evaluating any additional rules
* @param {Condition[]} conditions - conditions to be evaluated
* @param {string('all'|'any')} operator
* @return {Promise(boolean)} rule evaluation result
*/
prioritizeAndRun = function () {
var _ref4 = _asyncToGenerator(regeneratorRuntime.mark(function _callee3(conditions, operator) {
var method, orderedSets, cursor;
return regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
if (!(conditions.length === 0)) {
_context3.next = 2;
break;
}
return _context3.abrupt('return', true);
case 2:
method = Array.prototype.some;
if (operator === 'all') {
method = Array.prototype.every;
}
orderedSets = _this3.prioritizeConditions(conditions);
cursor = Promise.resolve();
orderedSets.forEach(function (set) {
var stop = false;
cursor = cursor.then(function (setResult) {
// after the first set succeeds, don't fire off the remaining promises
if (operator === 'any' && setResult === true || stop) {
debug('prioritizeAndRun::detected truthy result; skipping remaining conditions');
stop = true;
return true;
}
// after the first set fails, don't fire off the remaining promises
if (operator === 'all' && setResult === false || stop) {
debug('prioritizeAndRun::detected falsey result; skipping remaining conditions');
stop = true;
return false;
}
// all conditions passed; proceed with running next set in parallel
return evaluateConditions(set, method);
});
});
return _context3.abrupt('return', cursor);
case 8:
case 'end':
return _context3.stop();
}
}
}, _callee3, _this3);
}));
return function prioritizeAndRun(_x6, _x7) {
return _ref4.apply(this, arguments);
};
}();
/**
* Runs an 'any' boolean operator on an array of conditions
* @param {Condition[]} conditions to be evaluated
* @return {Promise(boolean)} condition evaluation result
*/
any = function () {
var _ref5 = _asyncToGenerator(regeneratorRuntime.mark(function _callee4(conditions) {
return regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
return _context4.abrupt('return', prioritizeAndRun(conditions, 'any'));
case 1:
case 'end':
return _context4.stop();
}
}
}, _callee4, _this3);
}));
return function any(_x8) {
return _ref5.apply(this, arguments);
};
}();
/**
* Runs an 'all' boolean operator on an array of conditions
* @param {Condition[]} conditions to be evaluated
* @return {Promise(boolean)} condition evaluation result
*/
all = function () {
var _ref6 = _asyncToGenerator(regeneratorRuntime.mark(function _callee5(conditions) {
return regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
return _context5.abrupt('return', prioritizeAndRun(conditions, 'all'));
case 1:
case 'end':
return _context5.stop();
}
}
}, _callee5, _this3);
}));
return function all(_x9) {
return _ref6.apply(this, arguments);
};
}();
/**
* Emits based on rule evaluation result, and decorates ruleResult with 'result' property
* @param {Boolean} result
*/
processResult = function processResult(result) {
ruleResult.setResult(result);
if (result) _this3.emit('success', ruleResult.event, almanac, ruleResult);else _this3.emit('failure', ruleResult.event, almanac, ruleResult);
return ruleResult;
};
if (!ruleResult.conditions.any) {
_context6.next = 14;
break;
}
_context6.next = 10;
return any(ruleResult.conditions.any);
case 10:
result = _context6.sent;
return _context6.abrupt('return', processResult(result));
case 14:
_context6.next = 16;
return all(ruleResult.conditions.all);
case 16:
_result = _context6.sent;
return _context6.abrupt('return', processResult(_result));
case 18:
case 'end':
return _context6.stop();
}
}
}, _callee6, this);
}));
function evaluate(_x2) {
return _ref.apply(this, arguments);
if (ruleResult.conditions.any) {
return any(ruleResult.conditions.any).then(function (result) {
return processResult(result);
});
} else {
return all(ruleResult.conditions.all).then(function (result) {
return processResult(result);
});
}
return evaluate;
}()
}
}]);

@@ -513,0 +329,0 @@

{
"name": "json-rules-engine",
"version": "2.1.0",
"version": "2.2.0-alpha1",
"description": "Rules Engine expressed in simple json",

@@ -10,4 +10,4 @@ "main": "dist/index.js",

"lint:fix": "standard --fix",
"prepublish": "npm run compile",
"compile": "babel --stage 1 -d dist/ src/ && regenerator --no-cache-dir --include-runtime src/generator-runtime.js > dist/generator-runtime.js"
"prepublishOnly": "npm run build",
"build": "babel --stage 1 -d dist/ src/"
},

@@ -41,3 +41,3 @@ "repository": {

},
"author": "Cache Hamm <cdhamm@gmail.com>",
"author": "Cache Hamm <cache.hamm@gmail.com>",
"license": "ISC",

@@ -53,3 +53,2 @@ "bugs": {

"babel-loader": "7.1.2",
"babel-plugin-transform-async-to-generator": "^6.4.6",
"babel-polyfill": "6.26.0",

@@ -59,12 +58,12 @@ "babel-preset-es2015": "~6.24.1",

"babel-register": "6.26.0",
"chai": "4.1.2",
"chai-as-promised": "7.1.1",
"chai": "^4.1.2",
"chai-as-promised": "^7.1.1",
"colors": "~1.1.2",
"dirty-chai": "2.0.1",
"mocha": "4.0.1",
"regenerator": "0.11.0",
"sinon": "4.1.2",
"sinon-chai": "2.14.0",
"mocha": "^5.0.5",
"perfy": "^1.1.2",
"sinon": "^4.1.2",
"sinon-chai": "^2.14.0",
"snazzy": "^7.0.0",
"standard": "10.0.3"
"standard": "^10.0.3"
},

@@ -71,0 +70,0 @@ "dependencies": {

@@ -54,3 +54,3 @@ import { Fact } from '../src/index'

it('throws an exception if it encounters an undefined fact', () => {
return expect(almanac.factValue('bar')).to.eventually.be.rejectedWith(/Undefined fact: bar/)
return expect(almanac.factValue('bar')).to.be.rejectedWith(/Undefined fact: bar/)
})

@@ -84,7 +84,2 @@ })

})
it('raises an exception if fact DNE', () => {
almanac = new Almanac(new Map())
expect(almanac._getFact.bind(almanac, 'unknown')).to.throw(/Undefined fact/)
})
})

@@ -91,0 +86,0 @@

@@ -6,7 +6,6 @@ 'use strict'

describe('Fact', () => {
function subject (id, definition, options) {
return new Fact(id, definition, options)
}
describe('Fact::constructor', () => {
function subject (id, definition, options) {
return new Fact(id, definition, options)
}
it('works for constant facts', () => {

@@ -40,2 +39,16 @@ let fact = subject('factId', 10)

})
describe('Fact::types', () => {
it('initializes facts with method values as dynamic', () => {
let fact = subject('factId', () => {})
expect(fact.type).to.equal(Fact.DYNAMIC)
expect(fact.isDynamic()).to.be.true()
})
it('initializes facts with non-methods as constant', () => {
let fact = subject('factId', 2)
expect(fact.type).to.equal(Fact.CONSTANT)
expect(fact.isConstant()).to.be.true()
})
})
})

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc