UNPKG

7.03 kBMarkdownView Raw
1![json-rules-engine](http://i.imgur.com/MAzq7l2.png)
2[![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard)
3[![Build Status](https://github.com/cachecontrol/json-rules-engine/workflows/Node.js%20CI/badge.svg?branch=master)](https://github.com/cachecontrol/json-rules-engine/workflows/Node.js%20CI/badge.svg?branch=master)
4
5[![npm version](https://badge.fury.io/js/json-rules-engine.svg)](https://badge.fury.io/js/json-rules-engine)
6[![install size](https://packagephobia.now.sh/badge?p=json-rules-engine)](https://packagephobia.now.sh/result?p=json-rules-engine)
7[![npm downloads](https://img.shields.io/npm/dm/json-rules-engine.svg)](https://www.npmjs.com/package/json-rules-engine)
8
9A rules engine expressed in JSON
10
11* [Synopsis](#synopsis)
12* [Features](#features)
13* [Installation](#installation)
14* [Docs](#docs)
15* [Examples](#examples)
16* [Basic Example](#basic-example)
17* [Advanced Example](#advanced-example)
18* [Debugging](#debugging)
19 * [Node](#node)
20 * [Browser](#browser)
21* [Related Projects](#related-projects)
22* [License](#license)
23
24## Synopsis
25
26```json-rules-engine``` is a powerful, lightweight rules engine. Rules are composed of simple json structures, making them human readable and easy to persist.
27
28## Features
29
30* Rules expressed in simple, easy to read JSON
31* Full support for ```ALL``` and ```ANY``` boolean operators, including recursive nesting
32* Fast by default, faster with configuration; priority levels and cache settings for fine tuning performance
33* Secure; no use of eval()
34* Isomorphic; runs in node and browser
35* Lightweight & extendable; 17kb gzipped w/few dependencies
36
37## Installation
38
39```bash
40$ npm install json-rules-engine
41```
42
43## Docs
44
45- [engine](./docs/engine.md)
46- [rules](./docs/rules.md)
47- [almanac](./docs/almanac.md)
48- [facts](./docs/facts.md)
49
50## Examples
51
52See the [Examples](./examples), which demonstrate the major features and capabilities.
53
54## Basic Example
55
56This example demonstrates an engine for detecting whether a basketball player has fouled out (a player who commits five personal fouls over the course of a 40-minute game, or six in a 48-minute game, fouls out).
57
58```js
59const { Engine } = require('json-rules-engine')
60
61
62/**
63 * Setup a new engine
64 */
65let engine = new Engine()
66
67// define a rule for detecting the player has exceeded foul limits. Foul out any player who:
68// (has committed 5 fouls AND game is 40 minutes) OR (has committed 6 fouls AND game is 48 minutes)
69engine.addRule({
70 conditions: {
71 any: [{
72 all: [{
73 fact: 'gameDuration',
74 operator: 'equal',
75 value: 40
76 }, {
77 fact: 'personalFoulCount',
78 operator: 'greaterThanInclusive',
79 value: 5
80 }]
81 }, {
82 all: [{
83 fact: 'gameDuration',
84 operator: 'equal',
85 value: 48
86 }, {
87 fact: 'personalFoulCount',
88 operator: 'greaterThanInclusive',
89 value: 6
90 }]
91 }]
92 },
93 event: { // define the event to fire when the conditions evaluate truthy
94 type: 'fouledOut',
95 params: {
96 message: 'Player has fouled out!'
97 }
98 }
99})
100
101/**
102 * Define facts the engine will use to evaluate the conditions above.
103 * Facts may also be loaded asynchronously at runtime; see the advanced example below
104 */
105let facts = {
106 personalFoulCount: 6,
107 gameDuration: 40
108}
109
110// Run the engine to evaluate
111engine
112 .run(facts)
113 .then(({ events }) => {
114 events.map(event => console.log(event.params.message))
115 })
116
117/*
118 * Output:
119 *
120 * Player has fouled out!
121 */
122```
123
124This is available in the [examples](./examples/02-nested-boolean-logic.js)
125
126## Advanced Example
127
128This example demonstates an engine for identifying employees who work for Microsoft and are taking Christmas day off.
129
130This demonstrates an engine which uses asynchronous fact data.
131Fact information is loaded via API call during runtime, and the results are cached and recycled for all 3 conditions.
132It also demonstates use of the condition _path_ feature to reference properties of objects returned by facts.
133
134```js
135const { Engine } = require('json-rules-engine')
136
137// example client for making asynchronous requests to an api, database, etc
138import apiClient from './account-api-client'
139
140/**
141 * Setup a new engine
142 */
143let engine = new Engine()
144
145/**
146 * Rule for identifying microsoft employees taking pto on christmas
147 *
148 * the account-information fact returns:
149 * { company: 'XYZ', status: 'ABC', ptoDaysTaken: ['YYYY-MM-DD', 'YYYY-MM-DD'] }
150 */
151let microsoftRule = {
152 conditions: {
153 all: [{
154 fact: 'account-information',
155 operator: 'equal',
156 value: 'microsoft',
157 path: '$.company' // access the 'company' property of "account-information"
158 }, {
159 fact: 'account-information',
160 operator: 'in',
161 value: ['active', 'paid-leave'], // 'status' can be active or paid-leave
162 path: '$.status' // access the 'status' property of "account-information"
163 }, {
164 fact: 'account-information',
165 operator: 'contains', // the 'ptoDaysTaken' property (an array) must contain '2016-12-25'
166 value: '2016-12-25',
167 path: '$.ptoDaysTaken' // access the 'ptoDaysTaken' property of "account-information"
168 }]
169 },
170 event: {
171 type: 'microsoft-christmas-pto',
172 params: {
173 message: 'current microsoft employee taking christmas day off'
174 }
175 }
176}
177engine.addRule(microsoftRule)
178
179/**
180 * 'account-information' fact executes an api call and retrieves account data, feeding the results
181 * into the engine. The major advantage of this technique is that although there are THREE conditions
182 * requiring this data, only ONE api call is made. This results in much more efficient runtime performance
183 * and fewer network requests.
184 */
185engine.addFact('account-information', function (params, almanac) {
186 console.log('loading account information...')
187 return almanac.factValue('accountId')
188 .then((accountId) => {
189 return apiClient.getAccountInformation(accountId)
190 })
191})
192
193// define fact(s) known at runtime
194let facts = { accountId: 'lincoln' }
195engine
196 .run(facts)
197 .then(({ events }) => {
198 console.log(facts.accountId + ' is a ' + events.map(event => event.params.message))
199 })
200
201/*
202 * OUTPUT:
203 *
204 * loading account information... // <-- API call is made ONCE and results recycled for all 3 conditions
205 * lincoln is a current microsoft employee taking christmas day off
206 */
207```
208
209This is available in the [examples](./examples/03-dynamic-facts.js)
210
211## Debugging
212
213To see what the engine is doing under the hood, debug output can be turned on via:
214
215### Node
216
217```bash
218DEBUG=json-rules-engine
219```
220
221### Browser
222```js
223// set debug flag in local storage & refresh page to see console output
224localStorage.debug = 'json-rules-engine'
225```
226
227## Related Projects
228
229https://github.com/vinzdeveloper/json-rule-editor - configuration ui for json-rules-engine:
230
231<img width="1680" alt="rule editor 2" src="https://user-images.githubusercontent.com/61467683/82750274-dd3b3b80-9da6-11ea-96eb-434a6a1a9bc1.png">
232
233
234## License
235[ISC](./LICENSE)