You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/facts.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,23 +1,23 @@
1
1
# Facts
2
2
3
-
Facts are methods or constants registered with the engine prior to runtime and referenced within rule conditions. Each fact method should be a pure function that may return a computed value or promise.
3
+
Facts are methods or constants registered with the engine prior to runtime and referenced within rule conditions. Each fact method should be a pure function that may return a either computed value, or promise that resolves to a computed value.
4
4
As rule conditions are evaluated during runtime, they retrieve fact values dynamically and use the condition _operator_ to compare the fact result with the condition _value_.
**options.event** : `[Object]` Sets the `.on('success')` and `on('failure')` event argument emitted whenever the rule passes. Event objects must have a ```type``` property, and an optional ```params``` property.
38
+
39
+
**options.priority** : `[Number, default 1]` Dictates when rule should be run, relative to other rules. Higher priority rules are run before lower priority rules. Rules with the same priority are run in parallel. Priority must be a positive, non-zero integer.
40
+
41
+
**options.onSuccess** : `[Function(Object event, Almanac almanac)]` Registers callback with the rule's `on('success')` listener. The rule's `event` property and the current [Almanac](./almanac.md) are passed as arguments.
42
+
43
+
**options.onFailure** : `[Function(Object event, Almanac almanac)]` Registers callback with the rule's `on('failure')` listener. The rule's `event` property and the current [Almanac](./almanac.md) are passed as arguments.
44
+
15
45
### setConditions(Array conditions)
16
46
17
-
Assigns the rule conditions to the provided argument. The root condition must be a boolean operator (```all``` or ```any```)
47
+
Helper for setting rule conditions. Alternative to passing the `conditions` option to the rule constructor.
48
+
49
+
### setEvent(Object event)
50
+
51
+
Helper for setting rule event. Alternative to passing the `event` option to the rule constructor.
52
+
53
+
### setPriority(Integer priority = 1)
54
+
55
+
Helper for setting rule priority. Alternative to passing the `priority` option to the rule constructor.
56
+
57
+
### toJSON(Boolean stringify = true)
58
+
59
+
Serializes the rule into a JSON string. Often used when persisting rules.
18
60
19
61
```js
20
-
rule.setConditions({
21
-
all: [
22
-
{
23
-
fact:'revenue',
24
-
operator:'greaterThanInclusive'
25
-
value:1000000
26
-
}
27
-
]
28
-
})
62
+
let jsonString =rule.toJSON() // string: '{"conditions":{"all":[]},"priority":50 ...
29
63
30
-
// if fact returns an object or array, providing a "path" key can be used for property traversal
See the [fact dependency example](../examples/fact-dependency.js)
70
+
## Conditions
44
71
45
-
### setEvent(Object event)
72
+
Rule conditions are a combination of facts, operators, and values that determine whether the rule is a `success` or a `failure`.
46
73
47
-
Sets the event the engine should emit when the rule conditions pass. All events must have a ```type``` property, which denotes the event name to emit when the rule passes.
74
+
### Basic conditions
48
75
49
-
Optionally, a ```params``` property may be provided as well. ```params``` will be passed to the event as an argument.
76
+
The simplest form of a condition consists of a `fact`, an `operator`, and a `value`. When the engine runs, the operator is used to compare the fact against the value.
50
77
51
78
```js
52
-
rule.setEvent({
53
-
type:'string', //required
54
-
params: { object } //optional
79
+
// my-fact <= 1
80
+
let rule =newRule({
81
+
conditions: {
82
+
all: [
83
+
{
84
+
fact:'my-fact',
85
+
operator:'lessThanInclusive',
86
+
value:1
87
+
}
88
+
]
89
+
}
55
90
})
56
91
```
57
92
58
-
### setPriority(Integer priority = 1)
93
+
See the [hello-world](../examples/01-hello-world.js) example.
94
+
95
+
### Boolean expressions: `all` and `any`
59
96
60
-
Sets the rule priority. Priority must be a positive, non-zero integer. The higher the priority, the sooner the rule will run. If no priority is assigned to a Rule, it will receive a default priority of 1.
97
+
Each rule's conditions *must* have either an `all` or an `any` operator at its root, containing an array of conditions. The `all` operator specifies that all conditions contained within must be truthy for the rule to be considered a `success`. The `any` operator only requires one condition to be truthy for the rule to succeed.
61
98
62
99
```js
63
-
rule.setPriority(100)
100
+
// all:
101
+
let rule =newRule({
102
+
conditions: {
103
+
all: [
104
+
{ /* condition 1 */ },
105
+
{ /* condition 2 */ },
106
+
{ /* condition n */ },
107
+
]
108
+
}
109
+
})
110
+
111
+
// any:
112
+
let rule =newRule({
113
+
conditions: {
114
+
any: [
115
+
{ /* condition 1 */ },
116
+
{ /* condition 2 */ },
117
+
{ /* condition n */ },
118
+
{
119
+
all: [ /* more conditions */ ]
120
+
}
121
+
]
122
+
}
123
+
})
64
124
```
65
125
66
-
### toJSON(Boolean stringify = true)
126
+
Notice in the second example how `all` and `any` can be nested within one another to produce complex boolean expressions. See the [nested-boolean-logic](../examples/02-nested-boolean-logic.js) example.
67
127
68
-
Serializes the rule into a JSON string. Usually used when persisting rules.
128
+
### Condition helpers: `params`
129
+
130
+
Sometimes facts require additional input to perform calculations. For this, the `params` property is passed as an argument to the fact handler. `params` essentially functions as fact arguments, enabling fact handlers to be more generic and reusable.
69
131
70
132
```js
71
-
let jsonString =rule.toJSON() // string: '{"conditions":{"all":[]},"priority":50 ...
133
+
// product-price retrieves any product's price based on the "productId" in "params"
134
+
engine.addFact('product-price', function (params, almanac) {
135
+
returnproductLoader(params.productId) // loads the "widget" product
136
+
.then(product=>product.price)
137
+
})
72
138
73
-
let rule =newRule(jsonString) // restored rule; same conditions, priority, event
139
+
// identifies whether the current widget price is above $100
140
+
let rule =newRule({
141
+
conditions: {
142
+
all: [
143
+
{
144
+
fact:'product-price',
145
+
params: {
146
+
productId:'widget'// specifies which product to load
See the [dynamic-facts](../examples/03-dynamic-facts) example
157
+
158
+
### Condition helpers: `path`
159
+
160
+
In the `params` example above, the dynamic fact handler loads an object, then returns a specific object property. For more complex data structures, writing a separate fact handler for each object property can sometimes become unwieldy.
161
+
162
+
To alleviate this overhead, a `path` property is provided for traversing objects and arrays returned by facts. The example above becomes simpler, and only one fact handler must be written by the developer to handle any number of properties.
163
+
164
+
```js
165
+
166
+
// product-price retrieves any product's price based on the "productId" in "params"
167
+
engine.addFact('product-price', function (params, almanac) {
168
+
// NOTE: `then` is not required; .price is specified via "path" below
169
+
returnproductLoader(params.productId)
170
+
})
171
+
172
+
// identifies whether the current widget price is above $100
173
+
let rule =newRule({
174
+
conditions: {
175
+
all: [
176
+
{
177
+
fact:'product-price',
178
+
params: {
179
+
productId:'widget',
180
+
// Complex accessor are supported, e.g. '.profile.addresses[0].city'
181
+
path:'.price'
182
+
},
183
+
operator:'greaterThan',
184
+
value:100
185
+
}
186
+
]
187
+
}
188
+
})
77
189
```
190
+
See the [fact-dependency](../examples/04-fact-dependency.js) example
78
191
79
-
### Events
192
+
### Comparing facts
80
193
81
-
Listen for 'success' and 'failure' events emitted when rule is evaluated.
194
+
Sometimes it is necessary to compare facts against others facts. This can be accomplished by nesting the second fact within the `value` property. This second fact has access to the same `params` and `path` helpers as the primary fact.
195
+
196
+
```js
197
+
// identifies whether the current widget price is above a maximum
198
+
let rule =newRule({
199
+
conditions: {
200
+
all: [
201
+
// widget-price > budget
202
+
{
203
+
fact:'product-price',
204
+
params: {
205
+
productId:'widget',
206
+
path:'.price'
207
+
},
208
+
operator:'greaterThan',
209
+
// "value" contains a fact
210
+
value: {
211
+
fact:'budget'// "params" and "path" helpers are available as well
212
+
}
213
+
}
214
+
]
215
+
}
216
+
})
217
+
```
218
+
See the [fact-comparison](../examples/08-fact-comparison.js) example
219
+
220
+
## Events
221
+
222
+
Listen for `success` and `failure` events emitted when rule is evaluated.
0 commit comments