Skip to main content

Overview

Logical operators let you combine multiple conditions together. Think of them like building blocks for complex rules.

and

All conditions must be true

or

At least one condition must be true

not

Reverses a condition

Architecture

Logical operators are implemented in the LogicalOperators class: Source Files:
  • Logical operators: src/operators/logical.js
  • Base operator: src/operators/base/BaseOperator.js
  • Unit tests: tests/unit/operators/logical.test.js

Key Features

  • Short-circuit evaluation - Stops checking as soon as result is known
  • Unlimited nesting - Combine operators inside each other
  • Works with any operator - Combine comparison, string, array operators, etc.
  • Clear error messages - Helpful feedback when something goes wrong

and - All Must Be True

All conditions must pass for the rule to pass. Like saying “I need this AND that AND those.”

Syntax

{ and: [condition1, condition2, ...] }

Parameters

conditions
array
required
Array of rule conditions (minimum 1 condition)

Returns

boolean - true only if all conditions are true

How It Works

✓ true  AND ✓ true  = ✓ true
✓ true  AND ✗ false = ✗ false
✗ false AND ✓ true  = ✗ false
✗ false AND ✗ false = ✗ false

Examples

  • Basic AND
  • Access Control
  • Nested AND
  • With Rule Helpers
import { createRuleEngine } from 'rule-engine-js';

const engine = createRuleEngine();
const user = {
  age: 28,
  role: 'admin',
  active: true
};

// All three conditions must be true
const rule = {
  and: [
    { gte: ['age', 18] },        // ✓ 28 >= 18
    { eq: ['role', 'admin'] },   // ✓ role is admin
    { eq: ['active', true] }     // ✓ active is true
  ]
};

engine.evaluateExpr(rule, user);
// Result: { success: true, value: true }

// If ANY condition fails, AND fails
const failRule = {
  and: [
    { gte: ['age', 18] },        // ✓ true
    { eq: ['role', 'guest'] }    // ✗ false (role is 'admin', not 'guest')
  ]
};

engine.evaluateExpr(failRule, user);
// Result: { success: true, value: false }

Common Use Cases

// User needs specific role AND active status
const hasPermission = {
  and: [
    { eq: ['role', 'admin'] },
    { eq: ['status', 'active'] },
    { neq: ['banned', true] }
  ]
};
// All fields must be valid
const validForm = {
  and: [
    { isNotNull: ['username'] },
    { regex: ['email', '^[^@]+@[^@]+$'] },
    { gte: ['age', 18] },
    { eq: ['terms', true] }
  ]
};
// Price must be within range
const validPrice = {
  and: [
    { gte: ['price', 10] },    // At least $10
    { lte: ['price', 100] }    // At most $100
  ]
};
Short-circuit: AND stops checking as soon as it finds a false condition, making it faster.

or - At Least One Must Be True

At least one condition must pass. Like saying “I need this OR that OR those.”

Syntax

{ or: [condition1, condition2, ...] }

Parameters

conditions
array
required
Array of rule conditions (minimum 1 condition)

Returns

boolean - true if any condition is true

How It Works

✓ true  OR ✓ true  = ✓ true
✓ true  OR ✗ false = ✓ true
✗ false OR ✓ true  = ✓ true
✗ false OR ✗ false = ✗ false

Examples

  • Basic OR
  • Multiple Payment Methods
  • Nested OR
  • With Rule Helpers
const user = {
  role: 'editor',
  isOwner: false,
  isModerator: false
};

// User needs at least ONE of these roles
const canEdit = {
  or: [
    { eq: ['role', 'admin'] },      // ✗ false
    { eq: ['role', 'editor'] },     // ✓ true (this one passes!)
    { eq: ['isOwner', true] },      // ✗ false
    { eq: ['isModerator', true] }   // ✗ false
  ]
};

engine.evaluateExpr(canEdit, user);
// Result: { success: true, value: true }

// All conditions must fail for OR to fail
const noAccess = {
  or: [
    { eq: ['role', 'admin'] },      // ✗ false
    { eq: ['isOwner', true] }       // ✗ false
  ]
};

engine.evaluateExpr(noAccess, user);
// Result: { success: true, value: false }

Common Use Cases

// Grant access to multiple roles
const canAccess = {
  or: [
    { eq: ['role', 'admin'] },
    { eq: ['role', 'moderator'] },
    { eq: ['role', 'editor'] }
  ]
};
// Discount for students OR seniors OR members
const getsDiscount = {
  or: [
    { eq: ['isStudent', true] },
    { gte: ['age', 65] },
    { eq: ['membershipLevel', 'gold'] }
  ]
};
// Match any category
const matchesSearch = {
  or: [
    { contains: ['category', 'electronics'] },
    { contains: ['category', 'computers'] },
    { contains: ['category', 'phones'] }
  ]
};
Short-circuit: OR stops checking as soon as it finds a true condition, making it faster.

