1.0.0 โ€ข Published 6 months ago

funrules v1.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
6 months ago

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 funrules

Browser

<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: 'test@example.com'
};

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 - hasSufficientIncome

Benefits ๐ŸŒŸ

  1. ๐Ÿ“‹ Readable: Each rule is clearly named and has a single responsibility
  2. ๐Ÿ” Debuggable: Visual tree shows exactly which rules passed or failed
  3. ๐Ÿ”„ Reusable: Rules can be combined in different ways
  4. ๐ŸŽฏ Maintainable: Add or modify rules without touching others
  5. ๐Ÿงช Testable: Each rule can be tested in isolation
  6. ๐Ÿ“Š 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 builder
  • checkRule(name, data)
  • checkAll(data)
  • printRuleTree()

License

MIT