Gathering detailed insights and metrics for @elite-libs/rules-machine
Gathering detailed insights and metrics for @elite-libs/rules-machine
Gathering detailed insights and metrics for @elite-libs/rules-machine
Gathering detailed insights and metrics for @elite-libs/rules-machine
📐 A fast, general-purpose JSON Rules Engine.
npm install @elite-libs/rules-machine
Typescript
Module System
Min. Node Version
Node Version
NPM Version
TypeScript (97.77%)
JavaScript (2.02%)
Shell (0.21%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
BSD-3-Clause License
57 Stars
115 Commits
5 Forks
5 Watchers
6 Branches
4 Contributors
Updated on Jun 24, 2025
Latest Version
1.6.0
Package Id
@elite-libs/rules-machine@1.6.0
Unpacked Size
574.55 kB
Size
137.06 kB
File Count
16
NPM Version
8.19.1
Node Version
18.9.0
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
4
20
Rules Against The Machine 🤘
Table of Content
Rules Machine
?
Rules Machine
?It's a fast, general purpose JSON Rules Engine
library for both the Browser & Node.js! 🚀
applySalesTax
)App Logic != Business Rules
Typically Business Rules are better-suited to 'rules engine' style pattern.
If your Business Rules or logic changes frequently, you can get alignment benefits by moving that logic to a serializable & sharable format. Specifically, this can provide immediate benefits to mobile & native apps, as you don't have to wait for an approvals process for every change. ✨
Typically App Logic & Business Rules are woven together throughout the project. This co-location of logic is usually helpful, keeping things readable in small and even mid-sized projects.
This works great, until you run into one of the following challenges:
DepositTransaction
controller shouldn't require careful reading of 2,000 lines of custom rules around currency hackery & country-code checks.trace
, with details on each step, what happened, and the time taken.1yarn add @elite-libs/rules-machine 2# Or 3npm install @elite-libs/rules-machine
1import { ruleFactory } from '@elite-libs/rules-machine'; 2 3const fishRhyme = ruleFactory([ 4 { if: 'fish == "oneFish"', then: 'fish = "twoFish"' }, 5 { if: 'fish == "redFish"', then: 'fish = "blueFish"' }, 6]); 7// Equivalent to: 8// if (fish == "oneFish") fish = "twoFish" 9// if (fish == "redFish") fish = "blueFish" 10 11fishyRhyme({ fish: 'oneFish' }); // {fish: 'twoFish'}
1// Using "and" object style operator 2[ 3 {"if": {"and": ["price >= 25", "price <= 50"]}, "then": "discount = 5"}, 4 {"if": "price > 50", "then": "discount = 10"}, 5 {"return": "discount"} 6] 7// Using inline AND operator 8[ 9 {"if": "price >= 25 AND price <= 50", "then": "discount = 5"}, 10 {"if": "price > 50", "then": "discount = 10"}, 11 {"return": "discount"} 12]
1- if: { and: [price >= 25, price <= 50] } 2 then: discount = 5 3- if: price > 50 4 then: discount = 10 5- return: discount
1[ 2 { 3 "if": "user.plan == \"premium\"", 4 "then": "discount = 15" 5 }, 6 { 7 "if": "user.employee == true", 8 "then": "discount = 15" 9 }, 10 { 11 "return": "discount" 12 } 13]
1[ 2 { 3 "if": "price <= 100", 4 "then": "discount = 5" 5 }, 6 { 7 "if": { 8 "or": ["price >= 100", "user.isAdmin == true"] 9 }, 10 "then": "discount = 20" 11 }, 12 { 13 "return": "discount" 14 } 15]
1- if: price <= 100 2 then: discount = 5 3- if: 4 or: [price >= 100, user.isAdmin == true] 5 then: discount = 20 6- return: discount
1[ 2 { 3 "if": "price <= 100", 4 "then": ["discount = 5", "user.discountApplied = true"] 5 }, 6 { 7 "if": { 8 "and": ["price >= 90", "user.discountApplied != true"] 9 }, 10 "then": "discount = 20" 11 }, 12 { 13 "return": "discount" 14 } 15]
1- if: price <= 100 2 then: 3 - discount = 5 4 - user.discountApplied = true 5- if: 6 and: 7 - price >= 90 8 - user.discountApplied != true 9 then: discount = 20 10- return: discount
map
1const doubleList = ruleFactory([ 2 { 3 map: 'list', 4 run: '$item * 2', 5 set: 'list', 6 }, 7]); 8doubleList({ list: [1, 2, 3, 4] }); 9// [2, 4, 6, 8]
filter
1const multiplesOfThree = ruleFactory([ 2 { 3 filter: 'list', 4 run: '$item % 3 == 0', 5 set: 'results', 6 }, 7 { return: 'results' } 8]); 9multiplesOfThree({ list: [1, 2, 3, 4] }); 10// [3]
find
1const getFirstMultipleOfThree = ruleFactory([ 2 { 3 find: 'list', 4 run: '$item % 3 == 0', 5 set: 'results', 6 }, 7 { return: 'results' } 8]); 9getFirstMultipleOfThree({list: [1, 2, 3, 4]}) 10// 3 11getFirstMultipleOfThree({list: [9, 3, 4]}) 12// 9 13getFirstMultipleOfThree({list: [99]}) 14// undefined
every
1const isEveryNumberMultipleOfThree = ruleFactory([ 2 { 3 every: 'list', 4 run: '$item % 3 == 0', 5 set: 'results', 6 }, 7 { return: 'results' } 8]); 9isEveryNumberMultipleOfThree({list: [3, 6, 9]}) 10// true 11isEveryNumberMultipleOfThree({list: [3, 6, 9, 10]}) 12// false
some
1const hasEvenNumbers = ruleFactory([ 2 { 3 some: 'list', 4 run: '2 % $item == 0', 5 set: 'results', 6 }, 7 { return: 'results' } 8]); 9hasEvenNumbers({list: [2, 4]}) 10// true 11hasEvenNumbers({list: [2, 4, 5]}) 12// true 13hasEvenNumbers({list: [5]}) 14// false
if/then
1const calculateDiscount = ruleFactory([ 2 {"if": {"and": ["price >= 25", "price <= 50"]}, "then": "discount = 5"}, 3 {"if": "price > 50", "then": "discount = 10"}, 4 {"return": "discount"} 5]); 6calculateDiscount({price: 40, discount: 0}) 7// 5 8calculateDiscount({price: 60, discount: 0}) 9// 10
and/or
1const isScoreValid = ruleFactory({ 2 "if": {"and": ["score > 0", "score <= 100"]}, 3 "then": "valid = true", 4 "else": "valid = false", 5}) 6isScoreValid({score: 10}) 7// { score: 10, valid: true }} 8isScoreValid({score: -10}) 9// { score: 10, valid: false }} 10isScoreValid({score: 101}) 11// { score: 10, valid: false }}
try/catch
Execute string rule from try
. Handle errors in the catch
expression.
1[ 2 { 3 try: 'THROW "error"', 4 catch: 'status = "Failure"', 5 }, 6 { return: 'status' }, // returns "Failure" 7]
return
Ends rule execution, returning the specified value.
1[ 2 { return: '"blue"' }, // returns "blue" 3 { return: '"green"' }, // is not executed 4]
!=
=
- equality check.==
- equality check.<
<=
<>
>
>=
%
- 10 % 2
=> 0
(tip: odd/even check)*
- 42 * 10
=> 420
+
- 42 + 10
=> 52
-
/
^
~=
AND
- this does not short circuit if the first operand is false, but the object form does.OR
- this does not short circuit if the first operand is true, but the object form does.REMOVE_VALUES(matches, input)
- will remove all values matching the item(s) in the 1st argument from the 2nd argument array. (XOR operation.)FILTER_VALUES(matches, input)
- will ONLY INCLUDE values that are in the 1st & 2nd arguments. (Intersection operation.)CONTAINS(42, [41, 42, 43])
=> true
IF(7 > 5, 8, 10)
=> 8
GET('users[2].name', users)
=> Mary
AVERAGE([10, 20, 30])
=> 20
CEIL(0.1)
=> 1
FLOOR(1.9)
=> 1
FLOOR(0.6)
=> 1
TRUNC(1.9)
=> 1
SUM([1,2,3])
=> 6
ADD(2, 3)
=> 5
SUB(2, 3)
=> -1
DIV(9, 3)
=> 3
MUL(3, 3)
=> 9
NEG(ADD(1, 2))
=> -3
NOT(ISPRIME(7))
=> false
ISNAN('hai')
=> true
ISPRIME(7)
=> true
MOD(10, 2)
=> 0
GCD(9, 3)
=> 3
SLICE(1, 3, [1, 42, 69, 54])
=> [42, 69]
LENGTH([42, 69, 54])
=> 3
SORT([2,2,1])
=> [1, 2, 2]
FILTER(isEven, [1,2,3,4,5,6])
=> [2, 4, 6]
INDEX([42, 69, 54], 0)
=> 42
MAP("NOT", [FALSE, TRUE, FALSE])
=> [true, false, true]
MIN([42, 69, 54])
=> 42
MAX([42, 69, 54])
=> 69
HEAD([42, 69, 54])
=> 42
LAST([42, 69, 54])
=> 54
TAIL([42, 69, 54])
=> [69, 54]
TAKE(2, [42, 69, 54])
=> [42, 69]
TAKEWHILE(isEven, [0,2,4,5,6,7,8])
=> [0, 2, 4]
DROP(2, [1, 42, 69, 54])
=> [69, 54]
DROPWHILE(isEven, [0,2,4,5,6,7,8])
=> [5,6,7,8]
REDUCE("ADD", 0, [1, 2, 3])
=> 6
REVERSE([1,2,2])
=> [2, 2, 1]
CHARARRAY("abc")
=> ['a', 'b', 'c']
CONCAT([42, 69], [54])
=> [42, 69, 54]
CONS(2, [3, 4])
=> [2, 3, 4]
JOIN(",", ["a", "b"])
=> a,b
RANGE(0, 5)
=> [0, 1, 2, 3, 4]
UNZIPDICT([["a", 1], ["b", 5]])
=> {a: 1, b: 5}
ZIP([1, 3], [2, 4])
=> [[1, 2], [3, 4]]
DICT(["a", "b"], [1, 4])
=> {a: 1, b: 4}
KEYS(DICT(["a", "b"], [1, 4]))
=> ['a', 'b']
VALUES(DICT(["a", "b"], [1, 4]))
=> [1, 4]
UNZIP([[1, 2], [3, 4]])
=> [[1, 3], [2, 4]]
CONTAINS("x", {x: 1})
=> true
COUNT_KEYS({x: 1})
=> 1
OMIT("x", {x: 1})
=> {}
LOWER('HELLO')
=> hello
UPPER('hello')
=> HELLO
SPLIT(',', 'a,b')
=> ['a', 'b']
CHAR(65)
=> A
CODE('A')
=> 65
BIN2DEC('101010')
=> 42
DEC2BIN(42)
=> 101010
DEC2HEX('42')
=> 2a
DEC2STR('42')
=> 42
HEX2DEC("F")
=> 15
STR2DEC('42')
=> 42
STRING_CONTAINS("lo wo", "hello world")
=> true
, note: this function does not currently accept regular expressionsSTRING_ENDS_WITH("rld", "hello world")
=> true
, note: this function does not currently accept regular expressionsSTRING_STARTS_WITH("hell", "hello world")
=> true
, note: this function does not currently accept regular expressionsSIGN(-42)
=> -1
ABS(-42)
=> 42
THROW("my error") => PARSER FAIL: Error: my error
eval
/Function('...')
parsing.Rule[]
the sole recursive type.{"and": []}
{"or": []}
).{"try": "rules", "catch": {"return": "error"}}
{"run": Rule[] | Rule | "ruleSetName"}
{"log": "rule/value expression"}
{"set": "newVar = value"}
undefined
, valueOf
, toString
, __proto__
, constructor
.No vulnerabilities found.
No security vulnerabilities found.