npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@data-prism/expressions

v0.0.16

Published

> **⚠️ DEPRECATED**: This package has been merged into `@data-prism/core` for better integration and simpler dependency management. Please migrate to `@data-prism/core` which includes all expression functionality. This package will receive no further upda

Readme

Data Prism Expressions

⚠️ DEPRECATED: This package has been merged into @data-prism/core for better integration and simpler dependency management. Please migrate to @data-prism/core which includes all expression functionality. This package will receive no further updates.

A JavaScript expression engine for enhancing Data Prism queries with computed values and conditional logic. Data Prism Expressions provides a JSON-based syntax for creating dynamic where clauses and calculated select fields, extending the core querying capabilities with lightweight programmatic logic.

It is suitable for more general applications that call for simple logic that needs to be written as JSON. It is inspired by the Lisp concept of code being data.

Migration

Old:

import { defaultExpressionEngine } from "@data-prism/expressions";

New:

import { defaultExpressionEngine } from "@data-prism/core";

All expression functionality remains identical - only the import path has changed.

Overview

Data Prism Expressions is built around several key principles:

  • Query enhancement: Adds computed fields and conditional logic to Data Prism queries
  • Extensible: Built for users to extend with custom expressions and operations
  • Lightweight: Focuses on the most common expressions needed in data queries
  • JSON-native: Uses JSON objects that can be serialized and stored

Installation

# Deprecated - use @data-prism/core instead
npm install @data-prism/expressions

# Recommended
npm install @data-prism/core

Core Concepts

Expressions

Expressions are JSON objects that describe computations to be performed on data. Each expression has a single key that identifies the operation (prefixed with $) and a value that provides the parameters:

// Simple comparison
{ "$gt": 18 }  // arg > 18

// Logical operations
{ "$and": [
  { "$gt": 80 },
  { "$lt": 5 }
]}

// Conditional logic
{ "$if": {
  "if": { "$eq": "active" },
  "then": { "$get": "fullName" },
  "else": "Inactive User"
}}

Expression Engine

The expression engine holds the expressions definitions and allows for them to be used in a few ways:

apply

Applies the expression like a function to a value.

import { defaultExpressionEngine } from "@data-prism/expressions";

const expression = { $gt: 21 };
const data = 25;

const result = defaultExpressionEngine.apply(expression, value);
// Returns: true

evaluate

Takes an expression in its evaluable form and evaluates it, returning a value wholly determined by the expression itself. It is not applied to anything, but is fully self-contained.

// Evaluate expressions without input data (for static expressions)
const staticResult = defaultExpressionEngine.evaluate({ $sum: [1, 2, 3] });
// Returns: 6

normalizeWhereClause

Transforms an expression from Data Prism's user-focused form to an equivalent expression that's more suitable for consumption by stores as they execute the where clause of a query. It lives in this repository for extensibility purposes, as expressions can define their own normalizeWhere functions to handle complex behavior.

API Reference

Core Functions

createExpressionEngine(definitions)

Creates a custom expression engine with additional operation definitions.

Parameters:

  • definitions (object) - Custom operation definitions to add to the engine

Returns: ExpressionEngine with core + custom operations

import { createExpressionEngine } from "@data-prism/expressions";

const customEngine = createExpressionEngine({
	$customOp: {
		apply: (params, data) => {
			// Custom operation logic
			return params + data;
		},
	},
});

defaultExpressionEngine

Pre-configured expression engine with all built-in operations.

import { defaultExpressionEngine } from "@data-prism/expressions";

const result = defaultExpressionEngine.apply(expression, data);

ExpressionEngine Methods

apply(expression, data)

Evaluates an expression against input data.

Parameters:

  • expression (Expression) - The expression to evaluate
  • data (any) - The data context for evaluation

Returns: Result of the expression evaluation

const expression = { $sum: [10, 20] };
const data = [1, 2, 3, 4];

const result = engine.apply(expression, data);
// Returns: 10 (sum of [10, 20])

evaluate(expression)

Evaluates an expression without input data (for static expressions).

Parameters:

  • expression (Expression) - The expression to evaluate

Returns: Static result of the expression

const expression = { $sum: [10, 20] };
const result = engine.evaluate(expression);
// Returns: 30

isExpression(value)

Tests whether a value is a valid expression.

Parameters:

  • value (any) - The value to test

Returns: Boolean indicating if the value is an expression

const isExpr1 = engine.isExpression({ $get: "name" }); // true
const isExpr2 = engine.isExpression({ name: "Juan" }); // false

