|
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