|
3 | 3 | import Condition from './condition' |
4 | 4 | import RuleResult from './rule-result' |
5 | 5 | import debug from './debug' |
| 6 | +import deepClone from 'clone' |
6 | 7 | import EventEmitter from 'eventemitter2' |
7 | 8 |
|
8 | 9 | class Rule extends EventEmitter { |
@@ -70,8 +71,8 @@ class Rule extends EventEmitter { |
70 | 71 | * @param {object} conditions - conditions, root element must be a boolean operator |
71 | 72 | */ |
72 | 73 | setConditions (conditions) { |
73 | | - if (!Object.prototype.hasOwnProperty.call(conditions, 'all') && !Object.prototype.hasOwnProperty.call(conditions, 'any') && !Object.prototype.hasOwnProperty.call(conditions, 'not')) { |
74 | | - throw new Error('"conditions" root must contain a single instance of "all", "any", or "not"') |
| 74 | + 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')) { |
| 75 | + throw new Error('"conditions" root must contain a single instance of "all", "any", "not", or "condition"') |
75 | 76 | } |
76 | 77 | this.conditions = new Condition(conditions) |
77 | 78 | return this |
@@ -188,7 +189,9 @@ class Rule extends EventEmitter { |
188 | 189 | * @return {Promise(true|false)} - resolves with the result of the condition evaluation |
189 | 190 | */ |
190 | 191 | const evaluateCondition = (condition) => { |
191 | | - if (condition.isBooleanOperator()) { |
| 192 | + if (condition.isConditionReference()) { |
| 193 | + return realize(this.engine.conditions.get(condition.condition), condition) |
| 194 | + } else if (condition.isBooleanOperator()) { |
192 | 195 | const subConditions = condition[condition.operator] |
193 | 196 | let comparisonPromise |
194 | 197 | if (condition.operator === 'all') { |
@@ -309,6 +312,23 @@ class Rule extends EventEmitter { |
309 | 312 | return prioritizeAndRun([condition], 'not').then(result => !result) |
310 | 313 | } |
311 | 314 |
|
| 315 | + const realize = (condition, conditionReference) => { |
| 316 | + if (!condition) { |
| 317 | + if (this.engine.allowUndefinedConditions) { |
| 318 | + // undefined conditions always fail |
| 319 | + conditionReference.result = false |
| 320 | + return Promise.resolve(false) |
| 321 | + } else { |
| 322 | + throw new Error(`No condition ${conditionReference.condition} exists`) |
| 323 | + } |
| 324 | + } else { |
| 325 | + // project the referenced condition onto reference object and evaluate it. |
| 326 | + delete conditionReference.condition |
| 327 | + Object.assign(conditionReference, deepClone(condition)) |
| 328 | + return evaluateCondition(conditionReference) |
| 329 | + } |
| 330 | + } |
| 331 | + |
312 | 332 | /** |
313 | 333 | * Emits based on rule evaluation result, and decorates ruleResult with 'result' property |
314 | 334 | * @param {RuleResult} ruleResult |
|
0 commit comments