A tiny, safe boolean-expression language with dotted paths, functions, and rule books for TypeScript.
Boolia is a lightweight expression language that allows you to evaluate complex boolean expressions with support for:
- Dotted path notation for accessing nested object properties
- Custom functions for extending evaluation capabilities
- Rule books for organizing and managing collections of rules
- Tag-based evaluation for conditional logic
- Safe evaluation with proper error handling
npm install booliaimport { evaluate } from 'boolia';
// Simple boolean logic
evaluate('true and false or true'); // true
// Comparisons and membership
const ctx = { user: { age: 21, roles: ['admin', 'ops'] } };
evaluate("user.age >= 18 and 'admin' in user.roles", { context: ctx }); // true// Access nested object properties
const context = { house: { light: { on: false } } };
evaluate('house.light.on', { context }); // false
// Works with class instances and methods
class User {
name = 'João';
isActive() { return true; }
}
const ctx = { user: new User() };
evaluate('user.name and user.isActive', { context: ctx }); // trueconst tags = new Set(['admin', 'premium']);
evaluate('admin and premium', { tags }); // true
evaluate('admin and guest', { tags }); // falseRegister your own functions to extend evaluation capabilities:
import { evaluate, DEFAULT_FUNCTIONS } from 'boolia';
// Register a custom function
DEFAULT_FUNCTIONS.register('starts_with', (subject, prefix) =>
String(subject ?? '').startsWith(String(prefix ?? ''))
);
const ctx = { user: { name: 'João', email: '[email protected]' } };
const expr = "starts_with(user.name, 'Jo') and matches(user.email, '.*@acme.com')";
evaluate(expr, { context: ctx }); // trueOrganize complex logic using rule books:
import { RuleBook, RuleGroup } from 'boolia';
const rules = new RuleBook();
// Add individual rules
rules.add('is_adult', 'user.age >= 18');
rules.add('has_discount', 'user.discount');
rules.add('is_premium', 'user.tier == "premium"');
// Create rule groups
rules.register('eligible_for_offer',
new RuleGroup('all', ['is_adult', 'has_discount'])
);
rules.register('priority_customer',
new RuleGroup('any', ['is_premium', 'eligible_for_offer'])
);
// Evaluate rules
const ctx = { user: { age: 22, discount: true, tier: 'standard' } };
rules.evaluate('eligible_for_offer', { context: ctx }); // true
rules.evaluate('priority_customer', { context: ctx }); // trueRule groups allow you to combine multiple rules with different logic:
allmode: All rules must be true (AND logic)anymode: At least one rule must be true (OR logic)
// Nested rule groups
const rules = new RuleBook();
rules.add('is_adult', 'user.age >= 18');
rules.add('has_payment', 'user.payment_method');
rules.add('is_vip', 'user.vip');
const eligibility = new RuleGroup('all', ['is_adult', 'has_payment']);
rules.register('can_purchase', new RuleGroup('any', [eligibility, 'is_vip']));Rule books can be serialized to/from JSON for persistence:
import { rulebookToJson, rulebookFromJson } from 'boolia';
const rules = new RuleBook();
rules.add('example', 'user.active');
// Serialize to JSON
const json = rulebookToJson(rules);
// Deserialize from JSON
const restored = rulebookFromJson(json);Boolia provides specific error types for different scenarios:
import {
MissingVariableError,
RulebookError,
RulebookValidationError
} from 'boolia';
try {
evaluate('unknown_variable', { context: {} });
} catch (error) {
if (error instanceof MissingVariableError) {
console.log('Variable not found:', error.variable);
}
}evaluate(expression, options?)- Evaluate a boolean expressioncompileExpr(expression)- Compile an expression for reusecompileRule(name, expression)- Compile a named rule
RuleBook- Container for rules and rule groupsRuleGroup- Logical grouping of rules with AND/OR semanticsRule- Individual rule with name and expression
The EvaluateOptions interface supports:
context?: any- Variable context for evaluationtags?: Set<string>- Available tags for tag-based logicmissingPolicy?: MissingPolicy- How to handle missing variables
This project uses:
- TypeScript for type safety
- Vitest for testing
- ESLint for code quality
# Install dependencies
npm install
# Run tests
npm test
# Build the project
npm run buildMIT © João Freires