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-engine
yarn 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-cache
for 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 |
-
condition
This containesand
andor
as main block. -
onSuccess
value that will be returned or function that will be invoked if the condition is satisfied. -
onFail
value that will be returned or function that will be invoked if the condition fails. -
cache
as default this will be set totrue
and 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.