js-rules-engine
v1.1.1
Published
JavaScript rules engine for validating data object structures.
Downloads
2,392
Maintainers
Readme
Rules Engine
JavaScript rules engine for validating data object structures.
Table of Contents
Features
- 💪 Easy to use chainable API.
- 💥 Support for infinitely nested
AND
/OR
conditions. - 🚀 Rules can be expressed in simple JSON.
- ✔️ Customize operators with your own functions.
- 🏄 Access nested properties with dot notation paths.
Installation
npm install js-rules-engine --save
Usage
import { Rule } from 'js-rules-engine';
// homeWorld.name equals 'Tatooine' AND (name contains 'Skywalker' OR eyeColor is 'green')
const rule = new Rule().equals('homeWorld.name', 'Tatooine').or((sub) => {
sub.contains('name', 'Skywalker').equals('eyeColor', 'green');
});
// object of data to evaluate rule against
const fact = {
eyeColor: 'blue',
homeWorld: {
name: 'Tatooine',
},
name: 'Luke Skywalker',
};
rule.evaluate(fact);
// => true
Default Engine
An Engine
contains all operators available to a Rule
. By default, a single Engine
instance is used for all Rule
instances. The default Engine
's operators can be customized like this:
import { defaultEngine } from 'js-rules-engine';
defaultEngine.removeOperator('greaterThan');
defaultEngine.addOperator('moreGreaterThan', myAwesomeFunction);
Override Engine
Each instance of Rule
has the ability to use it's own Engine
instance, overriding the default.
import { Engine, Rule } from 'js-rules-engine';
const engine = new Engine();
const rule = new Rule(null, engine);
Default Operators
Each Engine
contains the follow operators by default:
equals
notEquals
in
notIn
contains
notContains
lessThan
lessThanOrEquals
greaterThan
greaterThanOrEquals
Customizing Operators
Add your own operators to an Engine
. Once added, any custom Operator
can be used via the Rule
's add()
method.
import { defaultEngine, Operator } from 'js-rules-engine';
const noop = new Operator('noop', (a, b) => true);
defaultEngine.addOperator(noop);
You can also remove an Operator
.
import { defaultEngine } from 'js-rules-engine';
defaultEngine.removeOperator('noop');
Rule Conditions
The add
method is a generic way to add a condition to the Rule
. The conditions operator is added via it's name
.
The value
type should match what the operator is expecting.
| Param | Description | Type |
| ---------- | ----------------------------------- | -------- |
| fact
| Property name or dot notation path. | string
|
| operator
| Name of operator to use. | string
|
| value
| Value to compare. | any
|
A Rule
has shortcut methods for all default operators. Each method takes two arguments (fact
and value
) and returns
the Rule
instance for chaining.
| Method | Fact Type | Value Type |
| --------------------- | --------- | ---------- |
| equals
| string
| any
|
| notEquals
| string
| any
|
| in
| string
| string
|
| notIn
| string
| string
|
| contains
| string
| any
|
| notContains
| string
| any
|
| lessThan
| string
| number
|
| lessThanOrEquals
| string
| number
|
| greaterThan
| string
| number
|
| greaterThanOrEquals
| string
| number
|
Nested conditions can be achieved with the and()
/ or()
methods. Each methods takes one parameter, a callback
function that is supplied with a nested Rule
instance as the first argument, and returns the original Rule
instance
for chaining.
Persisting Rules
Rules can easily be converted to JSON and persisted to a database, file system, or elsewhere.
// save rule as JSON string ...
const jsonString = JSON.stringify(rule);
localStorage.setItem('persistedRule', jsonString);
// ... and hydrate rules from a JSON object!
const jsonString = localStorage.getItem('persistedRule');
const json = JSON.parse(jsonString);
const rule = new Rule(json);
Example JSON structure:
{
"and": [
{
"fact": "homeWorld.name",
"operator": "equals",
"value": "Tatooine"
},
{
"or": [
{
"fact": "name",
"operator": "contains",
"value": "Skywalker"
},
{
"fact": "eyeColor",
"operator": "equals",
"value": "green"
}
]
}
]
}
Development
npm install
npm run build