Compile MongoDB-like boolean expressions based on boolean operators AND and OR
Use one of the two based on your project's dependency manager.
$ npm install logical-compiler --save
$ yarn add logical-compilerimport compile from 'logical-compiler';
compile(expression, options);Arguments:
expression- the boolean expression to be executed.options- an optional object specifying options.fns- an optional attribute specifying any function(s) used on the expression.
let expression = { $and: [true, true] };
compile(expression); // true
expression = { $and: [true, false] };
compile(expression); // false
expression = { $and: [false, true] };
compile(expression); // false
expression = { $and: [false, false] };
compile(expression); // falselet expression = { $or: [true, true] };
compile(expression); // true
expression = { $or: [true, false] };
compile(expression); // true
expression = { $or: [false, true] };
compile(expression); // true
expression = { $or: [false, false] };
compile(expression); // falseconst expression = { $someOp: ['x', 'y'] };
compile(expression); // Error: Unrecognized operator: '$someOp'compile(); // Error: Expected an expressioncompile(true); // true
compile(false); // falseconst expression = 'test';
compile(expression); // Error: Unexpected token 'test'const expression = 201;
compile(expression); // Error: Unexpected token '201'let cb = () => true;
compile(cb); // true
cb = () => false;
compile(cb); // falsecb = () => Promise.resolve(true);
await compile(cb); //true
cb = () => Promise.resolve(false);
await compile(cb); // falseconst expression = {
$and: [true, () => Promise.resolve(true)],
};
await compile(expression); // trueconst options = {
fns: {
isEven: (number) => number % 2 === 0,
},
};
let expression = { isEven: 7 };
compile(expression, options); // false
expression = { isEven: 6 };
compile(expression, options); // trueNote that the function is defined on the
fnsattribute of theoptionsargument.
const options = {
fns: {
isEqual: (num1, num2) => Promise.resolve(num1 === num2),
},
};
expression = { isEqual: [3, 3] };
await compile(expression, options); // true
expression = { isEqual: [3, 5] };
await compile(expression, options); // falseconst options = {
fns: {
authenticated: () => Promise.resolve(true),
},
};
const expression = {
$or: [false, { authenticated: null }],
};
await compile(expression, options); // trueconst expression = { someFn: ['x', 'y'] };
compile(expression, options); // Error: Undefined function: 'someFn'let expression = {
$or: [{ $and: [true, true] }, false],
};
compile(expression); // trueexpression = {
$or: [() => false, () => false],
};
compile(expression); // falseexpression = {
$and: [() => true, true],
};
compile(expression); // trueexpression = {
$or: [
() => false,
false,
{
$and: [true, { $or: [() => true, false] }],
},
],
};
compile(expression); // trueconst options = {
fns: {
any: (target, values) => values.includes(target),
all: (targets, values) => targets.every((target) => values.includes(target)),
},
};
expression = {
$and: [
() => true,
{ $or: [true, false] },
{ any: [5, [1, 3, 4, 6, 7]] }
],
};
compile(expression, options); // false
expression = {
$or: [
() => false,
false,
{ $and: [true, false] },
{
all: [
[3, 4, 7],
[2, 3, 4, 5, 6, 7],
],
},
],
};
compile(expression, options); // trueOperators can be nested in any fashion to achieve the desired logical check.
-
compilereturnsbooleanfor fully synchronous expressions andPromise<boolean>when any callback or function returns a promise.$andstops at the firstfalse;$orstops at the firsttrue. Later operands (including async ones) are not evaluated. -
Callbacks and functions must explicitly return boolean values to avoid the ambiguity of relying on truthiness. Relying on truthiness would pose a serious loophole because the executable might accidentally resolve to true on a non-boolean value. If the library encounters a callback that resolves to a non-boolean value, it throws an exception. See MDN documentation on truthy values.
MIT © Mutai Mwiti | GitHub | GitLab
DISCLAIMER: All opinions expressed in this repository are mine and do not reflect any company or organisation I'm involved with.