# mini-rule-engine
**Repository Path**: itopen/mini-rule-engine
## Basic Information
- **Project Name**: mini-rule-engine
- **Description**: fork from https://github.com/Tyg-g/mini-rule-engine
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2025-12-09
- **Last Updated**: 2025-12-09
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README

[](https://opensource.org/licenses?ls=mpl)







[](https://github.com/Tyg-g/mini-rule-engine/issues/new/choose)
# Mini Rule Engine
A very-lightweight rule engine for DB data sources.
It evaluates simple, human-readable rules defined in standard JavaScript objects - with async DB operations in mind.
> This is a new module that I just created. If you are interesed in using the package or you have an idea for a new feature, contact me on the GitHub page.
Basic Philosophy:
1. 🧩 Keep rule definitions simple and intuitive.
2. ⚡ Make it straightforward to connect to async/DB operations.
3. ✨ Add features without sacrificing simplicity and readibility.
I welcome feature requests and suggestions for use cases I might not have considered. The goal is to keep the rule definitions simple and intuitive while adding powerful features.
## 0. Installation
```sh
$ npm i mini-rule-engine
```
## 1. Usage Basics
Here's a quick example of how to define parameters, create a rule, and evaluate it.
**1. Create a new engine instance, and define the data sources**
```javascript
import RuleEngine from 'mini-rule-engine';
// A parameter is a piece of data that the engine can check.
// The getter function can be async (eg. read from a DB)
const re = new RuleEngine();
re.defineParameterAccessor('user', async () => ({
age: 25,
country: 'Mars Colony',
isPremium: true,
}));
re.defineParameterAccessor('orderCount', async () => 4);
```
**2. Use the engine instance**
```javascript
// The ruleset object can be static,
// or can be read from a DB
// (eg. voucher code, dynamic configuration, etc.)
const myRuleset = {
'user.age': { min: 18 },
'user.country': { is: 'Mars Colony' },
OR: [
{'user.isPremium': { is: true } },
{'orderCount': { max: 0 } },
]
};
// Evaluate the rule
const result = await re.evaluate(myRuleset);
console.log(`Does this user meet our criteria? ${result}`); // true
// You can also get a reason for failure
const detailedResult = await re.evaluateWithReason({ 'user.age': { min: 30 } });
if (!detailedResult.value) {
if (detailedResult.parameterName === 'user.age') {
console.log(`The user's age is too low.`);
}
}
```
### Operation Mode
```
⛁ Automatic
◀ dynamic/DB
/ / read
/ /
Evaluate / ▶ of data needed
ruleset + ┌──────────────┐ for evaluation
params (call) ────────▶ │ │
│ RuleEngine │
│ instance │
(return value) ◀───────── │ │
evaluation └──────────────┘
result
```
## 2. Rule Operators
### Basic Operators
- `min`: Minimum value
- `max`: Maximum value
- `is`: Equal - exact match
- `not`: Not equal
- `under`: Less than
- `over`: Greater than
### Logical `'OR'` Operator
There are two ways to use the logical `'OR'` operator:
*Simple* - applied to a single parameter:
```js
const ruleset = {
'myStatus': { OR: [
{ is: -1 },
{ min: 1, max: 10 }
]},
};
```
*Compound* - applied to multiple differentparameters:
```js
const ruleset = {
OR: [
{'user.isPremium': { is: true } }
{
'user.age': { min: 18 },
'orderCount': { max: 0 }
}
]
};
```
Note: The `'OR'` operator in both cases expects an array of objects.
### Logical AND Operator
The logical AND operation is implied when listing different rules in the ruleset. Therefore, no AND operatoror is defined.
## 3. Rule variables (parameters)
### Data Types
The parameter and the compared limit value must have *matching types* to get a true result.
Supported data types: `number`, `string`, `boolean`, `object`, `null`.
### Object Data Type
If a parameter represents an object, this object must be a plain JS object (for security reasons). Only its own properties can be accessed (incl. getter functions).
You can use dot notation to access its properties:
```javascript
const ruleset = {
'user.age': { min: 18 },
'user.country': { is: 'Mars Colony' }
};
```
## 4. Getter Functions
The getter functions define *how* to get the correspondingparameter value for an evaluation run.
### Async
The evaluation is always async. If the getter functions defined in defineParameterAccessor() are async, the evaluation will resolve immediately.
For each evaluation:
- **Only those** getter functions are called, that are referenced in the evaluated ruleset.
- Each getter function is called **only once**, regardless of how many times it is referenced in the ruleset. The same value will be reused for each rule.
### Defining a Getter Function
The getter functions are defined as follows, before running any evaluations:
```javascript
re.defineParameterAccessor('parameterName', getterFunction);
```
### Function parameters
```javascript
async function getterFunction(params, meta) {...}
```
- `meta`: An object containing information about the how is the parameter used in the ruleset. This can be useful for example to limit database reads when counting objects.
- `meta.accessorName` (string): The name of the parameter (defined in `defineParameterAccessor()`) for which the getter was called.
*In the case the getter returns an object, and the ruleset evaluates an object parameter, this string contains the part before the first dot.*
- `meta.constraintValues` (array of any): All the values (operands) the parameter is being compared against in the ruleset.
- `meta.childrenConstraintValues` (object): *Only if the parameter is accesing an object's children (eg.: `'myObject.childA'`).*
The keys list all the descendants that are being accessed in the ruleset. Each key contains an array of the corresponding constraint values (as in `meta.constraintValues`).
- `params`: Is a value or an object, that is passed directly from the `re.evaluate()` or `re.evaluateWithReason()` functions (the `getterParams` parameter):
```javascript
async evaluateWithReason(parameterConstraintsObject, getterParams) {}
```
This can contain for example a userId.
### Example
**Setup**
```javascript
const re = new RuleEngine();
re.defineParameterAccessor('user', userGetter);
re.defineParameterAccessor('orderCount', orderCountGetter);
re.defineParameterAccessor('currentOrder', currentOrderGetter);
const ruleset = {
'user.age': {
min: 18,
max: 65
},
'user.eyes.left': { not: 'red' },
OR: [
{
'user.eyes.left': { is: 'black' },
'user.age': { max: 22 }
},
{
'user.eyes.left': { not: 'black' }
}
],
'orderCount': {
min: 1
}
};
const getterParams = {
userId: 'rxzUyV7qc5',
currentOrderId: 'mDyNy3ZmnR7g'
}
const result = await re.evaluateWithReason(ruleset, getterParams);
```
**The getter functions are called with the following parameters**
- **`async function userGetter(params, meta) {...}`:**
```javascript
params = {
userId: 'rxzUyV7qc5',
currentOrderId: 'mDyNy3ZmnR7g'
}
meta = {
accessorName: 'user',
constraintValues: [],
childrenConstraintValues: {
'age': [18, 65, 22],
'eyes.left': ['red', 'black']
}
}
```
- **`async function orderCountGetter(params, meta) {...}`:**
```javascript
params //is the same
meta = {
accessorName: 'orderCount',
constraintValues: [1]
}
```
- **`async function currentOrderGetter(params, meta) {...}`:**
*is not called.*
## 5. Errors
### Parameter definition errors
- `'REParameterError'`: If the parameter definition encounters a mistake/error in its inputs, it throws.
### Errors During Evaluation
The evaluation only throws, if it cannot be completed with a meaningful result.
- `'RERuleSyntaxError'`: This error is thrown, if the ruleset object contains an error. (Eg. an invalid operator)
- `'RETypeError'`: This error is thrown, if a parameter is evaluated to a data type, that cannot be accepted. (Ie. the getter function's return value is incompatible with the given rule, eg. primitive vs. object.)
Note: Comparing different primitive values (e.g. number and string) will not throw, it will simply return false, per JS's strict equality comparison.
## 6.  Issues / New Features 
Go to [**Issue Reporting on mini-rule-engine ➜**](https://github.com/Tyg-g/mini-rule-engine/issues/new/choose)
> *All contributions, ideas and encouragements are welcome!*