Breaking Change: Please move to v3.1.0 or later.
A lightweight and extensible rule engine built with TypeScript and Node.js. Define complex business rules and evaluate conditions easily using a simple JSON structure.
npm install @arunkumar_h/rule-engineyarn add @arunkumar_h/rule-engine- β Logical condition support (and, or, nested expressions)
- π§ Custom operators and named conditions
- π Fully typed with TypeScript
- π Lightweight and dependency-aware
- π Native JMESPath support for data querying
- π§° Built-in caching using
lru-cachefor better performance
| Feature / Capability | @arunkumar_h/rule-engine |
|---|---|
| β Written in TypeScript | β Native TypeScript with full type safety |
| βοΈ Custom Operators | β Built-in support, sync or async |
| π§ Named Conditions | β Supports reusable named conditions |
| π§± Nested Logical Trees | β Fully supported (and, or, deeply nested) |
| π Data Query Language | β Built-in JMESPath support |
| π Performance Optimizations | β Rule-level cache with lru-cache |
| π§° Extensibility | β Add custom operators, conditions dynamically |
| βοΈ Lightweight | β Small and focused build |
| π§ͺ Testing Coverage Ready | β Easy to unit test each rule block |
| π Dynamic Rule Loading | β Add/modify rules at runtime |
| π Async Support | β Full async engine and operators |
| π¦ Modern Packaging | β ESM + CJS + .d.ts types out of the box |
The following operators are available by default:
| Operator | Description |
|---|---|
| === | Strict equality |
| !== | Strict inequality |
| == | Loose equality |
| != | Loose inequality |
| > | Greater than |
| >= | Greater than or equal to |
| < | Less than |
| <= | Less than or equal to |
| %like | Starts with |
| like% | Ends with |
| %like% | Contains |
| in | Value is in the array |
| !in | Value is not in the array |
| includes | Array includes value |
| !includes | Array does not include value |
conditionThis containesandandoras main block.onSuccessvalue that will be returned or function that will be invoked if the condition is satisfied.onFailvalue that will be returned or function that will be invoked if the condition fails.cacheas default this will be set totrueand can be disabled for rule wisefalse
import { Engine } from "@arunkumar_h/rule-engine";
const engineObj = new Engine();
const rule = {
testRule: {
condition: {
and: [
{ path: "age", operator: "!==", value: 10 },
{
and: [
{ path: "age", operator: ">", value: 15 },
{
or: [
{ path: "age", operator: "!==", value: 30 },
{ path: "skills", operator: "includes", value: "ts" },
],
},
],
},
{ path: "language", operator: "in", value: ["tamil", "english"] },
],
},
onSuccess: (fact, ruleName) => "Success", // onSuccess: { id: 23 }
onFail: (fact, ruleName) => "Fail", // onFail: "Error"
cache: false, // default will be true
}
};
engine.addRule(rule);
const fact = {age: 16, skills: ["ts", "php"], language: "tamil"}; // Your data to be validated
const result = await engineObj.run(fact, "testRule");engine.addOperator({
isEven: (factValue) => factValue % 2 === 0,
});
const rule = {
evenCheck: {
condition: {
and: [
{ path: "number", operator: "isEven" },
],
},
onSuccess: "Number is even",
onFail: "Number is odd",
},
};
const result = await engine.run({ number: 8 }, "evenCheck");flowchart TB
Rule --> onSuccess
Rule --> onFail
Rule --> Condition --> AND --> Operation
Condition --> OR --> Operation
let engine = new Engine() addRule({ rule1, rule2, ... })
- Add named rules dynamically.
addCondition({ condition1, condition2, ... })
- Add reusable named conditions.
- Conditions can reference other named conditions.
addOperator({ customOperator1, customOperator2, ... })
- Add custom (sync or async) operators.
run(fact, ruleName)
- Executes a given rule against the provided fact
- Adding named conditions.
- Adding named operators.
- Rule wise cache disabling.
import { Engine } from "@arunkumar_h/rule-engine";
const engineObj = new Engine();
const condition1 = {
condition1: {
and: [
{ path: "age", operator: "!==", value: 10 },
{
and: [
{ path: "age", operator: ">", value: 15 },
{
or: [
{ path: "age", operator: "!==", value: 30 },
{ path: "skills", operator: "includes", value: "ts" },
],
},
],
},
{ path: "language", operator: "in", value: ["tamil", "english"] },
],
}
};
engine.addCondition(condition1); // adding named condition
const rule = {
testRule: {
condition: "condition1", // Using named condition
onSuccess: "Success", // can be a function or a data
onFail: "Fail", // can be a function or a data
cache: false // disable cache for this rule
}
};
engine.addRule(rule);
const fact = {age: 16, skills: ["ts", "php"], language: "tamil"}; // Your data to be validated
const result = await engineObj.run(fact, "testRule");Badges above represent live coverage stats for:
Arunkumar H
- Code: Licensed under the MIT License
- Assets & Documentation: Licensed under the CC BY-SA 4.0 License
Some non-code content (e.g. diagrams, images, markdown docs) is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
See https://creativecommons.org/licenses/by-sa/4.0/ for more info.
The detailed list of Open Source dependencies can be found in Fossa report.