not - Reverse a Condition

Flips a condition - true becomes false, false becomes true. Like saying “NOT this.”

Syntax

{
  not: [condition];
}

Parameters

condition
object
required
Single rule condition (exactly 1, no more, no less)

Returns

boolean - true if condition is false, false if condition is true

How It Works

NOT ✓ true  = ✗ false
NOT ✗ false = ✓ true

Examples

  • Basic NOT
  • Exclude Conditions
  • Combined with AND/OR
  • With Rule Helpers
const user = {
  name: 'John',
  banned: false,
  deleted: false
};

// User is NOT banned
const notBanned = {
  not: [
    { eq: ['banned', true] }  // false, so NOT false = true
  ]
};

engine.evaluateExpr(notBanned, user);
// Result: { success: true, value: true }

// User is NOT named Jane
const notJane = {
  not: [
    { eq: ['name', 'Jane'] }  // false, so NOT false = true
  ]
};

engine.evaluateExpr(notJane, user);
// Result: { success: true, value: true }

// User is NOT named John (this fails!)
const notJohn = {
  not: [
    { eq: ['name', 'John'] }  // true, so NOT true = false
  ]
};

engine.evaluateExpr(notJohn, user);
// Result: { success: true, value: false }

Common Use Cases

// User is NOT banned or deleted
const activeUser = {
  and: [
    { not: [{ eq: ['banned', true] }] },
    { not: [{ eq: ['deleted', true] }] }
  ]
};
// NOT a minor (under 18)
const isAdult = {
  not: [
    { lt: ['age', 18] }
  ]
};
// Show all products EXCEPT archived
const visibleProducts = {
  not: [
    { eq: ['status', 'archived'] }
  ]
};
NOT takes exactly one condition. Use { neq: [...] } for simple “not equal” checks.

Combining Operators

Mix AND, OR, and NOT to create complex logic:

Complex Examples

  • Premium Access
  • Shipping Eligibility
  • Content Moderation
const user = {
  subscription: 'basic',
  vipMember: false,
  trialActive: true,
  banned: false
};

// Premium access rules:
// (Premium subscriber OR VIP OR active trial) AND NOT banned
const hasPremiumAccess = {
  and: [
    {
      or: [
        { eq: ['subscription', 'premium'] },
        { eq: ['vipMember', true] },
        { eq: ['trialActive', true] }
      ]
    },
    {
      not: [
        { eq: ['banned', true] }
      ]
    }
  ]
};

engine.evaluateExpr(hasPremiumAccess, user);
// Result: { success: true, value: true }
// ✓ true because trial is active and not banned

Error Handling

Common Errors

// AND/OR need at least one condition
const result = engine.evaluateExpr({ and: [] }, {});

// Returns:
// {
//   success: false,
//   error: "AND operator requires at least one argument"
// }
// NOT needs exactly one condition
const result = engine.evaluateExpr(
  { not: [] },  // Missing condition
  {}
);

// Returns:
// {
//   success: false,
//   error: "NOT operator requires 1 arguments, got 0"
// }

// Also fails with multiple conditions
const result2 = engine.evaluateExpr(
  { not: [{ eq: ['a', 1] }, { eq: ['b', 2] }] },
  {}
);
// Error: NOT requires exactly 1 argument
// Nested condition has an error
const result = engine.evaluateExpr(
  {
    and: [
      { eq: ['valid', true] },
      { invalidOp: ['field'] }  // Unknown operator
    ]
  },
  { valid: true }
);

// Returns:
// {
//   success: false,
//   error: "Unknown operator: invalidOp"
// }

Tips for Debugging

// Break complex rules into smaller pieces
const isAdult = { gte: ['age', 18] };
const isActive = { eq: ['status', 'active'] };
const isPremium = { eq: ['tier', 'premium'] };

// Test each piece separately
console.log(engine.evaluateExpr(isAdult, user));
console.log(engine.evaluateExpr(isActive, user));
console.log(engine.evaluateExpr(isPremium, user));

// Then combine
const rule = {
  and: [isAdult, isActive, isPremium],
};
console.log(engine.evaluateExpr(rule, user));

Quick Reference

Operator Comparison

OperatorNeedsReturns True WhenExample
andAll conditions trueAll passUser is adult AND verified
orAny condition trueAt least one passesAdmin OR moderator
notCondition to reverseCondition is falseNOT banned

Common Patterns

// Value between min and max
{
  and: [
    { gte: ['price', 10] },
    { lte: ['price', 100] }
  ]
}

API Reference

For complete API documentation: