Skip to content

xe4me/json-rules

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

npm version

Statements Functions Lines
Statements Functions Lines

JsonRules Engine

A rule engine for JavaScript & TypeScript

Define business logic with JSON rules

TypeScript npm


Overview

JsonRules is a rule engine that allows you to define business logic as JSON and evaluate it against data. It provides a simple way to externalize decision-making logic from your application code.

Use Cases

  • E-commerce: Pricing rules, discount eligibility, shipping calculations
  • User Management: Access control, feature flags, user segmentation
  • Content: Filtering, moderation, recommendations
  • Workflows: Approval processes, notifications
  • Configuration: A/B testing, feature rollouts

Features

  • Type-safe with full TypeScript support
  • 40+ built-in operators for common operations
  • Support for complex nested conditions
  • Template variables for dynamic rules
  • Validation for rule structure and syntax
  • Works in Node.js and browsers

Installation

npm install @ivandt/json-rules

Dependencies

This library has one dependency:

  • validator - Used for advanced validation operators (email, URL, phone numbers, etc.)

Quick Start

import { JsonRules, Rule } from "@ivandt/json-rules";

// Define a rule
const rule: Rule = {
  conditions: {
    all: [
      { field: "age", operator: "is greater than or equal", value: 18 },
      { field: "country", operator: "is equal", value: "US" }
    ]
  }
};

// Evaluate against data
const user = { age: 25, country: "US" };
const result = JsonRules.evaluate(rule, user);
console.log(result); // true

Operators

JsonRules provides operators for common data operations:

Equality & Comparison

Operator Description Accepts Example
is equal Equal to string | number | boolean | Date | null { field: "status", operator: "is equal", value: "active" }
is not equal Not equal to string | number | boolean | Date | null { field: "status", operator: "is not equal", value: "banned" }
is greater than Greater than comparison string | number | Date { field: "age", operator: "is greater than", value: 18 }
is less than Less than comparison string | number | Date { field: "price", operator: "is less than", value: 100 }
is greater than or equal Greater than or equal string | number | Date { field: "score", operator: "is greater than or equal", value: 80 }
is less than or equal Less than or equal string | number | Date { field: "items", operator: "is less than or equal", value: 10 }

Range & Between

Operator Description Accepts Example
is between numbers Number within range (inclusive) [number, number] { field: "age", operator: "is between numbers", value: [18, 65] }
is not between numbers Number outside range [number, number] { field: "temperature", operator: "is not between numbers", value: [32, 100] }
is between dates Date within range (inclusive) [Date, Date] { field: "eventDate", operator: "is between dates", value: [startDate, endDate] }
is not between dates Date outside range [Date, Date] { field: "blackoutDate", operator: "is not between dates", value: [holiday1, holiday2] }

Collection & Array

Operator Description Accepts Example
in Value exists in array (string | number | boolean | object | null)[] { field: "country", operator: "in", value: ["US", "CA", "UK"] }
not in Value not in array (string | number | boolean | object | null)[] { field: "status", operator: "not in", value: ["banned", "suspended"] }
array contains Array field contains value string | number | boolean | object | null { field: "skills", operator: "array contains", value: "javascript" }
array no contains Array field doesn't contain value string | number | boolean | object | null { field: "permissions", operator: "array no contains", value: "admin" }

String Operations

Operator Description Accepts Example
contains String contains substring string { field: "email", operator: "contains", value: "@company.com" }
not contains String doesn't contain substring string { field: "message", operator: "not contains", value: "spam" }
contains any String contains any substring string[] { field: "title", operator: "contains any", value: ["urgent", "critical"] }
not contains any String contains none of substrings string[] { field: "content", operator: "not contains any", value: ["spam", "scam"] }
starts with String starts with prefix string { field: "productCode", operator: "starts with", value: "PRD-" }
ends with String ends with suffix string { field: "filename", operator: "ends with", value: ".pdf" }

Pattern Matching

Operator Description Accepts Example
matches Matches regex pattern { regex: string, flags?: string } { field: "email", operator: "matches", value: { regex: "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$" } }
not matches Doesn't match regex pattern { regex: string, flags?: string } { field: "username", operator: "not matches", value: { regex: "^(admin|root)$", flags: "i" } }

Date Operations

