| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent a95417c commit e2347d4
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -128,42 +128,22 @@ the same priority may still emit events, even though the engine has been told to | |||
| 128 | 128 | engine.stop() | |
| 129 | 129 | ``` | |
| 130 | 130 | ||
| 131 | - ### engine.on(String event, Function callback) -> Engine | ||
| 132 | - | ||
| 133 | - Listens for events emitted as rules are being evaluated. "event" is determined by the [rule event](./rules.md#Events). | ||
| 134 | - | ||
| 135 | - ```js | ||
| 136 | - let rule = new Rule({ | ||
| 137 | - event: { | ||
| 138 | - type: 'my-event', | ||
| 139 | - params: { | ||
| 140 | - customValue: 'my-custom-value' | ||
| 141 | - } | ||
| 142 | - } | ||
| 143 | - }) | ||
| 144 | - | ||
| 145 | - // whenever rule is evaluated and conditions pass, 'my-event' will trigger | ||
| 146 | - engine.on('my-event', function(params) { | ||
| 147 | - console.log(params) // { customValue: 'my-custom-value' } | ||
| 148 | - }) | ||
| 149 | - ``` | ||
| 150 | - | ||
| 151 | 131 | There are two generic event emissions that trigger automatically: | |
| 152 | 132 | ||
| 153 | 133 | #### ```engine.on('success', cb)``` | |
| 154 | 134 | ||
| 155 | - Fires when *any* rule passes. In this case the callback will receive the entire event object. | ||
| 135 | + Fires when a rule passes. In this case the callback will receive the entire event object. | ||
| 156 | 136 | ||
| 157 | 137 | ```js | |
| 158 | - engine.on('success', function(event, almanac) { | ||
| 138 | + engine.on('success', function(event, almanac, ruleResult) { | ||
| 159 | 139 | }) | |
| 160 | 140 | ``` | |
| 161 | 141 | ||
| 162 | 142 | #### ```engine.on('failure', cb)``` | |
| 163 | 143 | ||
| 164 | - Companion to 'success', except fires when any rule fails. | ||
| 144 | + Companion to 'success', except fires when a rule fails. | ||
| 165 | 145 | ||
| 166 | 146 | ```js | |
| 167 | - engine.on('failure', function(rule, almanac) { | ||
| 147 | + engine.on('failure', function(rule, almanac, ruleResult) { | ||
| 168 | 148 | }) | |
| 169 | 149 | ``` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -221,16 +221,16 @@ See the [fact-comparison](../examples/08-fact-comparison.js) example | |||
| 221 | 221 | ||
| 222 | 222 | Listen for `success` and `failure` events emitted when rule is evaluated. | |
| 223 | 223 | ||
| 224 | - #### ```rule.on('success', Function(Object event, Almanac almanac))``` | ||
| 224 | + #### ```rule.on('success', Function(Object event, Almanac almanac, RuleResult ruleResult))``` | ||
| 225 | 225 | ||
| 226 | 226 | ```js | |
| 227 | 227 | // whenever rule is evaluated and the conditions pass, 'success' will trigger | |
| 228 | - rule.on('success', function(event, almanac) { | ||
| 228 | + rule.on('success', function(event, almanac, ruleResult) { | ||
| 229 | 229 | console.log(event) // { type: 'my-event', params: { id: 1 } | |
| 230 | 230 | }) | |
| 231 | 231 | ``` | |
| 232 | 232 | ||
| 233 | - #### ```rule.on('failure', Function(Object event, Almanac almanac))``` | ||
| 233 | + #### ```rule.on('failure', Function(Object event, Almanac almanac, RuleResult ruleResult))``` | ||
| 234 | 234 | ||
| 235 | 235 | Companion to `success`, except fires when the rule fails. | |
| 236 | 236 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -66,6 +66,7 @@ | |||
| 66 | 66 | }, | |
| 67 | 67 | "dependencies": { | |
| 68 | 68 | "debug": "2.2.0", | |
| 69 | + "lodash.clonedeep": "4.5.0", | ||
| 69 | 70 | "lodash.isplainobject": "4.0.6", | |
| 70 | 71 | "object-hash": "1.1.5", | |
| 71 | 72 | "params": "0.1.1", | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -144,14 +144,15 @@ class Engine extends EventEmitter { | |||
| 144 | 144 | debug(`engine::run status:${this.status}; skipping remaining rules`) | |
| 145 | 145 | return | |
| 146 | 146 | } | |
| 147 | - return rule.evaluate(almanac).then((rulePasses) => { | ||
| 148 | - debug(`engine::run ruleResult:${rulePasses}`) | ||
| 149 | - if (rulePasses) { | ||
| 150 | - this.emit('success', rule.event, almanac) | ||
| 151 | - this.emit(rule.event.type, rule.event.params, this) | ||
| 147 | + return rule.evaluate(almanac).then((ruleResult) => { | ||
| 148 | + debug(`engine::run ruleResult:${ruleResult.result}`) | ||
| 149 | + if (ruleResult.result) { | ||
| 150 | + this.emit('success', rule.event, almanac, ruleResult) | ||
| 151 | + this.emit(rule.event.type, rule.event.params, this) // DEPRECATED; todo - remove from docs | ||
| 152 | 152 | almanac.factValue('success-events', { event: rule.event }) | |
| 153 | + } else { | ||
| 154 | + this.emit('failure', rule, almanac, ruleResult) | ||
| 153 | 155 | } | |
| 154 | - if (!rulePasses) this.emit('failure', rule, almanac) | ||
| 155 | 156 | }) | |
| 156 | 157 | })) | |
| 157 | 158 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3,6 +3,7 @@ | |||
| 3 | 3 | import params from 'params' | |
| 4 | 4 | import Condition from './condition' | |
| 5 | 5 | import { EventEmitter } from 'events' | |
| 6 | + import deepClone from 'lodash.clonedeep' | ||
| 6 | 7 | ||
| 7 | 8 | let debug = require('debug')('json-rules-engine') | |
| 8 | 9 | ||
@@ -124,9 +125,15 @@ class Rule extends EventEmitter { | |||
| 124 | 125 | /** | |
| 125 | 126 | * Evaluates the rule, starting with the root boolean operator and recursing down | |
| 126 | 127 | * All evaluation is done within the context of an almanac | |
| 127 | - * @return {Promise(boolean)} rule evaluation result | ||
| 128 | + * @return {Promise(RuleResult)} rule evaluation result | ||
| 128 | 129 | */ | |
| 129 | 130 | async evaluate (almanac) { | |
| 131 | + let ruleResult = { | ||
| 132 | + conditions: deepClone(this.conditions), | ||
| 133 | + event: deepClone(this.event), | ||
| 134 | + priority: deepClone(this.priority) | ||
| 135 | + } | ||
| 136 | + | ||
| 130 | 137 | /** | |
| 131 | 138 | * Evaluates the rule conditions | |
| 132 | 139 | * @param {Condition} condition - condition to evaluate | |
@@ -153,11 +160,11 @@ class Rule extends EventEmitter { | |||
| 153 | 160 | else throw err | |
| 154 | 161 | } | |
| 155 | 162 | } | |
| 156 | - | ||
| 163 | + condition.result = passes | ||
| 157 | 164 | if (passes) { | |
| 158 | - this.emit('success', this.event, almanac) | ||
| 165 | + this.emit('success', this.event, almanac, ruleResult) | ||
| 159 | 166 | } else { | |
| 160 | - this.emit('failure', this.event, almanac) | ||
| 167 | + this.emit('failure', this.event, almanac, ruleResult) | ||
| 161 | 168 | } | |
| 162 | 169 | return passes | |
| 163 | 170 | } | |
@@ -238,10 +245,14 @@ class Rule extends EventEmitter { | |||
| 238 | 245 | return prioritizeAndRun(conditions, 'all') | |
| 239 | 246 | } | |
| 240 | 247 | ||
| 241 | - if (this.conditions.any) { | ||
| 242 | - return await any(this.conditions.any) | ||
| 248 | + if (ruleResult.conditions.any) { | ||
| 249 | + let result = await any(ruleResult.conditions.any) | ||
| 250 | + ruleResult.result = result | ||
| 251 | + return ruleResult | ||
| 243 | 252 | } else { | |
| 244 | - return await all(this.conditions.all) | ||
| 253 | + let result = await all(ruleResult.conditions.all) | ||
| 254 | + ruleResult.result = result | ||
| 255 | + return ruleResult | ||
| 245 | 256 | } | |
| 246 | 257 | } | |
| 247 | 258 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -30,10 +30,12 @@ describe('Engine: event', () => { | |||
| 30 | 30 | ||
| 31 | 31 | describe('engine events', () => { | |
| 32 | 32 | it('passes the event type and params', (done) => { | |
| 33 | - engine.on('success', function (a, engine) { | ||
| 33 | + engine.on('success', function (a, almanac, ruleResult) { | ||
| 34 | 34 | try { | |
| 35 | 35 | expect(a).to.eql(event) | |
| 36 | - expect(engine).to.eql(engine) | ||
| 36 | + expect(almanac).to.be.an.instanceof(Almanac) | ||
| 37 | + expect(ruleResult.result).to.be.true() | ||
| 38 | + expect(ruleResult.conditions.any[0].result).to.be.true() | ||
| 37 | 39 | } catch (e) { return done(e) } | |
| 38 | 40 | done() | |
| 39 | 41 | }) | |
@@ -71,7 +73,7 @@ describe('Engine: event', () => { | |||
| 71 | 73 | }) | |
| 72 | 74 | engine.addRule(drinkOrderRule) | |
| 73 | 75 | return new Promise((resolve, reject) => { | |
| 74 | - engine.on('success', function (event, almanac) { | ||
| 76 | + engine.on('success', function (event, almanac, ruleResult) { | ||
| 75 | 77 | switch (event.type) { | |
| 76 | 78 | case 'setDrinkingFlag': | |
| 77 | 79 | almanac.addRuntimeFact('canOrderDrinks', event.params.canOrderDrinks) | |
@@ -91,11 +93,12 @@ describe('Engine: event', () => { | |||
| 91 | 93 | it('on-success, it passes the event type and params', (done) => { | |
| 92 | 94 | let failureSpy = sinon.spy() | |
| 93 | 95 | let rule = engine.rules[0] | |
| 94 | - rule.on('success', function (e, a) { | ||
| 96 | + rule.on('success', function (e, almanac, ruleResult) { | ||
| 95 | 97 | try { | |
| 96 | 98 | expect(e).to.eql(event) | |
| 97 | - expect(a).to.be.an.instanceof(Almanac) | ||
| 99 | + expect(almanac).to.be.an.instanceof(Almanac) | ||
| 98 | 100 | expect(failureSpy.callCount).to.equal(0) | |
| 101 | + expect(ruleResult.conditions.any[0].result).to.be.true() | ||
| 99 | 102 | } catch (err) { return done(err) } | |
| 100 | 103 | done() | |
| 101 | 104 | }) | |
@@ -106,11 +109,12 @@ describe('Engine: event', () => { | |||
| 106 | 109 | it('on-failure, it passes the event type and params', (done) => { | |
| 107 | 110 | let successSpy = sinon.spy() | |
| 108 | 111 | let rule = engine.rules[0] | |
| 109 | - rule.on('failure', function (e, a) { | ||
| 112 | + rule.on('failure', function (e, almanac, ruleResult) { | ||
| 110 | 113 | try { | |
| 111 | 114 | expect(e).to.eql(event) | |
| 112 | - expect(a).to.be.an.instanceof(Almanac) | ||
| 115 | + expect(almanac).to.be.an.instanceof(Almanac) | ||
| 113 | 116 | expect(successSpy.callCount).to.equal(0) | |
| 117 | + expect(ruleResult.conditions.any[0].result).to.be.false() | ||
| 114 | 118 | } catch (err) { return done(err) } | |
| 115 | 119 | done() | |
| 116 | 120 | }) | |
| Back | FazBrowse Home | New Git URL |
0 commit comments