UNPKG

the-rule-engine

Version:

⚙️ A small fluent DSL for conditional logic (validation, gating, etc)

178 lines (122 loc) 4.81 kB
# ⚙️ the-rule-engine [![NPM version](https://img.shields.io/npm/v/the-rule-engine.svg?style=flat)](https://www.npmjs.com/package/the-rule-engine) [![NPM downloads](https://img.shields.io/npm/dm/the-rule-engine.svg?style=flat)](https://npmjs.org/package/the-rule-engine) > "Declarative. Readable. Chainable. Unreasonably good looking." `the-rule-engine` is a lightweight, fluent API for building business logic, conditional flows, validations, or feature gating without writing spaghetti `if (a && (b || !c))` messes. It's your very own rule DSL ideal for settings where rules might get complicated, but your brain shouldn't have to. --- ## 🧩 Use Cases - Feature gating (A/B testing, roles, regions) - Form validation logic - Dynamic pricing tiers - Content access control - Rule-based UI rendering - Complex conditional branching --- ## 🦾 Why use **the-rule-engine**? - 🧠 **Fluent DSL**: Read like English. Write like code. - 🧼 **Zero boilerplate**: No ASTs, no config, no YAML dragons. - 🧪 **Fully testable**: Tiny API surface, easy mocks, clean logic. - 🧩 **Composable**: Use sub-engines or group logic like a pro. - 🔁 **Negations & nesting**: Yes, we support `.notGroup(...)`. --- ## 🚀 Installation ```bash npm install the-rule-engine ```` --- ## 🧑‍💻 Usage ```js import { createRuleEngine } from 'the-rule-engine'; const engine = createRuleEngine() .when(user => user.age >= 18) .and(user => user.country === 'US') .notGroup(group => group.when(user => user.banned).or(user => user.status === 'inactive') ) .then(() => '✅ Access Granted') .otherwise(() => '❌ Access Denied'); console.log(engine.evaluate({ age: 22, country: 'US', banned: false, status: 'active' })); // Access Granted ``` --- ## 🧠 API Overview | Method | Description | | ------------------------ | -------------------------------------------- | | `when(fn)` | Entry condition (`if`). Starts rule chain. | | `and(fn)` | Adds `AND` condition to current logic chain. | | `or(fn)` | Adds `OR` condition. | | `not(fn)` | Negates a condition. | | `group(cb)` | Nest AND conditions inside a callback. | | `orGroup(cb)` | Nest OR group of rules. | | `andGroup(cb)` | Explicit AND group. | | `notGroup(cb)` | Nest rules and negate the group result. | | `then(fn)` | What to do if the rules pass. | | `otherwise(fn)` | What to do if rules fail. | | `evaluate(ctx)` | Evaluate against input data. | | `evaluateLogicOnly(ctx)` | Returns only boolean result. | --- ## 💡 Real-World Example ```js const engine = createRuleEngine() .when(u => u.role === 'admin') .orGroup(g => g.when(u => u.plan === 'pro').and(u => u.paid === true) ) .not(u => u.suspended) .then(() => '🚀 Dashboard Access') .otherwise(() => '🔒 Please upgrade'); engine.evaluate({ role: 'user', plan: 'pro', paid: true, suspended: false }); // 🚀 Dashboard Access ``` --- ## 🧪 Testing ```bash npm run test ``` All examples from the README are covered in the test suite, including: * 🧱 Basic rules * 🔁 Nesting & grouping * 🔀 Multiple logic paths * Negations * 🧼 Clean evaluation with return value or boolean --- ## 🗿 Philosophy * Simplicity over frameworks. * Logic should be readable by humans, not just parsed by AI. * One chain to rule them all. --- ## 🐾 Related Inspiration * Redux-style DSLs (`.map().reduce()`) * Rule-based access control (RBAC) * Business logic extractors * Decision trees (without looking like one) --- ## 📦 CommonJS + ESM support ```js // ESM import { createRuleEngine } from 'the-rule-engine'; // CommonJS const { createRuleEngine } = require('the-rule-engine'); ``` --- ## 🧘 Final Thoughts Use it for fun, profit, or clarity. If your logic starts to look like: ```js if (a && (!b || (c && !d))) { ... } ``` It's time for `the-rule-engine`. --- Made with + 😤 to avoid `if-else` spaghetti. ## 🧑‍🚀 About the Developer Built by [cinfinit](https://github.com/cinfinit) who’s: Written too many if/else blocks to count Thought, “There has to be a cleaner way” Refused to let business logic live in nested ternaries Drinks water like .then() drinks callbacks They don’t claim to be a 10x engineer just someone who believes logic should be elegant, readable, and maybe even fun. Feel free to open issues, contribute, or just send memes about ugly conditionals.