forked from CacheControl/json-rules-engine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
04-fact-dependency.js
138 lines (127 loc) · 4.07 KB
/
04-fact-dependency.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
'use strict'
/*
* This is an advanced example that demonstrates facts with dependencies
* on other facts. In addition, it demonstrates facts that load data asynchronously
* from outside sources (api's, databases, etc)
*
* Usage:
* node ./examples/04-fact-dependency.js
*
* For detailed output:
* DEBUG=json-rules-engine node ./examples/04-fact-dependency.js
*/
require('colors')
const Engine = require('../dist').Engine
const accountClient = require('./support/account-api-client')
/**
* Setup a new engine
*/
const engine = new Engine()
/**
* Rule for identifying microsoft employees that have been terminated.
* - Demonstrates re-using a same fact with different parameters
* - Demonstrates calling a base fact, which serves to load data once and reuse later
*/
const microsoftRule = {
conditions: {
all: [{
fact: 'account-information',
operator: 'equal',
value: 'microsoft',
path: '$.company'
}, {
fact: 'account-information',
operator: 'equal',
value: 'terminated',
path: '$.status'
}]
},
event: { type: 'microsoft-terminated-employees' }
}
engine.addRule(microsoftRule)
/**
* Rule for identifying accounts older than 5 years
* - Demonstrates calling a base fact, also shared by the account-information-field fact
* - Demonstrates performing computations on data retrieved by base fact
*/
const tenureRule = {
conditions: {
all: [{
fact: 'employee-tenure',
operator: 'greaterThanInclusive',
value: 5,
params: {
unit: 'years'
}
}]
},
event: { type: 'five-year-tenure' }
}
engine.addRule(tenureRule)
/**
* Register listeners with the engine for rule success and failure
*/
let facts
engine
.on('success', event => {
console.log(facts.accountId + ' DID '.green + 'meet conditions for the ' + event.type.underline + ' rule.')
})
.on('failure', event => {
console.log(facts.accountId + ' did ' + 'NOT'.red + ' meet conditions for the ' + event.type.underline + ' rule.')
})
/**
* 'account-information' fact executes an api call and retrieves account data
* - Demonstrates facts called only by other facts and never mentioned directly in a rule
*/
engine.addFact('account-information', (params, almanac) => {
return almanac.factValue('accountId')
.then(accountId => {
return accountClient.getAccountInformation(accountId)
})
})
/**
* 'employee-tenure' fact retrieves account-information, and computes the duration of employment
* since the account was created using 'accountInformation.createdAt'
*/
engine.addFact('employee-tenure', (params, almanac) => {
return almanac.factValue('account-information')
.then(accountInformation => {
const created = new Date(accountInformation.createdAt)
const now = new Date()
switch (params.unit) {
case 'years':
return now.getFullYear() - created.getFullYear()
case 'milliseconds':
default:
return now.getTime() - created.getTime()
}
})
.catch(console.log)
})
// define fact(s) known at runtime
facts = { accountId: 'washington' }
engine
.run(facts) // first run, using washington's facts
.then(() => {
facts = { accountId: 'jefferson' }
return engine.run(facts) // second run, using jefferson's facts; facts & evaluation are independent of the first run
})
.catch(console.log)
/*
* OUTPUT:
*
* loading account information for "washington"
* washington DID meet conditions for the microsoft-terminated-employees rule.
* washington did NOT meet conditions for the five-year-tenure rule.
* loading account information for "jefferson"
* jefferson did NOT meet conditions for the microsoft-terminated-employees rule.
* jefferson DID meet conditions for the five-year-tenure rule.
*/
/*
* NOTES:
*
* - Notice that although a total of 6 conditions were evaluated using
* account-information (3 rule conditions x 2 accounts), the account-information api call
* is only called twice -- once for each account. This is due to the base fact caching the results
* for washington and jefferson after the initial data load.
*/