{"id":15616317,"url":"https://github.com/ilovepixelart/ts-rule-engine","last_synced_at":"2025-07-19T07:08:55.193Z","repository":{"id":186788764,"uuid":"675792206","full_name":"ilovepixelart/ts-rule-engine","owner":"ilovepixelart","description":"Lightweight rule engine, written in typescript","archived":false,"fork":false,"pushed_at":"2025-04-22T06:50:08.000Z","size":578,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-25T09:02:29.602Z","etag":null,"topics":["backend","engine","forward-chaining","library","node","rule","ts","ts-rule-engine","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/ilovepixelart.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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}},"created_at":"2023-08-07T18:26:14.000Z","updated_at":"2025-04-22T06:50:10.000Z","dependencies_parsed_at":"2023-12-06T11:06:26.382Z","dependency_job_id":"fea1c657-08d3-4069-b74d-086b1c8cfd63","html_url":"https://github.com/ilovepixelart/ts-rule-engine","commit_stats":null,"previous_names":["ilovepixelart/ts-rule-engine"],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilovepixelart%2Fts-rule-engine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilovepixelart%2Fts-rule-engine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilovepixelart%2Fts-rule-engine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilovepixelart%2Fts-rule-engine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ilovepixelart","download_url":"https://codeload.github.com/ilovepixelart/ts-rule-engine/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250787800,"owners_count":21487269,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["backend","engine","forward-chaining","library","node","rule","ts","ts-rule-engine","typescript"],"created_at":"2024-10-03T07:06:22.516Z","updated_at":"2025-04-28T16:21:18.990Z","avatar_url":"https://github.com/ilovepixelart.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ts-rule-engine\n\nLightweight rule engine, written in typescript\n\n[![npm](https://img.shields.io/npm/v/ts-rule-engine)](https://www.npmjs.com/package/ts-rule-engine)\n[![npm](https://img.shields.io/npm/dt/ts-rule-engine)](https://www.npmjs.com/package/ts-rule-engine)\n[![GitHub](https://img.shields.io/github/license/ilovepixelart/ts-rule-engine)](https://github.com/ilovepixelart/ts-rule-engine/blob/main/LICENSE)\n\\\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=ilovepixelart_ts-rule-engine\u0026metric=coverage)](https://sonarcloud.io/summary/new_code?id=ilovepixelart_ts-rule-engine)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=ilovepixelart_ts-rule-engine\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=ilovepixelart_ts-rule-engine)\n\\\n[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=ilovepixelart_ts-rule-engine\u0026metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=ilovepixelart_ts-rule-engine)\n[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=ilovepixelart_ts-rule-engine\u0026metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=ilovepixelart_ts-rule-engine)\n[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=ilovepixelart_ts-rule-engine\u0026metric=security_rating)](https://sonarcloud.io/summary/new_code?id=ilovepixelart_ts-rule-engine)\n\n## Supports and tested with\n\n```json\n{\n  \"node\": \"18.x || 20.x || 22.x\",\n}\n```\n\n## Features\n\n- Structure for rule definition\n- Rerun rules after fact is updated\n- Stop rule engine on any rule from executing further\n- Infinite loop prevention with max iterations limit\n- One time rule execution in sequence\n- Rule weight for priority\n- Logger interface for custom logging\n- Supports ESM and CommonJS\n\n## Installation\n\n```bash\nnpm install ts-rule-engine\npnpm add ts-rule-engine\nyarn add ts-rule-engine\nbun add ts-rule-engine\n```\n\n### 1. Defining a Rule\n\nA rule will consist of a condition and action, id, name and weight. The condition is a function that returns a boolean value. The action is a function that will be executed if the condition is true. The action function will be passed the fact, { rule, stop }. The stop function will stop the rule engine from executing further rules. This way you can control the flow of the rule engine.\n\n```typescript\nimport type { Rule } from 'ts-rule-engine'\n\n/* Define fact interface */\ninterface Fact {\n  balance: number\n  broke?: boolean\n}\n\n/* Define rule */\nconst rule: Rule\u003cFact\u003e = {\n  id: 1,\n  name: 'Rule 1',\n  weight: 1,\n  condition: (fact) =\u003e {\n    return fact.balance \u003c 5\n  },\n  action: (fact, { stop }) =\u003e {\n    fact.broke = true\n    /* stop() will stop the rule engine from executing further rules */\n    stop()\n  }\n}\n```\n\nHigher the weight of the rule, higher the priority of the rule. If the weight is not provided, it will be set to 0 by default and will be executed after all the rules with weight \u003e 0 are executed. If all weights are same, rules will be executed in the order they are added to the rule engine.\n\n### 2. Defining a Fact\n\nFacts are those input json values on which the rule engine applies its rule to obtain results. A fact can have multiple attributes as you decide.\n\nA sample Fact may look like\n\n```typescript\n/* Define fact interface */\ninterface Fact {\n  application: string\n  cost: number\n  license?: string\n  description?: string\n}\n\n/* Define fact */\nconst fact: Fact = {\n  application: 'ts-rule-engine',\n  cost: 0\n}\n```\n\n### 3. Using the Rule Engine\n\nThe example below shows how to use the rule engine to apply a sample rule on a specific fact. Rules can be fed into the rule engine as Array of rules or as an individual rule object.\n\n```typescript\nimport { RuleEngine } from 'ts-rule-engine'\n\n/* Define fact */\nconst fact: Fact = {\n  application: 'ts-rule-engine',\n  cost: 0,\n  license: '',\n  description: ''\n}\n\n/* Define rule */\nconst rule: Rule\u003cFact\u003e = {\n  condition: (fact) =\u003e {\n    return fact.cost === 0\n  },\n  consequence: (fact) =\u003e {\n    fact.license = 'MIT'\n    fact.description = 'License originating at the Massachusetts Institute of Technology (MIT) in the late 1980s'\n    fact.stop()\n  },\n};\n\n/* Creating Rule Engine instance */\nconst engine = new RuleEngine(fact)\nengine.addRule(rule)\n/* For multiple rules, use engine.addRules(rules) */\nawait engine.run()\n\nconsole.log(fact)\n/*\n{\n  application: 'ts-rule-engine',\n  cost: 0,\n  license: 'MIT',\n  reason: 'License originating at the Massachusetts Institute of Technology (MIT) in the late 1980s'\n}\n*/\n```\n\n### 4. Using the Rule Engine with Logger\n\nThe example below shows how to use the rule engine with a custom logger. The logger should implement the Logger interface. If a logger is not provided, logs are written using the global `console` object.\n\n```typescript\nimport { RuleEngine, Logger } from 'ts-rule-engine'\n\n/* Define fact */\nconst fact: Fact = {\n  application: 'ts-rule-engine',\n  cost: 0,\n  license: '',\n  description: ''\n}\n\n/* Define rule */\nconst rule: Rule\u003cFact\u003e = {\n  condition: (fact) =\u003e {\n    return fact.cost === 0\n  },\n  action: (fact, { logger }) =\u003e {\n    logger.info('All Good')\n    fact.license = 'MIT'\n    fact.description = 'License originating at the Massachusetts Institute of Technology (MIT) in the late 1980s'\n    fact.stop()\n  },\n};\n\n/* Custom Logger */\nclass CustomLogger implements Logger {\n  messages: string[] = []\n\n  info(message?: string, ...optionalParams: string[]): void {\n    this.messages.push(message)\n  }\n\n  warn(message?: string, ...optionalParams: string[]): void {\n    this.messages.push(message)\n  }\n\n  error(message?: string, ...optionalParams: string[]): void {\n    this.messages.push(message)\n  }\n}\n\n/* Creating Rule Engine instance */\nconst logger = new CustomLogger()\nconst engine = new RuleEngine(fact, {logger})\nengine.addRule(rule)\n/* For multiple rules, use engine.addRules(rules) */\nawait engine.run()\n\n// Check logger messages\nconsole.log(logger.messages)\n/*\n[\n  'Rule 1: Executing',\n  'Rule 1: Executed',\n  'Rule 1: Stopped'\n]\n*/\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filovepixelart%2Fts-rule-engine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Filovepixelart%2Fts-rule-engine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filovepixelart%2Fts-rule-engine/lists"}