json-logic-engine
Version:
Construct complex rules with JSON & process them.
149 lines (102 loc) • 5.14 kB
Markdown
# JSON Logic Engine
[](https://github.com/standard/standard)
[](https://badge.fury.io/js/json-logic-engine) [](https://coveralls.io/github/TotalTechGeek/json-logic-engine?branch=master) [](https://travis-ci.com/TotalTechGeek/json-logic-engine)

### Fast, Powerful, and Persistable Logic
Have you ever needed the ability to write a custom set of logic or set of rules for a particular customer? Or needed to be able to configure a piece of logic on the fly?
JSON Logic might be your solution! Designed with a lisp-like syntax, JSON Logic makes it easy to write safe instructions that can be persisted into a database, and shared between the front-end and back-end.
Check out our [Documentation Here](https://json-logic.github.io/json-logic-engine/).
## Why json-logic-engine?
This library was built as a more modern, performant, and feature-rich alternative to [`json-logic-js`](https://github.com/jwadhams/json-logic-js). Here's why you might choose it:
### Performance
- **Optimized Interpreter**: Uses closures to achieve ~5x faster evaluation on average
- **Logic Compilation**: Compile your rules for 12.5-20x performance improvements in hot paths
- **Deterministic Evaluation**: Prevents redundant re-computation of deterministic logic
### Features
- **Async Support**: First-class support for asynchronous logic evaluation
- **Custom Control Structures**: Define your own operators with lazy or eager evaluation semantics
- **Scope Traversal**: Handlebars-style `../../` traversal for accessing outer context in iterators
- **Error Handling**: Try/throw support with stricter error handling
- **Extended Proposals**: Implements additional JSON Logic specification proposals
### Modern JavaScript
- **Proper ESM & CJS Support**: Dual-build package with proper ES Modules and CommonJS support
- Unlike json-logic-js which uses a non-standard module format (neither proper CJS nor UMD), this library works seamlessly with modern bundlers and Node.js
### Security
- Better safeguards when evaluating rules from untrusted sources
### Bundle Size Concerns?
If bundle size is critical for your use case, check out [`json-logic-engine-slim`](https://www.npmjs.com/package/json-logic-engine-slim) (~4kB gzipped) which provides core functionality with a smaller footprint.
The engine supports both synchronous & asynchronous operations, and can use function compilation to keep your logic performant at scale.
Examples:
The premise is the logic engine traverses the document you pass in, and each "object" is interpreted as an instruction for the engine to run.
```js
logic.run({
'+': [1,2,3,4,5]
}) // 15
```
If you wanted to start factoring variables, you can pass a data object into it, and reference them using the "var" instruction:
```js
logic.run({
'+': [11, { var: 'a' }]
}, {
'a': 17
}) // 28
```
The engine will also allow you to reference variables that are several layers deep:
```js
logic.run({
'+': [{ var: 'a.b.c' }, 5]
}, {
a: { b: { c: 7 } }
}) // 12
```
Let's explore some slightly more complex logic:
```js
logic.run({
'reduce': [{ var: 'x' }, { '+': [{ var: 'current' }, { var: 'accumulator' }] }, 0]
}, {
'x': [1,2,3,4,5]
}) // 15
```
In this example, we run the reduce operation on a variable called "x", and we set up instructions to add the "current" value to the "accumulator", which we have set to 0.
Similarly, you can also do `map` operations:
```js
logic.run({
'map': [[1,2,3,4,5], { '+': [{ var: '' }, 1] }]
}) // [2,3,4,5,6]
```
If `var` is left as an empty string, it will assume you're referring to the whole variable that is accessible at the current layer it is looking at.
Example of a map accessing variables of the objects in the array:
```js
logic.run({
'map': [{var : 'x'}, { '+': [{ var: 'a' }, 1] }]
},
{
'x': [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }]
}) // [2,3,4,5]
```
You can easily nest different operations in each other, like so:
```js
logic.run({
max: [200, {
'*': [12, {var: 'a' }]
}]
}, {
a: 16
}) // 200
```
The engine also supports Handlebars-esque style traversal of data when you use the iterative control structures.
For example:
```js
logic.run({
'map': [{var : 'x'}, { '+': [{ var: 'a' }, { var: '../../adder'}] }]
},
{
'x': [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }],
'adder': 7
}) // [8, 9, 10, 11]
```
## Migrating from json-logic-js
This library is designed as a drop-in replacement for `json-logic-js`. Most existing rules should work without modification, while giving you access to all the performance and feature improvements mentioned above.