normalizeWhereClause(where)

Normalizes a user-friendly where clause into executable expressions for query processing.

Parameters:

  • where (object) - The where clause to normalize

Returns: Normalized expression suitable for query execution

const where = { name: "Juan", age: { $gt: 18 } };
const normalized = engine.normalizeWhereClause(where);
// Returns: { $and: [
//   { $pipe: [{ $get: "name" }, { $eq: "Juan" }] },
//   { $pipe: [{ $get: "age" }, { $gt: 18 }] }
// ] }

Built-in Operations

Core Operations

$apply

Applies the parameters directly (identity for parameters).

{ "$apply": [1, 2, 3] } // Returns [1, 2, 3]

$compose

Composes multiple expressions together using mathematical composition order (right-to-left). The expressions are applied in the order f(g(h(x))) where [f, g, h] means f applied to the result of g applied to the result of h applied to x.

{
	"$compose": [
		{ "$map": { "$get": "name" } }, // f: map to names
		{ "$filter": { "$gt": 18 } }, // g: filter adults
		{ "$get": "users" } // h: get users
	]
}

$debug

Evaluates an expression, logs the result to console, and returns the result (useful for debugging intermediate values in expression chains).

{ "$debug": { "$get": "name" } } // Logs the value of data.name, returns data.name
{ "$debug": { "$sum": [1, 2, 3] } } // Logs 6, returns 6

$echo

Returns the input data unchanged (identity function).

{ "$echo": null } // Returns the entire input data object

$ensurePath

Validates that a path exists in the data, throwing an error if not found.

{ "$ensurePath": "user.profile.email" } // Throws if path doesn't exist

$get

Retrieves a value from the data object using lodash-style path notation.

{ "$get": "name" }          // Gets data.name
{ "$get": "user.age" }      // Gets data.user.age (nested path)

$isDefined

Tests whether the input data is defined (not undefined).

{ "$isDefined": null } // Returns true if data !== undefined

$literal

Returns a literal value (useful when you need to pass a value that might be confused with an expression).

{ "$literal": { "$get": "not-an-expression" } }

$pipe

Pipes data through multiple expressions using pipeline order (left-to-right). The expressions are applied in the order h(g(f(x))) where [h, g, f] means f applied to x, then g applied to that result, then h applied to that result.

{
	"$pipe": [
		{ "$get": "users" }, // h: get users
		{ "$filter": { "$gt": 18 } }, // g: filter adults
		{ "$map": { "$get": "name" } } // f: map to names
	]
}

Note: $pipe is often more intuitive as it matches the natural reading order, while $compose follows mathematical function composition conventions.

Conditional Operations

$case

Switch-like expression that matches a value against multiple cases and returns the corresponding result.

{
	"$case": {
		"value": { "$get": "activity" },
		"cases": [
			{ "when": "playing", "then": "Child is playing" },
			{ "when": "napping", "then": "Child is napping" },
			{ "when": "eating", "then": "Child is eating" }
		],
		"default": "Unknown activity"
	}
}

The $case expression evaluates the value once and compares it against each when clause. When a match is found, it returns the corresponding then value. If no match is found, it returns the default value.

When clauses support two formats:

  • Simple equality: { "when": "value" } - matches if the value equals "value"
  • Complex expressions: { "when": { "$eq": "value" } } - evaluates the expression with the value as input

All parts (value, when, then, default) can be expressions or literal values.

$if

Conditional expression that evaluates different branches based on a condition.

{
	"$if": {
		"if": { "$gte": 18 },
		"then": "Adult",
		"else": "Minor"
	}
}

Logical Operations

$and

Logical AND operation - all expressions must be truthy.

{ "$and": [{ "$gt": 18 }, { "$eq": "active" }] }

$not

Logical NOT operation - inverts the truthiness of an expression.

{ "$not": { "$eq": true } }

$or

Logical OR operation - at least one expression must be truthy.

{ "$or": [{ "$eq": "admin" }, { "$eq": "moderator" }] }

Comparison Operations

All comparison operations use mathematical abbreviations for consistency and brevity.

$eq

Equality comparison using deep equality.

{ "$eq": "published" } // data === "published"

$gt

Greater than comparison.

{ "$gt": 90 } // data > 90

$gte

Greater than or equal comparison.

{ "$gte": 18 } // data >= 18

$in

Array membership test (in).

{ "$in": ["tech", "science", "math"] } // data is in array

