Overview
Special operators provide range checking and null validation capabilities:
between
Check if value is within range
isNull
Check if value is null/undefined
isNotNull
Check if value exists
Architecture
Source: src/operators/special.js | Tests: tests/unit/operators/special.test.js
between - Range Check
Check if a value is within a range (inclusive).
Syntax
{ between: [value, [min, max]] }
{ between: [value, range] } // Dynamic range
Parameters
Value to check - field path or literal
Range as [min, max] array - literal or field path
Returns
boolean - true if min ≤ value ≤ max, false otherwise
Examples
Basic Range
Dynamic Range
Common Use Cases
const data = { age: 25, score: 85, price: 49.99 };
// Age between 18 and 65
engine.evaluateExpr({ between: ['age', [18, 65]] }, data);
// Result: { success: true } - 18 ≤ 25 ≤ 65
// Score between 0 and 100
engine.evaluateExpr({ between: ['score', [0, 100]] }, data);
// Result: { success: true } - 0 ≤ 85 ≤ 100
// Price in budget range
engine.evaluateExpr({ between: ['price', [20, 50]] }, data);
// Result: { success: true } - 20 ≤ 49.99 ≤ 50
const data = {
temperature: 25,
config: {
minTemp: 18,
maxTemp: 30,
range: [18, 30]
}
};
// Range from field
engine.evaluateExpr({ between: ['temperature', 'config.range'] }, data);
// Result: { success: true }
// Age verification
const ageRule = { between: ['age', [18, 120]] };
// Price range filter
const priceFilter = { between: ['price', [10, 100]] };
// Score validation
const validScore = { between: ['score', [0, 100]] };
// Temperature monitoring
const tempOK = { between: ['temp', [15, 30]] };
// Discount range
const validDiscount = { between: ['discount', [0, 50]] };
Notes
Inclusive: Both min and max are included. between: [10, 20] matches 10, 15, and 20.
Alternative: You can use { and: [{ gte: [value, min] }, { lte: [value, max] }] } for the same effect.
isNull - Null Check
Check if a value is null or undefined.
Syntax
{ isNull: ['fieldPath'] }
Parameters
Returns
boolean - true if value is null, undefined, or field doesn’t exist
Examples
Basic Null Check
Optional Fields
Validation
const data = {
name: 'John',
age: null,
email: undefined,
// status field doesn't exist
};
// Check null value
engine.evaluateExpr({ isNull: ['age'] }, data);
// Result: { success: true }
// Check undefined value
engine.evaluateExpr({ isNull: ['email'] }, data);
// Result: { success: true }
// Check missing field
engine.evaluateExpr({ isNull: ['status'] }, data);
// Result: { success: true }
// Check existing value
engine.evaluateExpr({ isNull: ['name'] }, data);
// Result: { success: false }
const user = {
name: 'John',
middleName: null,
// lastName is undefined
};
// Check optional fields
const hasMiddleName = { not: [{ isNull: ['middleName'] }] };
const hasLastName = { not: [{ isNull: ['lastName'] }] };
engine.evaluateExpr(hasMiddleName, user);
// Result: { success: false } - middleName is null
engine.evaluateExpr(hasLastName, user);
// Result: { success: false } - lastName is undefined
const form = {
firstName: 'John',
lastName: 'Doe',
middleName: null
};
// Required fields must not be null
const validForm = {
and: [
{ not: [{ isNull: ['firstName'] }] },
{ not: [{ isNull: ['lastName'] }] }
]
};
engine.evaluateExpr(validForm, form);
// Result: { success: true }
isNotNull - Not Null Check
Check if a value exists (not null or undefined).
Syntax
{ isNotNull: ['fieldPath'] }
Parameters
Returns
boolean - true if value exists and is not null or undefined
Examples
Basic Existence Check
Required Fields
Conditional Logic
const data = {
name: 'John',
age: 25,
email: null,
// phone is undefined
};
// Check value exists
engine.evaluateExpr({ isNotNull: ['name'] }, data);
// Result: { success: true }
// Check age exists
engine.evaluateExpr({ isNotNull: ['age'] }, data);
// Result: { success: true }
// Check null value
engine.evaluateExpr({ isNotNull: ['email'] }, data);
// Result: { success: false }
// Check missing field
engine.evaluateExpr({ isNotNull: ['phone'] }, data);
// Result: { success: false }
const registration = {
username: 'john_doe',
email: 'john@example.com',
password: 'secret123',
phone: null
};
// All required fields must exist
const validRegistration = {
and: [
{ isNotNull: ['username'] },
{ isNotNull: ['email'] },
{ isNotNull: ['password'] }
]
};
engine.evaluateExpr(validRegistration, registration);
// Result: { success: true }
const order = {
total: 150,
discount: 10,
couponCode: 'SAVE10'
// shippingAddress may be null
};
// Apply discount only if coupon exists
const hasDiscount = {
and: [
{ isNotNull: ['couponCode'] },
{ gt: ['discount', 0] }
]
};
engine.evaluateExpr(hasDiscount, order);
// Result: { success: true }
Notes
Inverse: isNotNull is equivalent to { not: [{ isNull: [field] }] }
Common Patterns
const user = { age: 25 };
const validAge = {
and: [
{ isNotNull: ['age'] },
{ between: ['age', [18, 120]] }
]
};
const product = { price: 49.99 };
const affordableProduct = {
and: [
{ isNotNull: ['price'] },
{ between: ['price', [10, 100]] }
]
};
const user = { name: 'John', middleName: null };
const fullName = {
or: [
{ isNotNull: ['middleName'] },
{ isNotNull: ['name'] }
]
};
const exam = { score: 85 };
const validScore = {
and: [
{ isNotNull: ['score'] },
{ between: ['score', [0, 100]] }
]
};
Error Handling
const data = { name: 'John' };
const result = engine.evaluateExpr({ between: ['name', [1, 10]] }, data);
// Error: "BETWEEN operator requires numeric operands"
// BETWEEN requires 2 arguments
const result = engine.evaluateExpr({ between: ['age'] }, data);
// Error: "BETWEEN operator requires 2 arguments"
// IS_NULL requires 1 argument
const result2 = engine.evaluateExpr({ isNull: [] }, data);
// Error: "IS_NULL operator requires 1 arguments"
Quick Reference
| Operator | Purpose | Example | Result |
between | Range check (inclusive) | { between: [25, [18, 65]] } | true |
isNull | Check if null/undefined | { isNull: ['email'] } | true if null |
isNotNull | Check if exists | { isNotNull: ['name'] } | true if exists |
API Reference