json-rules-engine
Advanced tools
Comparing version 6.2.0 to 6.3.0
@@ -43,3 +43,3 @@ 'use strict'; | ||
} | ||
} else { | ||
} else if (!Object.prototype.hasOwnProperty.call(properties, 'condition')) { | ||
if (!Object.prototype.hasOwnProperty.call(properties, 'fact')) throw new Error('Condition: constructor "fact" property required'); | ||
@@ -85,2 +85,4 @@ if (!Object.prototype.hasOwnProperty.call(properties, 'operator')) throw new Error('Condition: constructor "operator" property required'); | ||
} | ||
} else if (this.isConditionReference()) { | ||
props.condition = this.condition; | ||
} else { | ||
@@ -185,2 +187,13 @@ props.operator = this.operator; | ||
} | ||
/** | ||
* Whether the condition represents a reference to a condition | ||
* @returns {Boolean} | ||
*/ | ||
}, { | ||
key: 'isConditionReference', | ||
value: function isConditionReference() { | ||
return Object.prototype.hasOwnProperty.call(this, 'condition'); | ||
} | ||
}], [{ | ||
@@ -187,0 +200,0 @@ key: 'booleanOperator', |
@@ -38,2 +38,6 @@ 'use strict'; | ||
var _condition = require('./condition'); | ||
var _condition2 = _interopRequireDefault(_condition); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -68,5 +72,7 @@ | ||
_this.allowUndefinedFacts = options.allowUndefinedFacts || false; | ||
_this.allowUndefinedConditions = options.allowUndefinedConditions || false; | ||
_this.pathResolver = options.pathResolver; | ||
_this.operators = new Map(); | ||
_this.facts = new Map(); | ||
_this.conditions = new Map(); | ||
_this.status = READY; | ||
@@ -160,2 +166,33 @@ rules.map(function (r) { | ||
/** | ||
* sets a condition that can be referenced by the given name. | ||
* If a condition with the given name has already been set this will replace it. | ||
* @param {string} name - the name of the condition to be referenced by rules. | ||
* @param {object} conditions - the conditions to use when the condition is referenced. | ||
*/ | ||
}, { | ||
key: 'setCondition', | ||
value: function setCondition(name, conditions) { | ||
if (!name) throw new Error('Engine: setCondition() requires name'); | ||
if (!conditions) throw new Error('Engine: setCondition() requires conditions'); | ||
if (!Object.prototype.hasOwnProperty.call(conditions, 'all') && !Object.prototype.hasOwnProperty.call(conditions, 'any') && !Object.prototype.hasOwnProperty.call(conditions, 'not') && !Object.prototype.hasOwnProperty.call(conditions, 'condition')) { | ||
throw new Error('"conditions" root must contain a single instance of "all", "any", "not", or "condition"'); | ||
} | ||
this.conditions.set(name, new _condition2.default(conditions)); | ||
return this; | ||
} | ||
/** | ||
* Removes a condition that has previously been added to this engine | ||
* @param {string} name - the name of the condition to remove. | ||
* @returns true if the condition existed, otherwise false | ||
*/ | ||
}, { | ||
key: 'removeCondition', | ||
value: function removeCondition(name) { | ||
return this.conditions.delete(name); | ||
} | ||
/** | ||
* Add a custom operator definition | ||
@@ -162,0 +199,0 @@ * @param {string} operatorOrName - operator identifier within the condition; i.e. instead of 'equals', 'greaterThan', etc |
@@ -21,2 +21,6 @@ 'use strict'; | ||
var _clone = require('clone'); | ||
var _clone2 = _interopRequireDefault(_clone); | ||
var _eventemitter = require('eventemitter2'); | ||
@@ -115,4 +119,4 @@ | ||
value: function setConditions(conditions) { | ||
if (!Object.prototype.hasOwnProperty.call(conditions, 'all') && !Object.prototype.hasOwnProperty.call(conditions, 'any') && !Object.prototype.hasOwnProperty.call(conditions, 'not')) { | ||
throw new Error('"conditions" root must contain a single instance of "all", "any", or "not"'); | ||
if (!Object.prototype.hasOwnProperty.call(conditions, 'all') && !Object.prototype.hasOwnProperty.call(conditions, 'any') && !Object.prototype.hasOwnProperty.call(conditions, 'not') && !Object.prototype.hasOwnProperty.call(conditions, 'condition')) { | ||
throw new Error('"conditions" root must contain a single instance of "all", "any", "not", or "condition"'); | ||
} | ||
@@ -267,3 +271,5 @@ this.conditions = new _condition2.default(conditions); | ||
var evaluateCondition = function evaluateCondition(condition) { | ||
if (condition.isBooleanOperator()) { | ||
if (condition.isConditionReference()) { | ||
return realize(_this3.engine.conditions.get(condition.condition), condition); | ||
} else if (condition.isBooleanOperator()) { | ||
var subConditions = condition[condition.operator]; | ||
@@ -398,2 +404,19 @@ var comparisonPromise = void 0; | ||
var realize = function realize(condition, conditionReference) { | ||
if (!condition) { | ||
if (_this3.engine.allowUndefinedConditions) { | ||
// undefined conditions always fail | ||
conditionReference.result = false; | ||
return Promise.resolve(false); | ||
} else { | ||
throw new Error('No condition ' + conditionReference.condition + ' exists'); | ||
} | ||
} else { | ||
// project the referenced condition onto reference object and evaluate it. | ||
delete conditionReference.condition; | ||
Object.assign(conditionReference, (0, _clone2.default)(condition)); | ||
return evaluateCondition(conditionReference); | ||
} | ||
}; | ||
/** | ||
@@ -400,0 +423,0 @@ * Emits based on rule evaluation result, and decorates ruleResult with 'result' property |
{ | ||
"name": "json-rules-engine", | ||
"version": "6.2.0", | ||
"version": "6.3.0", | ||
"description": "Rules Engine expressed in simple json", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
export interface EngineOptions { | ||
allowUndefinedFacts?: boolean; | ||
allowUndefinedConditions?: boolean; | ||
pathResolver?: PathResolver; | ||
@@ -26,2 +27,5 @@ } | ||
setCondition(name: string, conditions: TopLevelCondition): this; | ||
removeCondition(name: string): boolean; | ||
addOperator(operator: Operator): Map<string, Operator>; | ||
@@ -102,6 +106,3 @@ addOperator<A, B>( | ||
export type PathResolver = ( | ||
value: object, | ||
path: string, | ||
) => any; | ||
export type PathResolver = (value: object, path: string) => any; | ||
@@ -161,5 +162,22 @@ export type EventHandler = ( | ||
type NestedCondition = ConditionProperties | TopLevelCondition; | ||
type AllConditions = { all: NestedCondition[]; name?: string; priority?: number; }; | ||
type AnyConditions = { any: NestedCondition[]; name?: string; priority?: number; }; | ||
type NotConditions = { not: NestedCondition; name?: string; priority?: number; }; | ||
export type TopLevelCondition = AllConditions | AnyConditions | NotConditions; | ||
type AllConditions = { | ||
all: NestedCondition[]; | ||
name?: string; | ||
priority?: number; | ||
}; | ||
type AnyConditions = { | ||
any: NestedCondition[]; | ||
name?: string; | ||
priority?: number; | ||
}; | ||
type NotConditions = { not: NestedCondition; name?: string; priority?: number }; | ||
type ConditionReference = { | ||
condition: string; | ||
name?: string; | ||
priority?: number; | ||
}; | ||
export type TopLevelCondition = | ||
| AllConditions | ||
| AnyConditions | ||
| NotConditions | ||
| ConditionReference; |
83564
1546