$lt

Less than comparison.

{ "$lt": 100 } // data < 100

$lte

Less than or equal comparison.

{ "$lte": 3 } // data <= 3

$ne

Inequality comparison using deep equality.

{ "$ne": "draft" } // data !== "draft"

$nin

Array membership test (not in).

{ "$nin": ["deleted", "archived"] } // data is not in array

Aggregative Operations

$count

Count of items in an array.

{ "$count": [1, 2, 3, 4] } // Returns 4

$max

Maximum of array values.

{ "$max": [1, 5, 3, 9] } // Returns 9

$mean

Arithmetic mean (average) of array values.

{ "$mean": [1, 2, 3, 4, 5] } // Returns 3

Returns undefined for empty arrays.

$median

Median (middle value) of array values.

{ "$median": [1, 2, 3, 4, 5] } // Returns 3
{ "$median": [1, 2, 3, 4] }    // Returns 2.5 (average of middle two)

Returns undefined for empty arrays.

$min

Minimum of array values.

{ "$min": [1, 5, 3, 9] } // Returns 1

$mode

Mode (most frequent value) of array values.

{ "$mode": [1, 2, 2, 3, 4] }    // Returns 2 (single mode)
{ "$mode": [1, 1, 2, 2, 3] }    // Returns [1, 2] (multiple modes)
{ "$mode": [1, 2, 3, 4, 5] }    // Returns undefined (no mode)

Returns the single mode value, array of multiple modes, or undefined if no mode exists.

$quantile

Calculates quantiles (percentiles, quartiles, etc.) of array values.

// Quartiles (4-quantiles)
{ "$quantile": { "values": [1,2,3,4,5,6,7,8,9,10], "k": 1, "n": 4 } } // Q1
{ "$quantile": { "values": [1,2,3,4,5,6,7,8,9,10], "k": 2, "n": 4 } } // Q2 (median)
{ "$quantile": { "values": [1,2,3,4,5,6,7,8,9,10], "k": 3, "n": 4 } } // Q3

// Percentiles (100-quantiles)
{ "$quantile": { "values": [1,2,3,4,5,6,7,8,9,10], "k": 50, "n": 100 } } // 50th percentile
{ "$quantile": { "values": [1,2,3,4,5,6,7,8,9,10], "k": 90, "n": 100 } } // 90th percentile

Parameters:

  • values: Array of numeric values
  • k: The k-th quantile to calculate (0 ≤ k ≤ n)
  • n: The total number of quantiles (e.g., 4 for quartiles, 100 for percentiles)

Returns undefined for empty arrays. Uses linear interpolation for non-integer indices.

$sum

Sum of array values.

{ "$sum": [1, 2, 3, 4] } // Returns 10

Iterative Operations

$all

Tests if all elements in an array satisfy a predicate (similar to Array.every).

{ "$all": { "$gt": 0 } } // Returns true if all items > 0

$any

Tests if any element in an array satisfies a predicate (similar to Array.some).

{ "$any": { "$gt": 50 } } // Returns true if any item > 50

$concat

Concatenates two arrays together.

{ "$concat": [4, 5] } // With input [1, 2, 3], returns [1, 2, 3, 4, 5]

$filter

Filter array items based on a condition.

{ "$filter": { "$gt": 50 } } // Filters array, keeping items > 50

$find

Returns the first element in an array that satisfies a predicate, or undefined if none found.

{ "$find": { "$eq": "target" } } // Returns first item === "target"

$flatMap

Transform and flatten array items.

{ "$flatMap": { "$get": "products" } } // Maps and flattens results

$join

Joins array elements into a string with a separator.

{ "$join": ", " } // With input [1, 2, 3], returns "1, 2, 3"
{ "$join": "" }   // With input ["a", "b", "c"], returns "abc"

$map

Transform each item in an array.

{ "$map": { "$get": "name" } } // Maps over array, getting "name" from each item

$reverse

Returns a new array with elements in reverse order.

{ "$reverse": {} } // With input [1, 2, 3], returns [3, 2, 1]

Generative Operations

$random

Generates a random number with optional range and precision control.

{ "$random": {} }                                          // 0 to 1 (default)
{ "$random": { "min": 10, "max": 20 } }                   // 10 to 20 range
{ "$random": { "min": 0, "max": 1, "precision": 2 } }     // 2 decimal places (0.XX)
{ "$random": { "min": 0, "max": 100, "precision": 0 } }   // Integers (0 decimal places)
{ "$random": { "min": 0, "max": 1000, "precision": -1 } } // Round to nearest 10