Operator Description Accepts Example
is before Date is before specified date string | number | Date { field: "expiry", operator: "is before", value: new Date('2024-12-31') }
is after Date is after specified date string | number | Date { field: "startDate", operator: "is after", value: new Date('2024-01-01') }
is on or before Date is on or before specified date string | number | Date { field: "deadline", operator: "is on or before", value: new Date() }
is on or after Date is on or after specified date string | number | Date { field: "validFrom", operator: "is on or after", value: new Date() }

Math & Number Validation

Operator Description Accepts Example
is even Number is even none { field: "quantity", operator: "is even" }
is odd Number is odd none { field: "productId", operator: "is odd" }
is positive Number is positive (> 0) none { field: "balance", operator: "is positive" }
is negative Number is negative (< 0) none { field: "adjustment", operator: "is negative" }
is empty Value is null, undefined, or empty string/array none { field: "optionalField", operator: "is empty" }
is not empty Value is not empty none { field: "requiredField", operator: "is not empty" }

Data Validation

Operator Description Accepts Example
is valid email Valid email address EmailValidationConfig (optional) { field: "email", operator: "is valid email" }
is valid phone Valid phone number PhoneValidationConfig { field: "phone", operator: "is valid phone", value: { locale: "us" } }
is URL Valid URL URLValidationConfig { field: "website", operator: "is URL", value: { requireTld: false } }
is UUID Valid UUID UUIDValidationConfig { field: "id", operator: "is UUID", value: { version: 4 } }
is EAN Valid EAN barcode none { field: "barcode", operator: "is EAN" }
is IMEI Valid IMEI number IMEIValidationConfig { field: "deviceId", operator: "is IMEI", value: { allowHyphens: true } }
is unit Valid unit of measurement UnitType { field: "distance", operator: "is unit", value: "length" }
is country Valid country identifier CountryValidationConfig { field: "country", operator: "is country", value: { format: "iso2" } }
is domain Valid domain name DomainValidationConfig { field: "domain", operator: "is domain", value: { requireTld: true } }

Rule Structure

Basic Rule

interface Rule {
  conditions: Condition | Condition[];
  default?: any;
}

Conditions

Rules support three logical operators:

Type Logic Description
all AND All constraints must be true
any OR At least one constraint must be true
none NOT No constraints should be true

Constraints

{
  field: string,           // Property path (supports dot notation)
  operator: string,        // Comparison operator
  value: any              // Expected value or template reference
}

Examples

Basic Example

const rule: Rule = {
  conditions: {
    all: [
      { field: "age", operator: "is greater than or equal", value: 21 },
      { field: "country", operator: "in", value: ["US", "CA"] }
    ]
  }
};

const user = { age: 25, country: "US" };
const result = JsonRules.evaluate(rule, user); // true

Complex Conditions

const complexRule: Rule = {
  conditions: {
    any: [
      {
        all: [
          { field: "membershipTier", operator: "is equal", value: "premium" },
          { field: "accountAge", operator: "is greater than", value: 365 }
        ]
      },
      {
        all: [
          { field: "totalSpent", operator: "is greater than", value: 1000 },
          { field: "lastPurchase", operator: "is after", value: new Date('2024-01-01') }
        ]
      }
    ]
  }
};

Validation Operators

const validationRule: Rule = {
  conditions: {
    all: [
      { field: "email", operator: "is valid email", value: null },
      { field: "phone", operator: "is valid phone", value: { locale: "us" } },
      { field: "website", operator: "is URL", value: { protocols: ["https"] } }
    ]
  }
};

Template Variables

const dynamicRule: Rule = {
  conditions: {
    all: [
      { field: "endDate", operator: "is after", value: "{startDate}" },
      { field: "price", operator: "is less than", value: "{maxBudget}" }
    ]
  }
};

API Reference

JsonRules.evaluate()

static evaluate<T>(
  rule: Rule, 
  criteria: object | object[], 
  trustRule?: boolean
): T | boolean

JsonRules.validate()

static validate(rule: Rule): ValidationResult

ValidationResult

interface ValidationResult {
  isValid: boolean;
  error?: ValidationError;
}

Phone Number Validation

To use phone validation, import the specific locale validators:

// Import specific locales
import "@ivandt/json-rules/validators/phone/us";
import "@ivandt/json-rules/validators/phone/gb";
import "@ivandt/json-rules/validators/phone/de";

const rule: Rule = {
  conditions: {
    all: [
      { field: "phone", operator: "is valid phone", value: { locale: "us" } }
    ]
  }
};

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/new-feature
  3. Make your changes with tests
  4. Run the test suite: npm test
  5. Submit a pull request

License

MIT License - see LICENSE file for details.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •