Gathering detailed insights and metrics for @briza/illogical
Gathering detailed insights and metrics for @briza/illogical
Gathering detailed insights and metrics for @briza/illogical
Gathering detailed insights and metrics for @briza/illogical
A micro conditional javascript engine used to parse the raw logical and comparison expressions, evaluate the expression in the given data context, and provide access to a text form of the given expressions.
npm install @briza/illogical
Typescript
Module System
Node Version
NPM Version
TypeScript (99.07%)
JavaScript (0.93%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
21 Stars
405 Commits
3 Forks
17 Watchers
11 Branches
23 Contributors
Updated on Jul 09, 2025
Latest Version
1.7.0
Package Id
@briza/illogical@1.7.0
Unpacked Size
206.89 kB
Size
35.79 kB
File Count
58
NPM Version
10.8.2
Node Version
20.19.0
Published on
Jul 09, 2025
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
26
A micro conditional javascript engine used to parse the raw logical and comparison expressions, evaluate the expression in the given data context, and provide access to a text form of the given expressions.
Revision: March 22, 2022.
This project has been developed to provide a shared conditional logic between front-end and back-end code, stored in JSON or in any other data serialization format.
Code documentation could be found here: https://briza-insurance.github.io/illogical/index.html.
The library is being build as CommonJS module and ESM.
1npm install -D @briza/illogical
1yarn add @briza/illogical -D
Table of Content
1// Import the illogical engine 2import Engine from '@briza/illogical' 3 4// Create a new instance of the engine 5const engine = new Engine() 6 7// Evaluate the raw expression 8const result = engine.evaluate(['==', 5, 5])
For advanced usage, please Engine Options.
Evaluate comparison or logical expression as TRUE or FALSE result:
engine.evaluate(
Comparison Expression or Logical Expression, Evaluation Data Context)
=> boolean
Data context is optional.
Example
1// Comparison expression 2engine.evaluate(['==', 5, 5]) 3engine.evaluate(['==', 'circle', 'circle']) 4engine.evaluate(['==', true, true]) 5engine.evaluate(['==', '$name', 'peter'], { name: 'peter' }) 6engine.evaluate(['UNDEFINED', '$RefA'], {}) 7 8// Logical expression 9engine.evaluate(['AND', ['==', 5, 5], ['==', 10, 10]]) 10engine.evaluate(['AND', ['==', 'circle', 'circle'], ['==', 10, 10]]) 11engine.evaluate(['OR', ['==', '$name', 'peter'], ['==', 5, 10]], { 12 name: 'peter', 13})
Get expression string representation:
engine.statement(
Comparison Expression or Logical Expression)
=> string
Example
1/* Comparison expression */ 2 3engine.statement(['==', 5, 5]) 4// (5 == 5) 5 6engine.statement(['==', 'circle', 'circle']) 7// ("circle" == "circle") 8 9engine.statement(['==', true, true]) 10// (true == true) 11 12engine.statement(['==', '$name', 'peter'], { name: 'peter' }) 13// ({name} == "peter") 14 15engine.statement(['UNDEFINED', '$RefA']) 16// ({RefA} is UNDEFINED) 17 18/* Logical expression */ 19 20engine.statement(['AND', ['==', 5, 5], ['==', 10, 10]]) 21// ((5 == 5) AND (10 == 10)) 22 23engine.statement(['AND', ['==', 'circle', 'circle'], ['==', 10, 10]]) 24// (("circle" == "circle") AND (10 == 10)) 25 26engine.statement(['OR', ['==', '$name', 'peter'], ['==', 5, 10]], { 27 name: 'peter', 28}) 29// (({name} == "peter") OR (5 == 10))
Parse the expression into a evaluable object, i.e. it returns the parsed self-evaluable condition expression.
engine.parse(
Comparison Expression or Logical Expression)
=> evaluable
evaluable.evaluate(context)
please see Evaluation Data Context.evaluable.toString()
please see Statement.Example
1let evaluable = engine.parse(['==', '$name', 'peter']) 2 3evaluable.evaluate({ name: 'peter' }) // true 4 5evaluable.toString() 6// ({name} == "peter")
Simplifies an expression with a given context. This is useful when you already have some of the properties of context and wants to try to evaluate the expression.
Example
1engine.simplify(['AND', ['==', '$a', 10], ['==', '$b', 20]], { a: 10 }) // ['==', '$b', 20] 2 3engine.simplify(['AND', ['==', '$a', 10], ['==', '$b', 20]], { a: 20 }) // false
Values not found in the context will cause the parent operand not to be evaluated and returned as part of the simplified expression.
In some situations we might want to evaluate the expression even if referred value is not present. You can provide a list of keys that will be strictly evaluated even if they are not present in the context.
Example
1engine.simplify( 2 ['AND', ['==', '$a', 10], ['==', '$b', 20]], 3 { a: 10 }, 4 ['b'] // '$b' will be evaluated to undefined. 5) // false
Alternatively we might want to do the opposite and strictly evaluate the expression for all referred values not present in the context except for a specified list of optional keys.
Example
1engine.simplify( 2 ['OR', ['==', '$a', 10], ['==', '$b', 20], ['==', '$c', 20]], 3 { c: 10 }, 4 undefined, 5 ['b'] // except for '$b' everything not in context will be evaluated to undefined. 6) // ['==', '$b', 20]
Simplifies an expression with a given context, but without parsing and ensuring the condition is syntatically correct. This can be used in situations where you can decouple the parsing from the simplification and extra performance is needed in runtime.
1engine.unsafeSimplify( 2 ['OR', ['==', '$a', 10], ['==', '$b', 20], ['==', '$c', 20]], 3 { a: 10 } 4) // true due to $a. Expressions for $b and $c won't even be parsed.
The evaluation data context is used to provide the expression with variable references, i.e. this allows for the dynamic expressions. The data context is object with properties used as the references keys, and its values as reference values.
Valid reference values: object, string, number, boolean, string[], number[].
To reference the nested reference, please use "." delimiter, e.g.:
$address.city
If the key of the nested reference includes the "." delimiter, please wrap the whole key with backticks `
, e.g.:
$address.`city.code`
can reference the object
1{ 2 address: { 3 'city.code': 'TOR' 4 } 5}
$address.`city.code`[0]
can reference the object
1{ 2 address: { 3 'city.code': ['TOR'] 4 } 5}
when the value of the nested reference is an array.
$options[1]
$options[{index}]
$address.{segment}
$shape{shapeType}
$payment.amount.(Type)
Cast the given data context into the desired data type before being used as an operand in the evaluation.
Note: If the conversion is invalid, then a warning message is being logged.
Supported data type conversions:
Example
1// Data context 2const ctx = { 3 name: 'peter', 4 country: 'canada', 5 age: 21, 6 options: [1, 2, 3], 7 address: { 8 city: 'Toronto', 9 country: 'Canada', 10 }, 11 index: 2, 12 segment: 'city', 13 shapeA: 'box', 14 shapeB: 'circle', 15 shapeType: 'B', 16} 17 18// Evaluate an expression in the given data context 19engine.evaluate(['>', '$age', 20], ctx) // true 20 21// Evaluate an expression in the given data context 22engine.evaluate(['==', '$address.city', 'Toronto'], ctx) // true 23 24// Accessing Array Element 25engine.evaluate(['==', '$options[1]', 2], ctx) // true 26 27// Accessing Array Element via Reference 28engine.evaluate(['==', '$options[{index}]', 3], ctx) // true 29 30// Nested Referencing 31engine.evaluate(['==', '$address.{segment}', 'Toronto'], ctx) // true 32 33// Composite Reference Key 34engine.evaluate(['==', '$shape{shapeType}', 'circle'], ctx) // true 35 36// Data Type Casting 37engine.evaluate(['==', '$age.(String)', '21'], ctx) // true
The Comparison Expression expect operands to be one of the below:
Simple value types: string, number, boolean.
Example
1;['==', 5, 5][('==', 'circle', 'circle')][('==', true, true)]
The reference operand value is resolved from the Evaluation Data Context, where the the operands name is used as key in the context.
The reference operand must be prefixed with $
symbol, e.g.: $name
. This might be customized via Reference Predicate Parser Option.
Example
Expression | Data Context |
---|---|
['==', '$age', 21] | {age: 21} |
['==', 'circle', '$shape'] | {shape: 'circle'} |
['==', '$visible', true] | {visible: true} |
['==', '$circle', '$shape'] | {circle: 'circle', shape: 'circle'} |
The operand could be an array mixed from Value and Reference.
Example
Expression | Data Context |
---|---|
['IN', [1, 2], 1] | {} |
['IN', 'circle', ['$shapeA', $shapeB] | {shapeA: 'circle', shapeB: 'box'} |
['IN', [$number, 5], 5] | {number: 3} |
Expression format: ["==",
Left Operand, Right Operand]
.
Valid operand types: string, number, boolean.
1["==", 5, 5]
1engine.evaluate(['==', 5, 5]) // true
Expression format: ["!=",
Left Operand, Right Operand]
.
Valid operand types: string, number, boolean.
1["!=", "circle", "square"]
1engine.evaluate(['!=', 'circle', 'square']) // true
Expression format: [">",
Left Operand, Right Operand]
.
Valid operand types: number, string.
1[">", 10, 5] 2[">", "2023-01-01", "2022-12-31"]
1engine.evaluate(['>', 10, 5]) // true 2engine.evaluate(['>', '2023-01-01', '2022-12-31']) // true
Expression format: [">=",
Left Operand, Right Operand]
.
Valid operand types: number, string.
1[">=", 5, 5] 2[">=", "2023-01-01", "2023-01-01"]
1engine.evaluate(['>=', 5, 5]) // true 2engine.evaluate(['>=', '2023-01-01', '2023-01-01']) // true
Expression format: ["<",
Left Operand, Right Operand]
.
Valid operand types: number, string.
1["<", 5, 10] 2["<", "2022-12-31", "2023-01-01"]
1engine.evaluate(['<', 5, 10]) // true 2engine.evaluate(['<', '2022-12-31', '2023-01-01']) // true
Expression format: ["<=",
Left Operand, Right Operand]
.
Valid operand types: number, string.
1["<=", 5, 5] 2["<=", "2023-01-01", "2023-01-01"]
1engine.evaluate(['<=', 5, 5]) // true 2engine.evaluate(['<=', '2023-01-01', '2023-01-01']) // true
Expression format: ["IN",
Left Operand, Right Operand]
.
Valid operand types: number and number[] or string and string[].
1["IN", 5, [1,2,3,4,5]] 2["IN", ["circle", "square", "triangle"], "square"]
1engine.evaluate(['IN', 5, [1, 2, 3, 4, 5]]) // true 2engine.evaluate(['IN', ['circle', 'square', 'triangle'], 'square']) // true
Expression format: ["NOT IN",
Left Operand, Right Operand]
.
Valid operand types: number and number[] or string and string[].
1["IN", 10, [1,2,3,4,5]] 2["IN", ["circle", "square", "triangle"], "oval"]
1engine.evaluate(['NOT IN', 10, [1, 2, 3, 4, 5]]) // true 2engine.evaluate(['NOT IN', ['circle', 'square', 'triangle'], 'oval']) // true
Expression format: ["PREFIX",
Left Operand, Right Operand]
.
Valid operand types: string.
1["PREFIX", "hemi", "hemisphere"]
1engine.evaluate(['PREFIX', 'hemi', 'hemisphere']) // true 2engine.evaluate(['PREFIX', 'hemi', 'sphere']) // false
Expression format: ["SUFFIX",
Left Operand, Right Operand]
.
Valid operand types: string.
1["SUFFIX", "establishment", "ment"]
1engine.evaluate(['SUFFIX', 'establishment', 'ment']) // true 2engine.evaluate(['SUFFIX', 'establish', 'ment']) // false
Expression format: ["OVERLAP",
Left Operand, Right Operand]
.
Valid operand types number[] or string[].
1["OVERLAP", [1, 2], [1, 2, 3, 4, 5]] 2["OVERLAP", ["circle", "square", "triangle"], ["square"]]
1engine.evaluate(['OVERLAP', [1, 2, 6], [1, 2, 3, 4, 5]]) // true 2engine.evaluate([ 3 'OVERLAP', 4 ['circle', 'square', 'triangle'], 5 ['square', 'oval'], 6]) // true
Expression format: ["UNDEFINED",
Reference Operand]
.
1["UNDEFINED", "$RefA"]
1engine.evaluate(['UNDEFINED', 'RefA'], {}) // true 2engine.evaluate(['UNDEFINED', 'RefA'], { RefA: undefined }) // true 3engine.evaluate(['UNDEFINED', 'RefA'], { RefA: 10 }) // false
Evaluates as FALSE when the operand is UNDEFINED or NULL.
Expression format: ["PRESENT",
Reference Operand]
.
1["PRESENT", "$RefA"]
1engine.evaluate(['PRESENT', 'RefA'], {}) // false 2engine.evaluate(['PRESENT', 'RefA'], { RefA: undefined }) // false 3engine.evaluate(['PRESENT', 'RefA'], { RefA: null }) // false 4engine.evaluate(['PRESENT', 'RefA'], { RefA: 10 }) // true 5engine.evaluate(['PRESENT', 'RefA'], { RefA: false }) // true 6engine.evaluate(['PRESENT', 'RefA'], { RefA: 0 }) // true
The logical AND operator (&&) returns the boolean value TRUE if both operands are TRUE and returns FALSE otherwise.
Expression format: ["AND", Left Operand 1, Right Operand 2, ... , Right Operand N]
.
Valid operand types: Comparison Expression or Nested Logical Expression.
1["AND", ["==", 5, 5], ["==", 10, 10]]
1engine.evaluate(['AND', ['==', 5, 5], ['==', 10, 10]]) // true
The logical OR operator (||) returns the boolean value TRUE if either or both operands is TRUE and returns FALSE otherwise.
Expression format: ["OR", Left Operand 1, Right Operand 2, ... , Right Operand N]
.
Valid operand types: Comparison Expression or Nested Logical Expression.
1["OR", ["==", 5, 5], ["==", 10, 5]]
1engine.evaluate(['OR', ['==', 5, 5], ['==', 10, 5]]) // true
The logical NOR operator returns the boolean value TRUE if both operands are FALSE and returns FALSE otherwise.
Expression format: ["NOR", Left Operand 1, Right Operand 2, ... , Right Operand N]
Valid operand types: Comparison Expression or Nested Logical Expression.
1["NOR", ["==", 5, 1], ["==", 10, 5]]
1engine.evaluate(['NOR', ['==', 5, 1], ['==', 10, 5]]) // true
The logical NOR operator returns the boolean value TRUE if both operands are FALSE and returns FALSE otherwise.
Expression format: ["XOR", Left Operand 1, Right Operand 2, ... , Right Operand N]
Valid operand types: Comparison Expression or Nested Logical Expression.
1["XOR", ["==", 5, 5], ["==", 10, 5]]
1engine.evaluate(['XOR', ['==', 5, 5], ['==', 10, 5]]) // true
1["XOR", ["==", 5, 5], ["==", 10, 10]]
1engine.evaluate(['XOR', ['==', 5, 5], ['==', 10, 10]]) // false
The logical NOT operator returns the boolean value TRUE if the operand is FALSE, TRUE otherwise.
Expression format: ["NOT", Operand]
Valid operand types: Comparison Expression or Nested Logical Expression.
1["NOT", ["==", 5, 5]]
1engine.evaluate(['NOT', ['==', 5, 5]]) // true
Arithmetic Expressions are not supported as root level expressions since they must evaluate to a boolean. But it can be used nested within Comparisson Expressions.
The arithmetical operator for division produces the quotient of its operands where the left-most operand is the dividend and the subsequent one is the divisor, done from left to right.
Expression format: ["/", First Operand, Second Operand, ... , Nth Operand]
.
Valid operand types: Arithmetic Expressions or Operands.
1["==", ["/", 100, 10], 10]
1engine.evaluate(['==', ['/', 100, 10], 10]) // true
The arithmetical operator for multiplication produces the product of the operands.
Expression format: ["*", First Operand, Second Operand, ... , Nth Operand]
.
Valid operand types: Arithmetic Expressions or Operands.
1["==", ["*", 100, 10], 10]
1engine.evaluate(['==', ['*', 10, 10], 100]) // true
The arithmetical operator for subtraction subtracts the operands, producing their difference.
Expression format: ["-", First Operand, Second Operand, ... , Nth Operand]
.
Valid operand types: Arithmetic Expressions or Operands.
1["==", ["-", 20, 10], 10]
1engine.evaluate(['==', ['-', 20, 10], 10]) // true
The arithmetical operator for addition produces the sum of the operands.
Expression format: ["+", First Operand, Second Operand, ... , Nth Operand]
.
Valid operand types: Arithmetic Expressions or Operands.
1["==", ["+", 5, 5], 10]
1engine.evaluate(['==', ['+', 5, 5], 10]) // true
Below described, are individual options object properties which could be used individually. Any missing options will be substituted with the default options.
Usage
1// Import the illogical engine 2import Engine from '@briza/illogical' 3 4// Create a new instance of the engine 5const opts = { 6 referencePredicate: (operand) => operand.startsWith('$'), 7} 8const engine = new Engine(opts)
A function used to determine if the operand is a reference type, otherwise evaluated as a static value.
1referencePredicate: (operand: string) => boolean
Return value:
true
= reference typefalse
= value typeDefault reference predicate:
The
$
symbol at the begging of the operand is used to predicate the reference type., E.g.$State
,$Country
.
A function used to transform the operand into the reference annotation stripped form. I.e. remove any annotation used to detect the reference type. E.g. "$Reference" => "Reference".
1referenceTransform: (operand: string) => string
Default reference transform: It removes the
$
symbol at the begging of the operand name.
Mapping of the operators. The key is unique operator key, and the value is the key used to represent the given operator in the raw expression.
1operatorMapping: Map<symbol, string>
Default operator mapping:
1 // Comparison 2 [OPERATOR_EQ, '=='], 3 [OPERATOR_NE, '!='], 4 [OPERATOR_GT, '>'], 5 [OPERATOR_GE, '>='], 6 [OPERATOR_LT, '<'], 7 [OPERATOR_LE, '<='], 8 [OPERATOR_IN, 'IN'], 9 [OPERATOR_NOT_IN, 'NOT IN'], 10 [OPERATOR_PREFIX, 'PREFIX'], 11 [OPERATOR_SUFFIX, 'SUFFIX'], 12 [OPERATOR_OVERLAP, 'OVERLAP'], 13 [OPERATOR_UNDEFINED, 'UNDEFINED'], 14 [OPERATOR_PRESENT, 'PRESENT'], 15 // Logical 16 [OPERATOR_AND, 'AND'], 17 [OPERATOR_OR, 'OR'], 18 [OPERATOR_NOR, 'NOR'], 19 [OPERATOR_XOR, 'XOR'], 20 [OPERATOR_NOT, 'NOT'], 21 // Arithmetic 22 [OPERATOR_SUM, '+'], 23 [OPERATOR_SUBTRACT, '-'], 24 [OPERATOR_MULTIPLY, '*'], 25 [OPERATOR_DIVIDE, '/'],
The operator keys are unique symbols which could be imported from the engine package:
1import { 2 OPERATOR_EQ, 3 OPERATOR_NE, 4 OPERATOR_GT, 5 OPERATOR_GE, 6 OPERATOR_LT, 7 OPERATOR_LE, 8 OPERATOR_IN, 9 OPERATOR_NOT_IN, 10 OPERATOR_PREFIX, 11 OPERATOR_SUFFIX, 12 OPERATOR_OVERLAP, 13 OPERATOR_UNDEFINED, 14 OPERATOR_PRESENT, 15 OPERATOR_AND, 16 OPERATOR_OR, 17 OPERATOR_NOR, 18 OPERATOR_XOR, 19 OPERATOR_NOT, 20 OPERATOR_DIVIDE, 21 OPERATOR_MULTIPLY, 22 OPERATOR_SUBTRACT, 23 OPERATOR_SUM, 24} from '@briza/illogical'
@babel/env
preset to target > 1%, node 12
this will remove some polyfills that were causing performance
problems in some projects.const engine = new Engine(strictMode, opts);
-> const engine = new Engine(opts);
See contributing.md.
Illogical is released under the MIT license. See license.txt.
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
all changesets reviewed
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
1 existing vulnerabilities detected
Details
Reason
2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More