Parameters:

  • min (default: 0): Minimum value (inclusive)
  • max (default: 1): Maximum value (exclusive)
  • precision (default: null): Decimal places for positive values, or power of 10 for negative values
    • precision: 2 → 2 decimal places (0.01 precision)
    • precision: 0 → integers (1.0 precision)
    • precision: -1 → round to nearest 10
    • precision: null → no rounding (full precision)

$uuid

Generates a unique UUID v4 string.

{ "$uuid": null } // Returns UUID like "f47ac10b-58cc-4372-a567-0e02b2c3d479"

The operand is ignored - this expression always generates a new UUID.

Temporal Operations

$nowLocal

Returns the current date and time as a local RFC3339 string with timezone offset.

{ "$nowLocal": null } // Returns "2024-01-01T05:00:00.000-07:00"

The operand is ignored - this expression returns the current local time with timezone information in RFC3339 format.

$nowUTC

Returns the current date and time as a UTC RFC3339 string.

{ "$nowUTC": null } // Returns "2024-01-01T12:00:00.000Z"

The operand is ignored - this expression always returns the current UTC time in RFC3339 format.

$timestamp

Returns the current timestamp as a number (milliseconds since Unix epoch).

{ "$timestamp": null } // Returns current timestamp like 1704067200000

The operand is ignored - this expression always returns the current timestamp when evaluated.

Examples

Basic Usage

import { defaultExpressionEngine } from "@data-prism/expressions";

const data = {
	user: { name: "Fatoumata", age: 30 },
	orders: [
		{ id: 1, amount: 50 },
		{ id: 2, amount: 75 },
		{ id: 3, amount: 120 },
	],
};

// Check if user is adult
const isAdult = defaultExpressionEngine.apply({ $gte: 18 }, data.user.age);
// Returns: true

// Get user name
const userName = defaultExpressionEngine.apply({ $get: "name" }, data.user);
// Returns: "Fatoumata"

// Calculate total order amount
const orderAmounts = data.orders.map((order) => order.amount);
const totalAmount = defaultExpressionEngine.apply({ $sum: orderAmounts }, null);
// Returns: 245

// Calculate average order amount
const avgAmount = defaultExpressionEngine.apply({ $mean: orderAmounts }, null);
// Returns: 81.67

// Get median order amount
const medianAmount = defaultExpressionEngine.apply(
	{ $median: orderAmounts },
	null,
);
// Returns: 75

// Calculate 75th percentile of order amounts
const p75 = defaultExpressionEngine.apply(
	{
		$quantile: { values: orderAmounts, k: 75, n: 100 },
	},
	null,
);
// Returns: 97.5

// Get names of adult users using pipe (left-to-right)
const adultNames = defaultExpressionEngine.apply(
	{
		$pipe: [
			{ $get: "users" },
			{ $filter: { $gte: 18 } },
			{ $map: { $get: "name" } },
		],
	},
	data,
);
// Returns: ["Fatoumata"]

// Same operation using compose (right-to-left)
const adultNamesComposed = defaultExpressionEngine.apply(
	{
		$compose: [
			{ $map: { $get: "name" } },
			{ $filter: { $gte: 18 } },
			{ $get: "users" },
		],
	},
	data,
);
// Returns: ["Fatoumata"]

// Determine child's activity status
const activityStatus = defaultExpressionEngine.apply(
	{
		$case: {
			value: { $get: "activity" },
			cases: [
				{ when: "playing", then: "Child is playing" },
				{ when: "napping", then: "Child is napping" },
				{ when: "eating", then: "Child is eating" },
			],
			default: "Unknown activity",
		},
	},
	{ activity: "playing" },
);
// Returns: "Child is playing"

// Categorize children by age group
const ageGroup = defaultExpressionEngine.apply(
	{
		$case: {
			value: { $get: "age" },
			cases: [
				{ when: { $lt: 2 }, then: "Toddler" },
				{ when: { $lt: 5 }, then: "Preschooler" },
				{ when: { $gte: 5 }, then: "School age" },
			],
			default: "Unknown age group",
		},
	},
	{ age: 4 },
);
// Returns: "Preschooler"

// Generate random data with parameters
const randomValue = defaultExpressionEngine.apply({ $random: {} }, null);
// Returns: 0.7234 (random number 0-1)

