{"id":25495356,"url":"https://github.com/mutaimwiti/logical-compiler","last_synced_at":"2026-05-29T21:00:32.213Z","repository":{"id":90781940,"uuid":"326370532","full_name":"mutaimwiti/logical-compiler","owner":"mutaimwiti","description":"Compile MongoDB-like boolean expressions based on boolean operators AND and OR","archived":false,"fork":false,"pushed_at":"2026-05-29T19:06:16.000Z","size":181,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-29T19:16:16.468Z","etag":null,"topics":["bool","boolean","compile","compiler","expression","logic","logical","mongo","mongodb"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mutaimwiti.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-01-03T09:30:30.000Z","updated_at":"2026-05-29T18:50:15.000Z","dependencies_parsed_at":"2023-07-23T05:02:28.078Z","dependency_job_id":null,"html_url":"https://github.com/mutaimwiti/logical-compiler","commit_stats":null,"previous_names":["mutaimwiti/bool-eval"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/mutaimwiti/logical-compiler","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutaimwiti%2Flogical-compiler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutaimwiti%2Flogical-compiler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutaimwiti%2Flogical-compiler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutaimwiti%2Flogical-compiler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mutaimwiti","download_url":"https://codeload.github.com/mutaimwiti/logical-compiler/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mutaimwiti%2Flogical-compiler/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33670211,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bool","boolean","compile","compiler","expression","logic","logical","mongo","mongodb"],"created_at":"2025-02-19T00:36:08.361Z","updated_at":"2026-05-29T21:00:32.207Z","avatar_url":"https://github.com/mutaimwiti.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# logical-compiler\n\n[![build](https://github.com/mutaimwiti/logical-compiler/actions/workflows/ci.yml/badge.svg)](https://github.com/mutaimwiti/logical-compiler/actions/workflows/ci.yml)\n[![version](https://img.shields.io/npm/v/logical-compiler.svg)](https://www.npmjs.com/package/logical-compiler)\n[![downloads](https://img.shields.io/npm/dm/logical-compiler.svg)](https://www.npmjs.com/package/logical-compiler)\n[![license](https://img.shields.io/npm/l/logical-compiler.svg)](https://www.npmjs.com/package/logical-compiler)\n\nCompile MongoDB-like boolean expressions based on boolean operators `AND` and `OR`\n\n### Installation\n\nUse one of the two based on your project's dependency manager.\n\n```bash\n$ npm install logical-compiler --save\n\n$ yarn add logical-compiler\n```\n\n### Getting started\n\n```javascript\nimport compile from 'logical-compiler';\n\ncompile(expression, options);\n```\n\nArguments:\n\n- `expression` - the boolean expression to be executed.\n- `options` - an optional object specifying options.\n  - `fns` - an optional attribute specifying any function(s) used on the expression.\n   \n### Operators\n\n#### AND operator\n\n```javascript\nlet expression = { $and: [true, true] };\ncompile(expression); // true\n\nexpression = { $and: [true, false] };\ncompile(expression); // false\n\nexpression = { $and: [false, true] };\ncompile(expression); // false\n\nexpression = { $and: [false, false] };\ncompile(expression); // false\n```\n\n#### OR operator\n\n```javascript\nlet expression = { $or: [true, true] };\ncompile(expression); // true\n\nexpression = { $or: [true, false] };\ncompile(expression); // true\n\nexpression = { $or: [false, true] };\ncompile(expression); // true\n\nexpression = { $or: [false, false] };\ncompile(expression); // false\n```\n\n#### NOT operator\n\n`$not` takes a single expression and returns its negation.\n\n```javascript\nlet expression = { $not: true };\ncompile(expression); // false\n\nexpression = { $not: { $and: [true, true] } };\ncompile(expression); // false\n```\n\n#### NOR operator\n\n`$nor` takes an array and returns the negation of `$or` over it, i.e. `true`\nonly when every operand is `false`.\n\n```javascript\nlet expression = { $nor: [false, false] };\ncompile(expression); // true\n\nexpression = { $nor: [false, true] };\ncompile(expression); // false\n```\n\n#### Unrecognized operator\n```javascript\nconst expression = { $someOp: ['x', 'y'] };\n\ncompile(expression); // Error: Unrecognized operator: '$someOp'\n```\n\n### Primitives\n\n#### undefined\n```javascript\ncompile(); // Error: Expected an expression\n```\n\n#### boolean\n```javascript\ncompile(true); // true\n\ncompile(false); // false\n```\n\n#### string\n```javascript\nconst expression = 'test';\n\ncompile(expression); // Error: Unexpected token 'test'\n```\n\n#### number\n```javascript\nconst expression = 201;\n\ncompile(expression); // Error: Unexpected token '201'\n```\n\n### Callbacks\n\nA callback is a function that returns a boolean. If it returns a promise,\n`compile` resolves to a promise you `await`.\n\n```javascript\nlet cb = () =\u003e true;\ncompile(cb); // true\n\ncb = () =\u003e Promise.resolve(false);\nawait compile(cb); // false\n```\n\n#### Nested promise callback\n\n```javascript\nconst expression = {\n  $and: [true, () =\u003e Promise.resolve(true)],\n};\n\nawait compile(expression); // true\n```\n\n### Functions\n\nA function is defined on the `fns` attribute of the `options` argument. It may\nreturn a boolean or a promise.\n\n```javascript\nconst options = {\n  fns: {\n    isEven: (number) =\u003e number % 2 === 0,\n    isEqual: (num1, num2) =\u003e Promise.resolve(num1 === num2),\n  },\n};\n\ncompile({ isEven: 6 }, options); // true\n\nawait compile({ isEqual: [3, 5] }, options); // false\n```\n\n#### Nested promise function\n\n```javascript\nconst options = {\n  fns: {\n    authenticated: () =\u003e Promise.resolve(true),\n  },\n};\n\nconst expression = {\n  $or: [false, { authenticated: null }],\n};\n\nawait compile(expression, options); // true\n```\n\n#### Undefined function\n\n```javascript\nconst expression = { someFn: ['x', 'y'] };\n\ncompile(expression, options); // Error: Undefined function: 'someFn'\n````\n\n### Compound expressions\n\n```javascript\nlet expression = {\n  $or: [{ $and: [true, true] }, false],\n};\n\ncompile(expression); // true\n```\n\n```javascript\nexpression = {\n  $or: [() =\u003e false, () =\u003e false],\n};\n\ncompile(expression); // false\n```\n\n```javascript\nexpression = {\n  $and: [() =\u003e true, true],\n};\n\ncompile(expression); // true\n```\n\n```javascript\nexpression = {\n  $or: [\n    () =\u003e false,\n    false,\n    {\n      $and: [true, { $or: [() =\u003e true, false] }],\n    },\n  ],\n};\n\ncompile(expression); // true\n```\n\n```javascript\nconst options = {\n  fns: {\n    any: (target, values) =\u003e values.includes(target),\n    all: (targets, values) =\u003e targets.every((target) =\u003e values.includes(target)),\n  },\n};\n\nexpression = {\n  $and: [\n    () =\u003e true, \n    { $or: [true, false] },\n    { any: [5, [1, 3, 4, 6, 7]] }\n  ],\n};\n\ncompile(expression, options); // false\n\nexpression = {\n  $or: [\n    () =\u003e false,\n    false,\n    { $and: [true, false] },\n    {\n      all: [\n        [3, 4, 7],\n        [2, 3, 4, 5, 6, 7],\n      ],\n    },\n  ],\n};\n\ncompile(expression, options); // true\n```\n\n\u003e Operators can be nested in any fashion to achieve the desired logical check.\n\n### Multiple keys (implicit AND)\n\nWhen an object expression has more than one key, the keys are AND-ed together,\nat any nesting depth. This applies to operators and functions alike.\n\n```javascript\nconst options = {\n  fns: {\n    isEven: (number) =\u003e number % 2 === 0,\n  },\n};\n\nlet expression = { $or: [false, true], isEven: 6 };\ncompile(expression, options); // true  ($or AND isEven)\n\nexpression = { $or: [false, true], isEven: 7 };\ncompile(expression, options); // false ($or is true, but isEven is false)\n```\n\nAn empty object is not a valid expression and throws:\n\n```javascript\ncompile({}); // Error: Expected an expression\n```\n\n##### IMPORTANT NOTES\n\n1. `compile` returns `boolean` for fully synchronous expressions and `Promise\u003cboolean\u003e` when any callback or\n   function returns a promise. `$and` stops at the first `false`; `$or` stops at the first `true`. Later operands\n   (including async ones) are not evaluated.\n\n2. Callbacks and functions must explicitly return boolean values to avoid the ambiguity of relying on truthiness. \n   Relying on truthiness would pose a serious loophole because the executable might accidentally resolve to true on a \n   non-boolean value. If the library encounters a callback that resolves to a non-boolean value, it throws an exception. \n   See [MDN](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) documentation on truthy values.\n\n### Error handling\n\nAll errors thrown by `compile` are instances of `LogicalCompilerError`, a\nsubclass of `Error` that carries a `.code` field for programmatic handling. The\nhuman-readable `.message` is unchanged.\n\n```javascript\nimport compile from 'logical-compiler';\n\ntry {\n  compile({ $unknown: [] });\n} catch (error) {\n  error instanceof compile.LogicalCompilerError; // true\n  error.code; // 'UNRECOGNIZED_OPERATOR'\n}\n```\n\nCodes: `UNRECOGNIZED_OPERATOR`, `UNDEFINED_FUNCTION`, `UNEXPECTED_TOKEN`,\n`UNEXPECTED_RETURN_TYPE`, `EXPECTED_EXPRESSION`.\n\n### TypeScript\n\nType declarations ship with the package, so no separate `@types` install is\nneeded. The supporting types `compile.Expression`, `compile.Options`, and\n`compile.LogicalCompilerError` are available for use in your own code.\n\n### Licence\n\n[MIT](https://mit-license.org/) © Mutai Mwiti |\n[GitHub](https://github.com/mutaimwiti) |\n[GitLab](https://gitlab.com/mutaimwiti)\n\n_**DISCLAIMER:**_\n_All opinions expressed in this repository are mine and do not reflect any company or organisation I'm involved with._\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmutaimwiti%2Flogical-compiler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmutaimwiti%2Flogical-compiler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmutaimwiti%2Flogical-compiler/lists"}