{"id":45705671,"url":"https://github.com/adrael/business-engine","last_synced_at":"2026-02-25T00:30:58.831Z","repository":{"id":57191792,"uuid":"151120926","full_name":"adrael/business-engine","owner":"adrael","description":"Node.js module allowing you to easily implement your business rules against your domain.","archived":false,"fork":false,"pushed_at":"2018-10-02T14:11:29.000Z","size":48,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-09T02:49:00.343Z","etag":null,"topics":["business","customizable","free","nodejs","rule","standalone","test","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/adrael.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-10-01T16:32:32.000Z","updated_at":"2023-02-15T17:54:53.000Z","dependencies_parsed_at":"2022-09-01T00:52:12.057Z","dependency_job_id":null,"html_url":"https://github.com/adrael/business-engine","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/adrael/business-engine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrael%2Fbusiness-engine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrael%2Fbusiness-engine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrael%2Fbusiness-engine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrael%2Fbusiness-engine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adrael","download_url":"https://codeload.github.com/adrael/business-engine/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrael%2Fbusiness-engine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29806378,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-24T22:43:48.403Z","status":"ssl_error","status_checked_at":"2026-02-24T22:43:18.536Z","response_time":75,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["business","customizable","free","nodejs","rule","standalone","test","typescript"],"created_at":"2026-02-25T00:30:56.458Z","updated_at":"2026-02-25T00:30:58.821Z","avatar_url":"https://github.com/adrael.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Business Engine\n\n[![npm version][npm-image]][npm-url]\n[![Build Status][build-image]][build-url]\n[![GitHub issues][github-issues-image]][github-issues-url]\n[![Dependencies][dependencies-image]][dependencies-url]\n[![Dev Dependencies][dev-image]][dev-url]\n[![Peer Dependencies][peer-image]][peer-url]\n[![Coverage Status][coverage-image]][coverage-url]\n[![Known Vulnerabilities][known-image]][known-url]\n[![npm downloads][npm-downloads-image]][npm-downloads-url]\n[![GitHub license][github-license-image]][github-license-url]\n[![GitHub version][github-version-image]][github-version-url]\n[![code style: prettier][prettier-image]][prettier-url]\n\n\u003e Empower your software!\n\n*Business Engine* is a Node.js module allowing you to easily implement your business\nrules against your domain. Testable, standalone, opinionated and framework agnostic,\nyou now have the power to make your code base shiny again.\n\nIt can be used on its own, or altogether with some other tools, such as Mongoose.\n\n## Installation\n\n```sh\nnpm install business-engine --save\n```\n\nor\n\n```sh\nyarn add business-engine --exact --latest\n```\n\n## Usage\n\nBecause *Business Engine* is totally DOM free and UI Independent, you can basically do whatever you want with it.\nAn example would be to check whether a given entity is valid according to predefined business rules.\nWe could ask the engine to check said entity in a dedicated service, upon creation or update.\n\nLet's do it. We will show how to validate a simple user representation against a few business rules.\n\nHere is what our `User` domain looks like:\n\n```typescript\nexport class User {\n    public email: string;\n    public lastName: string;\n    public firstName: string;\n}\n```\n\nLet's review which business rules we would like to apply on this User class.\n\n1 - First name property is mandatory\n2 - Email property should match a given email pattern (anything that ends in `@gmail.com`), but only when we create it\n2 - Email property should be unique in our database\n\nThe first and second rules are quite easy to implement. Actually, there are even rules shipped with *Business Engine* that will do the work for us.\nWe will use the `StringPropertyRequiredRule` and `StringFormatRule` rules, respectively.\n\nThe latter is a bit more complicated. As *Business Engine* is database agnostic, this kind of rules cannot be pre-implemented for us.\nWe have to do it ourselves. For brevity, we won't show the database logic.\nLet's implement the `UniqueUserEmailRule` rule.\n\n```typescript\nimport { isNil } from \"lodash\";\nimport { User } from \"../domain/User\";\nimport { BusinessRule, BusinessRuleError } from \"business-engine\";\n\n// IMPORTANT NOTE\n// The entire business engine logic is built around optionals.\nimport Optional from \"typescript-optional\";\n\nexport class UniqueUserEmailRule\u003cUser\u003e extends BusinessRule\u003cUser\u003e {\n\n    // This method allows you to implement some kind of routing logic.\n    // If the rule applies to your entity, then return true.\n    // If not, return false.\n    // For example, this can be useful if you only want to target a specific mode\n    // no matter what. Or if the rule must only target entities containing specific properties,\n    // and so on.\n    public isApplicable(user: User): boolean {\n        return true;\n    }\n\n    protected checkForCreation(user: User): Optional\u003cBusinessRuleError\u003cUser\u003e\u003e {\n        // ... database logic to check if user's email address is already taken\n\n        if (/* email address already in use */) {\n            // When the entity being check is not compliant\n            // the engine expects an error to be returned.\n            return Optional.ofNonNull(this.buildError(user));\n        }\n\n        // When the entity being checked is valid, no error should be risen.\n        // Therefore an error-free optional.\n        return Optional.empty();\n    }\n\n    // In our case, the UPDATE logic is just the same as the CREATE logic\n    protected checkForUpdate(user: User): Optional\u003cBusinessRuleError\u003cUser\u003e\u003e {\n        return this.checkForCreation(user);\n    }\n\n    private buildError(user: User): BusinessRuleError\u003cUser\u003e {\n        return new BusinessRuleError\u003cUser\u003e(\"my-project.errors.email.already.used\", \"email must be unique\")\n            .set(\"EMAIL\", user.email);\n    }\n}\n\n```  \n\nLet's say we have a `UserService` which role is to handle all user interactions, between our resource layer and our repository layer.\nIt has the duty to make sure our `User` conforms to our rules before making it to the next layer.\n\n```typescript\nimport { List } from \"immutable\";\nimport { User } from \"../domain/User\";\nimport { UniqueUserEmailRule } from \"../rules/UniqueUserEmailRule\";\nimport { BusinessRuleService, IBusinessRule, BusinessRuleMode, StringPropertyRequiredRule, StringFormatRule } from \"business-engine\";\n\nexport class UserService extends BusinessRuleService {\n    // The rules will be applied one after the other, stopping at the first error.\n    protected readonly businessRules: List\u003cIBusinessRule\u003cUser\u003e\u003e = List(\n        // Creating a rule that can be applied in CREATE and UPDATE mode on the firstName property\n        new StringPropertyRequiredRule\u003cUser\u003e(BusinessRuleMode.ANY, \"firstName\"),\n        \n        // Again, CREATE mode only, on email property, with the pattern validator\n        new StringFormatRule\u003cUser\u003e(BusinessRuleMode.CREATE, \"email\", /.*@gmail\\.com$/i),\n        \n        // Finally our custom rule\n        new UniqueUserEmailRule(BusinessRuleMode.ANY)\n    );\n    \n    public createUser(user: User): User {\n        // Will throw an error if user does not comply with our rules\n        this.checkForCreation(user);\n        \n        // ... your logic here\n    }\n    \n    public updateUser(user: User): User {\n        // Will throw an error if user does not comply with our rules\n        this.checkForUpdate(user);\n        \n        // ... your logic here\n    }\n}\n```\n\n### Embedded rules\n\nBy design, *Business Engine* is shipped with a few handful of useful basic rules.\n\nHere is the list:\n\n- `StringFormatRule`\nChecks if a given entity's property comply to a given pattern\n\n- `StringPropertyRequiredRule`\nChecks if a given entity's string property if present (e.g. not null, not undefined and not empty) \n\n- `ObjectPropertyRequiredRule`\nChecks if a given entity's property if present (e.g. not null and not undefined) \n\n\n## Contributing\n\nPlease read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct,\nand the process for submitting pull requests to us.\n\n### Setup\n\nEverything should be available without you installing anything globally.\nJust run this command and you are good to go:\n\n```sh\nyarn\n```\n\n### Running the tests\n\n*Business Engine* uses Mocha and Chai under the hood. Shipped with 100% test coverage.\nIf you intend to improve the code, or add business rules, your PR is expected to keep the 100% test coverage ratio.\n\nTo run the tests, just do:\n\n```sh\nnpm test\n```\n\nor\n\n```sh\nyarn test\n```\n\n## Versioning\n\nWe use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/Adrael/business-engine/tags). \n\n## Authors\n\n* **Raphaël MARQUES** - *Initial work* - [Adrael](https://github.com/Adrael)\n\nSee also the list of [contributors](https://github.com/Adrael/business-engine/contributors) who participated in this project.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.\n\n[npm-image]: https://badge.fury.io/js/business-engine.svg\n[npm-url]: https://badge.fury.io/js/business-engine\n[build-image]: https://travis-ci.org/Adrael/business-engine.svg?branch=master\n[build-url]: https://travis-ci.org/Adrael/business-engine\n[github-issues-image]: https://img.shields.io/github/issues/Adrael/business-engine.svg\n[github-issues-url]: https://github.com/Adrael/business-engine/issues\n[dependencies-image]: https://david-dm.org/Adrael/business-engine.svg\n[dependencies-url]: https://david-dm.org/Adrael/business-engine#info=dependencies\n[dev-image]: https://david-dm.org/Adrael/business-engine/dev-status.svg\n[dev-url]: https://david-dm.org/Adrael/business-engine#info=devDependencies\n[peer-image]: https://david-dm.org/Adrael/business-engine/peer-status.svg\n[peer-url]: https://david-dm.org/Adrael/business-engine#info=peerDependenciess\n[coverage-image]: https://coveralls.io/repos/github/Adrael/business-engine/badge.svg?branch=master\n[coverage-url]: https://coveralls.io/github/Adrael/business-engine?branch=master\n[known-image]: https://snyk.io/test/github/Adrael/business-engine/badge.svg\n[known-url]: https://snyk.io/test/github/Adrael/business-engine\n[npm-downloads-image]: https://img.shields.io/npm/dm/business-engine.svg\n[npm-downloads-url]: https://npmjs.org/business-engine\n[github-license-image]: https://img.shields.io/github/license/Adrael/business-engine.svg\n[github-license-url]: https://github.com/Adrael/business-engine/blob/master/LICENSE\n[github-version-url]: https://badge.fury.io/gh/Adrael%2Fbusiness-engine\n[github-version-image]: https://badge.fury.io/gh/Adrael%2Fbusiness-engine.svg\n[prettier-image]: https://img.shields.io/badge/code_style-prettier-ff69b4.svg\n[prettier-url]: https://github.com/prettier/prettier\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadrael%2Fbusiness-engine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadrael%2Fbusiness-engine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadrael%2Fbusiness-engine/lists"}