json-rules-engine
Advanced tools
Comparing version 6.5.0 to 6.6.0
@@ -23,6 +23,2 @@ 'use strict'; | ||
var _lodash = require('lodash.isobjectlike'); | ||
var _lodash2 = _interopRequireDefault(_lodash); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -163,3 +159,3 @@ | ||
} | ||
(0, _debug2.default)('almanac::addFact id:' + factId); | ||
(0, _debug2.default)('almanac::addFact', { id: factId }); | ||
this.factMap.set(factId, fact); | ||
@@ -182,3 +178,3 @@ if (fact.isConstant()) { | ||
value: function addRuntimeFact(factId, value) { | ||
(0, _debug2.default)('almanac::addRuntimeFact id:' + factId); | ||
(0, _debug2.default)('almanac::addRuntimeFact', { id: factId }); | ||
var fact = new _fact2.default(factId, value); | ||
@@ -221,5 +217,5 @@ return this._addConstantFact(fact); | ||
factValuePromise = Promise.resolve(cacheVal); | ||
(0, _debug2.default)('almanac::factValue cache hit for fact:' + factId); | ||
(0, _debug2.default)('almanac::factValue cache hit for fact', { id: factId }); | ||
} else { | ||
(0, _debug2.default)('almanac::factValue cache miss for fact:' + factId + '; calculating'); | ||
(0, _debug2.default)('almanac::factValue cache miss, calculating', { id: factId }); | ||
factValuePromise = this._setFactValue(fact, params, fact.calculate(params, this)); | ||
@@ -229,10 +225,10 @@ } | ||
if (path) { | ||
(0, _debug2.default)('condition::evaluate extracting object property ' + path); | ||
(0, _debug2.default)('condition::evaluate extracting object', { property: path }); | ||
return factValuePromise.then(function (factValue) { | ||
if ((0, _lodash2.default)(factValue)) { | ||
if (factValue != null && (typeof factValue === 'undefined' ? 'undefined' : _typeof(factValue)) === 'object') { | ||
var pathValue = _this.pathResolver(factValue, path); | ||
(0, _debug2.default)('condition::evaluate extracting object property ' + path + ', received: ' + JSON.stringify(pathValue)); | ||
(0, _debug2.default)('condition::evaluate extracting object', { property: path, received: pathValue }); | ||
return pathValue; | ||
} else { | ||
(0, _debug2.default)('condition::evaluate could not compute object path(' + path + ') of non-object: ' + factValue + ' <' + (typeof factValue === 'undefined' ? 'undefined' : _typeof(factValue)) + '>; continuing with ' + factValue); | ||
(0, _debug2.default)('condition::evaluate could not compute object path of non-object', { path: path, factValue: factValue, type: typeof factValue === 'undefined' ? 'undefined' : _typeof(factValue) }); | ||
return factValue; | ||
@@ -253,3 +249,3 @@ } | ||
value: function getValue(value) { | ||
if ((0, _lodash2.default)(value) && Object.prototype.hasOwnProperty.call(value, 'fact')) { | ||
if (value != null && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && Object.prototype.hasOwnProperty.call(value, 'fact')) { | ||
// value = { fact: 'xyz' } | ||
@@ -256,0 +252,0 @@ return this.factValue(value.fact, value.params, value.path); |
@@ -149,3 +149,8 @@ 'use strict'; | ||
var result = op.evaluate(leftHandSideValue, rightHandSideValue); | ||
(0, _debug2.default)('condition::evaluate <' + JSON.stringify(leftHandSideValue) + ' ' + _this.operator + ' ' + JSON.stringify(rightHandSideValue) + '?> (' + result + ')'); | ||
(0, _debug2.default)('condition::evaluate', { | ||
leftHandSideValue: leftHandSideValue, | ||
operator: _this.operator, | ||
rightHandSideValue: rightHandSideValue, | ||
result: result | ||
}); | ||
return { | ||
@@ -152,0 +157,0 @@ result: result, |
@@ -6,7 +6,7 @@ 'use strict'; | ||
}); | ||
exports.default = debug; | ||
function debug(message) { | ||
function createDebug() { | ||
try { | ||
if (typeof process !== 'undefined' && process.env && process.env.DEBUG && process.env.DEBUG.match(/json-rules-engine/) || typeof window !== 'undefined' && window.localStorage && window.localStorage.debug && window.localStorage.debug.match(/json-rules-engine/)) { | ||
console.log(message); | ||
return console.debug.bind(console); | ||
} | ||
@@ -16,2 +16,5 @@ } catch (ex) { | ||
} | ||
} | ||
return function () {}; | ||
} | ||
exports.default = createDebug(); |
@@ -20,6 +20,2 @@ 'use strict'; | ||
var _operator = require('./operator'); | ||
var _operator2 = _interopRequireDefault(_operator); | ||
var _almanac = require('./almanac'); | ||
@@ -37,2 +33,6 @@ | ||
var _engineDefaultOperatorDecorators = require('./engine-default-operator-decorators'); | ||
var _engineDefaultOperatorDecorators2 = _interopRequireDefault(_engineDefaultOperatorDecorators); | ||
var _debug = require('./debug'); | ||
@@ -46,2 +46,6 @@ | ||
var _operatorMap = require('./operator-map'); | ||
var _operatorMap2 = _interopRequireDefault(_operatorMap); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -79,3 +83,3 @@ | ||
_this.pathResolver = options.pathResolver; | ||
_this.operators = new Map(); | ||
_this.operators = new _operatorMap2.default(); | ||
_this.facts = new Map(); | ||
@@ -90,2 +94,5 @@ _this.conditions = new Map(); | ||
}); | ||
_engineDefaultOperatorDecorators2.default.map(function (d) { | ||
return _this.addOperatorDecorator(d); | ||
}); | ||
return _this; | ||
@@ -211,10 +218,3 @@ } | ||
value: function addOperator(operatorOrName, cb) { | ||
var operator = void 0; | ||
if (operatorOrName instanceof _operator2.default) { | ||
operator = operatorOrName; | ||
} else { | ||
operator = new _operator2.default(operatorOrName, cb); | ||
} | ||
(0, _debug2.default)('engine::addOperator name:' + operator.name); | ||
this.operators.set(operator.name, operator); | ||
this.operators.addOperator(operatorOrName, cb); | ||
} | ||
@@ -225,3 +225,2 @@ | ||
* @param {string} operatorOrName - operator identifier within the condition; i.e. instead of 'equals', 'greaterThan', etc | ||
* @param {function(factValue, jsonValue)} callback - the method to execute when the operator is encountered. | ||
*/ | ||
@@ -232,13 +231,29 @@ | ||
value: function removeOperator(operatorOrName) { | ||
var operatorName = void 0; | ||
if (operatorOrName instanceof _operator2.default) { | ||
operatorName = operatorOrName.name; | ||
} else { | ||
operatorName = operatorOrName; | ||
} | ||
return this.operators.removeOperator(operatorOrName); | ||
} | ||
return this.operators.delete(operatorName); | ||
/** | ||
* Add a custom operator decorator | ||
* @param {string} decoratorOrName - decorator identifier within the condition; i.e. instead of 'someFact', 'everyValue', etc | ||
* @param {function(factValue, jsonValue, next)} callback - the method to execute when the decorator is encountered. | ||
*/ | ||
}, { | ||
key: 'addOperatorDecorator', | ||
value: function addOperatorDecorator(decoratorOrName, cb) { | ||
this.operators.addOperatorDecorator(decoratorOrName, cb); | ||
} | ||
/** | ||
* Remove a custom operator decorator | ||
* @param {string} decoratorOrName - decorator identifier within the condition; i.e. instead of 'someFact', 'everyValue', etc | ||
*/ | ||
}, { | ||
key: 'removeOperatorDecorator', | ||
value: function removeOperatorDecorator(decoratorOrName) { | ||
return this.operators.removeOperatorDecorator(decoratorOrName); | ||
} | ||
/** | ||
* Add a fact definition to the engine. Facts are called by rules as they are evaluated. | ||
@@ -261,3 +276,3 @@ * @param {object|Fact} id - fact identifier or instance of Fact | ||
} | ||
(0, _debug2.default)('engine::addFact id:' + factId); | ||
(0, _debug2.default)('engine::addFact', { id: factId }); | ||
this.facts.set(factId, fact); | ||
@@ -350,7 +365,7 @@ return this; | ||
if (_this2.status !== RUNNING) { | ||
(0, _debug2.default)('engine::run status:' + _this2.status + '; skipping remaining rules'); | ||
(0, _debug2.default)('engine::run, skipping remaining rules', { status: _this2.status }); | ||
return Promise.resolve(); | ||
} | ||
return rule.evaluate(almanac).then(function (ruleResult) { | ||
(0, _debug2.default)('engine::run ruleResult:' + ruleResult.result); | ||
(0, _debug2.default)('engine::run', { ruleResult: ruleResult.result }); | ||
almanac.addResult(ruleResult); | ||
@@ -405,3 +420,3 @@ if (ruleResult.result) { | ||
almanac.addFact(fact); | ||
(0, _debug2.default)('engine::run initialized runtime fact:' + fact.id + ' with ' + fact.value + '<' + _typeof(fact.value) + '>'); | ||
(0, _debug2.default)('engine::run initialized runtime fact', { id: fact.id, value: fact.value, type: _typeof(fact.value) }); | ||
} | ||
@@ -408,0 +423,0 @@ var orderedSets = this.prioritizeRules(); |
@@ -6,3 +6,3 @@ 'use strict'; | ||
}); | ||
exports.Almanac = exports.Engine = exports.Operator = exports.Rule = exports.Fact = undefined; | ||
exports.OperatorDecorator = exports.Almanac = exports.Engine = exports.Operator = exports.Rule = exports.Fact = undefined; | ||
@@ -33,2 +33,6 @@ exports.default = function (rules, options) { | ||
var _operatorDecorator = require('./operator-decorator'); | ||
var _operatorDecorator2 = _interopRequireDefault(_operatorDecorator); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -40,2 +44,3 @@ | ||
exports.Engine = _engine2.default; | ||
exports.Almanac = _almanac2.default; | ||
exports.Almanac = _almanac2.default; | ||
exports.OperatorDecorator = _operatorDecorator2.default; |
@@ -7,2 +7,4 @@ 'use strict'; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
@@ -14,6 +16,2 @@ | ||
var _lodash = require('lodash.isobjectlike'); | ||
var _lodash2 = _interopRequireDefault(_lodash); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -44,3 +42,3 @@ | ||
if ((0, _lodash2.default)(this.event.params)) { | ||
if (this.event.params !== null && _typeof(this.event.params) === 'object') { | ||
var updates = []; | ||
@@ -47,0 +45,0 @@ |
@@ -311,3 +311,3 @@ 'use strict'; | ||
})).then(function (conditionResults) { | ||
(0, _debug2.default)('rule::evaluateConditions results', conditionResults); | ||
(0, _debug2.default)('rule::evaluateConditions', { results: conditionResults }); | ||
return method.call(conditionResults, function (result) { | ||
@@ -339,8 +339,4 @@ return result === true; | ||
} | ||
var method = Array.prototype.some; | ||
if (operator === 'all') { | ||
method = Array.prototype.every; | ||
} | ||
var orderedSets = _this3.prioritizeConditions(conditions); | ||
var cursor = Promise.resolve(); | ||
var cursor = Promise.resolve(operator === 'all'); | ||
// use for() loop over Array.forEach to support IE8 without polyfill | ||
@@ -350,19 +346,5 @@ | ||
var set = orderedSets[i]; | ||
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) { | ||
(0, _debug2.default)('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) { | ||
(0, _debug2.default)('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); | ||
// rely on the short-circuiting behavior of || and && to avoid evaluating subsequent conditions | ||
return operator === 'any' ? setResult || evaluateConditions(set, Array.prototype.some) : setResult && evaluateConditions(set, Array.prototype.every); | ||
}); | ||
@@ -369,0 +351,0 @@ }; |
{ | ||
"name": "json-rules-engine", | ||
"version": "6.5.0", | ||
"version": "6.6.0", | ||
"description": "Rules Engine expressed in simple json", | ||
@@ -92,5 +92,4 @@ "main": "dist/index.js", | ||
"hash-it": "^6.0.0", | ||
"jsonpath-plus": "^7.2.0", | ||
"lodash.isobjectlike": "^4.0.0" | ||
"jsonpath-plus": "^7.2.0" | ||
} | ||
} |
@@ -38,9 +38,13 @@ export interface AlmanacOptions { | ||
addOperator(operator: Operator): Map<string, Operator>; | ||
addOperator(operator: Operator): void; | ||
addOperator<A, B>( | ||
operatorName: string, | ||
callback: OperatorEvaluator<A, B> | ||
): Map<string, Operator>; | ||
): void; | ||
removeOperator(operator: Operator | string): boolean; | ||
addOperatorDecorator(decorator: OperatorDecorator): void; | ||
addOperatorDecorator<A, B, NextA, NextB>(decoratorName: string, callback: OperatorDecoratorEvaluator<A, B, NextA, NextB>): void; | ||
removeOperatorDecorator(decorator: OperatorDecorator | string): boolean; | ||
addFact<T>(fact: Fact<T>): this; | ||
@@ -55,5 +59,3 @@ addFact<T>( | ||
on(eventName: "success", handler: EventHandler): this; | ||
on(eventName: "failure", handler: EventHandler): this; | ||
on(eventName: string, handler: EventHandler): this; | ||
on<T = Event>(eventName: string, handler: EventHandler<T>): this; | ||
@@ -77,2 +79,15 @@ run(facts?: Record<string, any>, runOptions?: RunOptions): Promise<EngineResult>; | ||
export interface OperatorDecoratorEvaluator<A, B, NextA, NextB> { | ||
(factValue: A, compareToValue: B, next: OperatorEvaluator<NextA, NextB>): boolean | ||
} | ||
export class OperatorDecorator<A = unknown, B = unknown, NextA = unknown, NextB = unknown> { | ||
public name: string; | ||
constructor( | ||
name: string, | ||
evaluator: OperatorDecoratorEvaluator<A, B, NextA, NextB>, | ||
validator?: (factValue: A) => boolean | ||
) | ||
} | ||
export class Almanac { | ||
@@ -125,4 +140,4 @@ constructor(options?: AlmanacOptions); | ||
export type EventHandler = ( | ||
event: Event, | ||
export type EventHandler<T = Event> = ( | ||
event: T, | ||
almanac: Almanac, | ||
@@ -129,0 +144,0 @@ ruleResult: RuleResult |
99205
4
23
1889
- Removedlodash.isobjectlike@^4.0.0
- Removedlodash.isobjectlike@4.0.0(transitive)