funrules
v1.0.0
Published
A flexible rule engine for JavaScript that works in both Node.js and browser environments
Maintainers
Readme
FunRules
A flexible and powerful rule engine for JavaScript that works seamlessly in both Node.js and browser environments.
Features
- 🌐 Universal Module Definition (UMD) - works in Node.js and browsers
- ⚡ Lightweight and dependency-free
- 🔄 Support for rule chaining and complex conditions
- 🎯 Priority-based rule execution
- 🌳 Dependency management with cycle detection
- 🚦 Smart error handling
- 📊 Visual rule tree representation
Installation
Node.js
npm install funrulesBrowser
<script src="dist/funrules.js"></script>Usage
Basic Example
// Create a new instance
const rules = new FunRules();
// Add some simple rules
rules.addRule('isAdult', (data) => data.age >= 18);
rules.addRule('hasValidEmail', (data) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email));
// Add a composite rule using the rule builder
rules.addRule('canRegister', (data) => true, { needsFirst: ['isAdult', 'hasValidEmail'] });
// Check the rules
const data = {
age: 20,
email: '[email protected]'
};
const results = rules.checkAll(data);
console.log(results);Advanced Features
Rule Chaining
const rules = new FunRules();
rules.addRule('A', data => data.value > 10);
rules.addRule('B', data => data.value < 20);
// Create a composite rule using AND
const compositeRule = rules.rule('A').and('B');
rules.addSmartRule('C', compositeRule);Priority-based Execution
rules.addRule('highPriority', checkFn, { priority: 2 });
rules.addRule('lowPriority', checkFn, { priority: 1 });Dependency Management
rules.addRule('dependent', checkFn, {
needsFirst: ['prerequisite1', 'prerequisite2'],
skipIfFailed: ['criticalRule']
});Visual Rule Tree
rules.checkAll(data);
rules.printRuleTree();🍝 Say Goodbye to Spaghetti Code!
Before FunRules: The Nightmare 😱
if (user.age >= 18) {
if (user.hasValidEmail) {
if (user.country === 'US') {
if (user.hasAcceptedTerms) {
if (user.creditScore > 700) {
if (user.income > 50000) {
// Finally! But what were we checking again? 🤔
approveApplication();
} else {
rejectIncome();
}
} else {
rejectCredit();
}
} else {
rejectTerms();
}
} else {
rejectCountry();
}
} else {
rejectEmail();
}
} else {
rejectAge();
}The Spaghetti Monster:
if ──┐
└── if ──┐
└── if ──┐
└── if ──┐
└── if ──┐
└── if ──┐
└── 🍝 Yikes!After FunRules: Clean & Organized! 🎉
const rules = new FunRules();
// Simple, focused rules
rules.addRule('isAdult', user => user.age >= 18);
rules.addRule('hasValidEmail', user => /\S+@\S+\.\S+/.test(user.email));
rules.addRule('isUSResident', user => user.country === 'US');
rules.addRule('hasAcceptedTerms', user => user.hasAcceptedTerms);
rules.addRule('hasGoodCredit', user => user.creditScore > 700);
rules.addRule('hasSufficientIncome', user => user.income > 50000);
// Combine them elegantly
rules.addRule('isEligible', user => true, {
needsFirst: [
'isAdult',
'hasValidEmail',
'isUSResident',
'hasAcceptedTerms',
'hasGoodCredit',
'hasSufficientIncome'
]
});
// One clean check!
const result = rules.checkAll(user);The Clean Architecture:
🌳 Rule Tree
├── ✅ isAdult - Priority: 1
├── ✅ hasValidEmail - Priority: 1
├── ✅ isUSResident - Priority: 1
├── ✅ hasAcceptedTerms - Priority: 1
├── ✅ hasGoodCredit - Priority: 1
├── ✅ hasSufficientIncome - Priority: 1
└── ✅ isEligible - Priority: 2
└── (AND Group)
├── needsFirst - isAdult
├── needsFirst - hasValidEmail
├── needsFirst - isUSResident
├── needsFirst - hasAcceptedTerms
├── needsFirst - hasGoodCredit
└── needsFirst - hasSufficientIncomeBenefits 🌟
- 📋 Readable: Each rule is clearly named and has a single responsibility
- 🔍 Debuggable: Visual tree shows exactly which rules passed or failed
- 🔄 Reusable: Rules can be combined in different ways
- 🎯 Maintainable: Add or modify rules without touching others
- 🧪 Testable: Each rule can be tested in isolation
- 📊 Visualizable: See your business logic as a beautiful tree!
API Reference
Constructor
new FunRules(options)options.throwErrors: Boolean to control error handling
Methods
addRule(name, checkFunction, options)addSmartRule(name, rule, options)rule(name)- Returns a rule buildercheckRule(name, data)checkAll(data)printRuleTree()
License
MIT