const randomInt = defaultExpressionEngine.apply(
	{
		$random: { min: 1, max: 100, precision: 0 },
	},
	null,
);
// Returns: 42 (random integer 1-99)

const randomPrice = defaultExpressionEngine.apply(
	{
		$random: { min: 10, max: 50, precision: 2 },
	},
	null,
);
// Returns: 23.45 (random price with 2 decimal places)

const uniqueId = defaultExpressionEngine.apply({ $uuid: null }, null);
// Returns: "f47ac10b-58cc-4372-a567-0e02b2c3d479" (unique UUID)

// Get current time information
const utcTime = defaultExpressionEngine.apply({ $nowUTC: null }, null);
// Returns: "2024-01-01T12:00:00.000Z" (UTC time string)

const localTime = defaultExpressionEngine.apply({ $nowLocal: null }, null);
// Returns: "2024-01-01T05:00:00.000-07:00" (local time with timezone)

const timestamp = defaultExpressionEngine.apply({ $timestamp: null }, null);
// Returns: 1704067200000 (current timestamp)

// Use in conditional logic
const sessionId = defaultExpressionEngine.apply(
	{
		$if: {
			if: { $eq: null },
			then: { $uuid: null },
			else: { $get: "existingId" },
		},
	},
	{ existingId: null },
);
// Returns: new UUID since existingId is null

// Evaluate static expressions
const staticExpr = { $sum: [10, 20, 30] };
const precomputed = defaultExpressionEngine.evaluate(staticExpr);
console.log("Static result:", precomputed); // 60

// Evaluate static query expressions
const queryExpression = {
	$if: {
		if: true, // Static condition
		then: { $sum: [1, 2, 3] }, // Static calculation
		else: { $get: "fallbackValue" },
	},
};

const optimized = defaultExpressionEngine.evaluate(queryExpression);
console.log("Pre-computed result:", optimized); // 6

Query Enhancement

// In a Data Prism query
const query = {
  "type": "products",
  "where": {
    "$and": [
      { "$gte": 10 },
      { "$lte": 100 },
      { "$eq": true }
    ]
  },
  "select": {
    "name": "name",
    "price": "price",
    "priceWithTax": { "$sum": ["price", "tax"] },
    "category": "category"
  }
};

Custom Operations

import {
	createExpressionEngine,
	defaultExpressions,
} from "@data-prism/expressions";

const customEngine = createExpressionEngine({
	...defaultExpressions,

	// Custom string operation
	$titleCase: {
		apply: (str) => {
			return str
				.toLowerCase()
				.split(" ")
				.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
				.join(" ");
		},
	},

	// Custom validation operation
	$isValidEmail: {
		apply: (email) => {
			const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
			return emailRegex.test(email);
		},
	},
});

// Use custom operations
const result = customEngine.apply({ $titleCase: "paul bunyan" }, null);
// Returns: "Paul Bunyan"

Expressions for Reusable Logic

import { defaultExpressionEngine } from "@data-prism/expressions";

// Define reusable expression
const discountPriceExpression = {
	$if: {
		if: { $gt: 0 },
		then: { $sum: ["price", "discount"] },
		else: { $get: "price" },
	},
};

// Apply to multiple products
const products = [
	{ name: "Laptop", price: 1000, discount: -100 },
	{ name: "Mouse", price: 50, discount: -2.5 },
	{ name: "Keyboard", price: 100, discount: 0 },
];

const discountedPrices = products.map((product) =>
	defaultExpressionEngine.apply(discountPriceExpression, product),
);
// Returns: [900, 47.5, 100]

Integration with Data Prism Core

Expressions work seamlessly with Data Prism queries:

import { defaultExpressionEngine } from "@data-prism/expressions";
import { queryGraph } from "@data-prism/core";

const query = {
	type: "users",
	where: {
		$and: [{ $gte: 21 }, { $eq: "active" }],
	},
	select: {
		name: "name",
		isAdult: { $gte: 18 },
		ageGroup: {
			$case: {
				value: { $get: "age" },
				cases: [
					{ when: { $lt: 30 }, then: "young" },
					{ when: { $lt: 50 }, then: "middle" },
				],
				default: "senior",
			},
		},
	},
};

// Use with expression engine in query options
const results = queryGraph(schema, query, graph, {
	expressionEngine: defaultExpressionEngine,
});

Related Packages

  • @data-prism/core - Core schema and querying functionality
  • @data-prism/memory-store - In-memory data store with expression support
  • @data-prism/postgres-store - PostgreSQL backend with SQL expression compilation