JavaScript rules engine for validating data object structures.
- 💪 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.
npm install js-rules-engine --save
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
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);
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);
Each Engine
contains the follow operators by default:
equals
notEquals
in
notIn
contains
notContains
lessThan
lessThanOrEquals
greaterThan
greaterThanOrEquals
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');
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.
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"
}
]
}
]
}
npm install
npm run build