All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
- More forgiving type handling - Expressions now return sensible defaults for type mismatches instead of throwing errors
- String expressions (
$uppercase,$lowercase,$trim,$split,$replace,$substring) returnnullfor non-string input - Array expressions (
$filterBy,$groupBy,$pluck,$sort,$first,$last) return empty arrays/null for non-array input - Object expressions (
$keys,$values,$pairs,$fromPairs,$pick,$omit,$merge) return empty objects/arrays for non-object input - Predicate expressions (
$matchesRegex,$exists) returnfalsefor type mismatches - Updated README and documentation with data handling philosophy and examples
- String expressions (
- Tree-shaking enabled - Package now ships source files for ESM imports
- ESM imports (
import) now use source files directly, enabling optimal tree-shaking - CJS imports (
require) use pre-built bundle (no change in behavior) - All existing imports continue to work - no breaking changes
- Tree-shaking works with modern bundlers (Webpack 5+, Vite, Rollup, esbuild)
- ESM imports (
- Up to 87% bundle size reduction with selective imports:
- Math pack only: 31 KB (was 234 KB)
- Math + Array: 36 KB (was 234 KB)
- All packs (no temporal): 42 KB (was 234 KB)
- Full bundle with temporal: 133 KB (was 234 KB)
How it works:
// Import packs (recommended) - 31 KB for math only
import { mathPack, createExpressionEngine } from "json-expressions";
const engine = createExpressionEngine({ packs: [mathPack] });
// Or import individual expressions - even smaller (28 KB)
import {
$add,
$multiply,
$sum,
createExpressionEngine,
} from "json-expressions";
const engine = createExpressionEngine({ custom: { $add, $multiply, $sum } });No migration needed - All existing code continues to work. Modern bundlers automatically tree-shake unused code.
- Bracket notation support in
$getand$pluckexpressions- Array index access:
"items[0].name"accesses first item's name property - Consecutive brackets:
"matrix[0][1]"accesses nested arrays - Mixed notation:
"users[0].profile.age"combines brackets and dots - Wildcard in brackets:
"[$].name"or"items[$].id"iterates arrays - Nested wildcards:
"teams[$].members[$].name"flattens nested arrays
- Array index access:
- Wildcard validation - Wildcards (
$) are now explicitly controlled per expression$getand$plucksupport wildcards for array iteration$matchesAll,$matchesAny,$filterBy,$exists, and$sortreject wildcards with clear error messages- Helps prevent confusing behavior where wildcards produce unexpected results
- Expression validation methods on the expression engine
validateExpression(value)- Returns array of all validation errors (empty array if valid)ensureValidExpression(value)- Validates expression tree, throwing all errors joined by newline- Both methods perform deep recursive validation of nested expressions
- Returns all errors at once for better user experience (not just first error)
$literaloperands are correctly excluded from validation (treated as data)- Useful for validating user-provided expressions before evaluation
- Extended operand-over-inputData pattern to more expression types
- Array transformation expressions (
$reverse,$sort,$unique, etc.) now support operand form - Math transformation expressions (
$abs,$ceil,$floor,$sqrt) now support operand form - String transformation expressions (
$uppercase,$lowercase,$trim, etc.) now support operand form - These expressions now operate on either the resolved operand (if it matches the expected type) or input data
- Enables more composable patterns like
{ $abs: { $get: "value" } }without requiring$pipe
- Array transformation expressions (
0.13.0 - 2025-10-18
- Middleware support - Add middleware functions to wrap expression evaluation for logging, telemetry, error handling, and more
- Middleware can observe expression evaluation (operand, inputData, expressionName, path)
- Middleware can transform operand and inputData before evaluation
- Middleware can transform results, catch errors, or short-circuit evaluation
- Multiple middleware compose in order with proper before/after wrapping
$propexpression - Fast simple property access without path traversal features- 2.5x faster than
$getfor simple property access (obj[key] only) - No dot notation, wildcards, or array paths - just direct property lookup
- Included in base pack for opt-in performance optimization
- 2.5x faster than
- ~26x performance improvement for expression evaluation through optimistic error handling
- Fast path avoids closure creation overhead for path tracking
- Error path rebuilds with full path information on demand
- Simple operations now achieve 1.2-2.1M ops/sec (previously ~450K ops/sec)
0.12.1 - 2025-10-13
- Removed language around tree shaking
$debugis now included in the base pack for easier debugging during development- Temporal pack redesigned with more flexible, composable expressions
- Replaced individual arithmetic operations with unified
$addTime(supports years, months, weeks, days, hours, minutes, seconds, milliseconds) - Negative values in
$addTimeenable subtraction (e.g.,{ days: -3 }) - Replaced individual difference operations with unified
$diffTime(supports all time units) - Replaced individual boundary operations with
$startOfand$endOf(supports day, week, month, year) - Replaced individual component extractors with unified
$getTime(supports year, month, day, hour, minute, second, dayOfWeek, dayOfYear) - Simplified comparison operations to
$isAfterand$isBefore - Removed predicates like
$isWeekend,$isWeekday,$isSameDay(can be achieved with$getTimeand comparisons) - All temporal expressions preserve error types when throwing errors
- Replaced individual arithmetic operations with unified
0.12.0 - 2025-10-08
- Temporal Pack - Comprehensive date/time operations with 38 expressions
- Date arithmetic:
$addDays,$addMonths,$addYears,$addHours,$addMinutes,$addSeconds,$subDays,$subMonths,$subYears,$subHours,$subMinutes,$subSeconds - Date components:
$year,$month,$day,$hour,$minute,$second,$dayOfWeek,$dayOfYear,$weekOfYear - Date boundaries:
$startOfDay,$endOfDay,$startOfMonth,$endOfMonth,$startOfYear,$endOfYear,$startOfWeek,$endOfWeek - Date comparison:
$isBefore,$isAfter,$isSameDay,$isSameMonth,$isSameYear,$isBetween - Date predicates:
$isWeekend,$isWeekday,$isLeapYear - Date differences:
$diffDays,$diffHours,$diffMinutes,$diffSeconds,$diffMonths,$diffYears - Date parsing/formatting:
$formatDate,$parseDate,$isDateValid
- Date arithmetic:
- All temporal expressions use ISO 8601 string format for JSON compatibility
- All temporal expressions support both array form and input data form patterns
- Added
date-fnsdependency for date parsing and formatting operations
- Temporal expressions use UTC-based operations to ensure consistent behavior across timezones
$matchAnyis now in the base packexcludecan now specify the names of expressions meant to be excluded from the engine (so{ packs: [mathPack], exclude: ["$add"] }would work as expected)
0.10.3 - 2025-10-03
$getnow returnsnullinstead ofundefinedfor non-existent paths, aligning with JSON semanticsundefinedandnullare now treated as equal throughout the library to support JSON-first design
- Fixed
$getpath resolution edge cases
0.10.2 - 2025-10-03
- Removed
$prependand$appendexpressions in favor of$concatfor better API consistency
0.10.1 - 2025-10-01
- Operand-over-inputData pattern for aggregative expressions (
$count,$sum,$min,$max,$mean,$first,$last) - These expressions can now operate on either an operand expression result or input data
- Aggregative expressions now support more composable patterns without requiring
$pipe
0.9.0 - 2025-09-29
- Math operation edge case handling and improvements
- Comprehensive documentation in
docs/directory- Quick Start Guide
- Expression Reference
- Pack Reference
- Custom Expressions Guide
- Renamed "Pack" suffix added to all pack exports for consistency (
mathPack,arrayPack, etc.) - Improved null/undefined equality handling across all comparison operations
- Updated documentation to focus on "apply mode" as primary usage pattern
- Improved test coverage across all expression definitions
0.8.0 - 2025-09-27
- Array form for binary comparison operators (
$eq,$ne,$gt,$gte,$lt,$lte) - Array form for math operations (
$add,$subtract,$multiply,$divide,$modulo,$pow) - Support for comparing or computing values from two expressions
- Pack reorganization for better logical grouping
- Documentation synchronized with pack structure
0.7.0 - 2025-09-24
$identityexpression for identity function pattern$literalexpression for wrapping values that should not be evaluatedisWrappedLiteralcontext function for custom expressions
- Renamed
isLiteraltoisWrappedLiteralin expression context for clarity - Renamed
allpack toallExpressionsForTestingto clarify its purpose
- Non-deterministic expressions removed from core library
0.6.0 - 2025-09-23
- Updated core expression definitions with improvements to evaluation logic
- Reorganized expression files for better maintainability
- Combined
$caseand$switchinto unified$caseexpression supporting both literal and predicate matching
$switchexpression removed; use$caseinstead
0.5.0 - 2025-09-06
- Packs system for modular expression loading
createExpressionEngineconfiguration object supporting:packs: Array of expression pack objectscustom: Custom expression definitionsincludeBase: Option to exclude base expressions
- Moved to packs-based architecture for better tree-shaking and modularity
- Updated package structure to support selective imports
- Changed from flat export to pack-based export system
- Engine creation now requires explicit pack imports
0.4.0 - 2025-09-05
- Adjusted
$getsignature for better path handling - Improved
.gitignorefor better development workflow
$getnow properly handles default values for missing paths
0.3.0 - 2025-09-03
$propexpression for property access (later renamed to$get)- Default value support for
$getexpression
0.2.0 - 2025-09-02
- Updated dependencies to latest versions
- Improved README documentation
0.1.0 - 2025-09-02
- Initial release of JSON Expressions
- Core expression engine with
applymethod - Basic expression types:
- Access:
$get - Comparison:
$eq,$ne,$gt,$gte,$lt,$lte,$in,$nin - Logic:
$and,$or,$not - Math:
$add,$subtract,$multiply,$divide,$modulo,$abs,$ceil,$floor,$pow,$sqrt - Array:
$filter,$map,$find,$all,$any,$concat,$flatten,$unique,$sort,$reverse,$first,$last,$skip,$take,$pluck,$groupBy,$flatMap - Object:
$pick,$omit,$merge,$keys,$values,$pairs,$fromPairs,$select - String:
$uppercase,$lowercase,$trim,$split,$join,$replace,$substring - Conditional:
$if,$case - Flow:
$pipe,$default,$debug - Predicate:
$matchesAll,$filterBy,$exists,$isEmpty,$isPresent,$between,$matchesRegex,$coalesce - Aggregation:
$count,$sum,$min,$max,$mean
- Access:
- MIT License
- TypeScript definitions
- Comprehensive test suite
- Build tooling (Rollup for ESM/CJS)
- ESLint and Prettier configuration