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

@taioncom/taion-expression

v1.1.0

Published

A safe, sandboxed expression evaluator for JavaScript/TypeScript with large set of built-in functions

Downloads

37

Readme

Taion Expression

A safe, sandboxed expression language for parsing and evaluating user-provided expressions. Parses expressions into an Abstract Syntax Tree (AST) that is securely interpreted with a given context.

Install

npm install @taioncom/taion-expression

Purpose

This library provides a controlled environment for evaluating expressions written by external users for purposes such as:

  • Filtering data
  • Defining workflow logic
  • Creating dynamic rules
  • Conditional processing

Since expressions can be written by external users, the language is designed to be safe, predictable, and limited in scope to prevent security issues.

Language Specification

Data Types

  • Number: Integer and floating-point numbers (e.g., 42, 3.14)
  • String: Text enclosed in single, double quotes, or backticks (e.g., "hello", 'world', `template`)
  • Boolean: true or false
  • Null: null
  • Array: Ordered collection of values (e.g., [1, 2, 3])
  • Date: Date/time values created via built-in functions (e.g., now(), date(2024, 3, 15))

Variables

Variables are referenced by name and resolved from the context object provided during evaluation:

user.name
items.length
settings.enabled

Operators

Arithmetic Operators

  • Addition: +
  • Subtraction: -
  • Multiplication: *
  • Division: /
  • Modulo: %
  • Exponentiation: ^
  • Unary negation: - (e.g., -5)

Comparison Operators

  • Equal: == (strict equality)
  • Not equal: != (strict inequality)
  • Greater than: >
  • Less than: <
  • Greater than or equal: >=
  • Less than or equal: <=

Logical Operators

  • AND: &&
  • OR: ||
  • NOT: !

String Operators

  • Concatenation: + (e.g., "Hello" + " " + "World")
  • Template literals: `Hello, ${name}!` (with enableTemplateStrings option)

Array Operators

  • Indexing: array[index] (with enableArrays option)

Arrow Functions

When the enableArrowFunctions option is enabled, you can use arrow functions (lambdas):

  • Single parameter without parentheses: x => x * 2
  • Multiple parameters: (x, y) => x + y
  • No parameters: () => 42

Operator Precedence

Operators are evaluated in the following order (from highest to lowest precedence):

  1. Parentheses ()
  2. Exponentiation ^
  3. Unary operators +, -, !
  4. Multiplication, division, modulo *, /, %
  5. Addition, subtraction +, -
  6. Comparison operators <, <=, >, >=, ==, !=
  7. Logical AND &&
  8. Logical OR ||

Control Flow

Conditional (Ternary) Expression

condition ? trueExpression : falseExpression

If-Then-Else Expression

The if-then-else expression allows for conditional logic:

if (condition) then expression1 else expression2
  • condition must evaluate to a boolean value
  • expression1 is evaluated if the condition is true
  • expression2 is evaluated if the condition is false
  • Both expression1 and expression2 must be of the same type

Example:

if (user.age >= 18) then "Adult" else "Minor"

Template Strings

With the enableTemplateStrings option, you can use template literals with string interpolation:

`Hello, ${name}! You are ${age} years old.`

This allows for more readable string construction with embedded expressions.

Arrays

With the enableArrays option, you can create and manipulate arrays:

// Array literal
[1, 2, 3, 4, 5]

// Array with expressions
[a, b + c, func()]

// Array indexing
items[0]
matrix[row][col]

Functions

Functions must be pre-registered in the evaluation context to be available for use. This ensures only safe, allowed functions can be called.

Function calls use the following syntax:

functionName(argument1, argument2, ...)

Built-in Functions

The language includes several safe built-in functions:

String Functions
  • length(str), contains(str, sub), startsWith(str, prefix), endsWith(str, suffix)
  • toLowerCase(str), toUpperCase(str), substring(str, start, end?), trim(str), trimStart(str), trimEnd(str)
  • replace(str, search, replacement) (replaces all occurrences), split(str, separator), indexOf(str, search), lastIndexOf(str, search)
  • capitalize(str, allWords?), padLeft(value, len, pad?), padRight(value, len, pad?)
  • repeat(str, n), charAt(str, index), includes(strOrArray, search), concat(...values)
Math Functions
  • Basic: min(...values), max(...values) (variadic), round(num, decimals?), floor(num), ceil(num), abs(num)
  • Advanced: pow(base, exp), sqrt(num), log(num), log10(num), log2(num), sign(num), trunc(num), mod(a, b)
  • Interpolation: clamp(value, min, max), lerp(a, b, t)
  • Constants: pi(), e()
Trigonometric Functions
  • sin(rad), cos(rad), tan(rad), asin(num), acos(num), atan(num), atan2(y, x)
Array Functions
  • Basic: length(array), sum(array), avg(array), arrayContains(array, value), count(array)
  • Access: first(array), last(array), slice(array, start, end?)
  • Transform: join(array, separator), sort(array), reverse(array), unique(array), compact(array), flat(array, depth?)
  • Generate: range(start, end, step?)
  • Reshape: chunk(array, size), zip(arr1, arr2)
Statistical Functions
  • median(array), stddev(array), variance(array), percentile(array, p)
Higher-Order Array Functions (require enableArrowFunctions)
  • Iterate: map(array, fn), filter(array, fn), find(array, fn), findIndex(array, fn), reduce(array, fn, initial?), every(array, fn), some(array, fn)
  • Sort/Group: sortBy(array, fn), groupBy(array, fn), distinctBy(array, fn)
  • Aggregate: minBy(array, fn), maxBy(array, fn), sumBy(array, fn), countBy(array, fn)
Object Functions
  • keys(object), values(object), entries(object)
  • hasKey(object, key), merge(obj1, obj2), pick(object, ...keys), omit(object, ...keys), fromEntries(entries)
Type Checking
  • type(value): Returns 'number', 'string', 'boolean', 'array', 'object', 'date', or 'null'
  • isNull(value), isUndefined(value), isDefined(value), isNumber(value), isString(value)
  • isBoolean(value), isObject(value), isArray(value), isDate(value), isEmpty(value)
Conversion
  • toString(value), toNumber(value), toBoolean(value), toInteger(value), toDate(value)
  • toFixed(num, digits), parseInt(str, radix?), parseFloat(str)
Utility
  • coalesce(...values): Returns the first non-null/undefined value
  • ifElse(condition, thenValue, elseValue): Inline conditional
  • defaultTo(value, fallback): Returns fallback if value is null/undefined/NaN
  • jsonStringify(value), jsonParse(str)
Random
  • random(), randomInt(min, max)
Regex
  • regexTest(str, pattern), regexMatch(str, pattern), regexReplace(str, pattern, replacement)
Date Functions
  • Creation: now(), date(y, m, d, h?, min?, s?, ms?) (month 1-based), parseDate(str), toDate(value)
  • Extraction: year(date), month(date) (1-12), day(date), hour(date), minute(date), second(date), dayOfWeek(date) (0=Sun), timestamp(date)
  • Formatting: formatDate(date, pattern?) (tokens: yyyy, yy, MM, dd, HH, mm, ss, SSS), toISOString(date)
  • Arithmetic: dateAdd(date, amount, unit), dateDiff(d1, d2, unit) (units: years, months, weeks, days, hours, minutes, seconds, milliseconds; months/years use calendar-aware calculation)
  • Utilities: startOfDay(date), endOfDay(date), startOfMonth(date), endOfMonth(date), dateBetween(date, start, end)

Custom Functions

Custom functions can be registered during initialization:

import { evaluateExpression } from '@taioncom/taion-expression';

const options = {
  customFunctions: {
    greet: (name) => `Hello, ${name}!`,
    calculateTax: (amount, rate) => amount * (rate / 100),
  },
};

const result = evaluateExpression('greet(name)', { name: 'John' }, options);
console.log(result.result); // "Hello, John!"

Security Features

The expression evaluator includes several security features to ensure safe evaluation:

Property Access Control

Control which properties can be accessed through allowlists and denylists:

// Only allow these properties to be accessed
const options = {
  allowedProperties: ['name', 'age', 'score'],
};

// Deny access to these properties
const options = {
  deniedProperties: ['password', 'secretKey', 'token'],
};

Timeout Control

Prevent infinite loops and expensive calculations by setting a maximum execution time:

const options = { timeout: 1000 }; // 1 second timeout
const result = evaluateExpression('complexExpression', context, options);

Prototype Access Prevention

By default, the evaluator prevents access to object prototypes to avoid prototype pollution:

// Only enable if absolutely needed and you trust the input
const options = { allowPrototypeAccess: false }; // Default

Call Stack Depth Limiting

Prevent stack overflow attacks by limiting call stack depth:

const options = { maxCallStackDepth: 50 }; // Default

Expression Complexity Limiting

Limit the complexity of expressions to prevent resource exhaustion:

const options = { maxComplexity: 100 }; // Default

Loop Iteration Limiting

Prevent infinite loops by limiting the number of iterations:

const options = { maxLoopIterations: 10000 }; // Default

Feature Toggle

Enable or disable specific features based on your needs:

// Enable template string support
const options = { enableTemplateStrings: true };

// Enable array literals and indexing
const options = { enableArrays: true };

// Enable arrow functions
const options = { enableArrowFunctions: true };

Usage

Basic Example

import { evaluateExpression } from '@taioncom/taion-expression';

// Simple arithmetic
const result = evaluateExpression('2 + 3 * 4');
console.log(result.result); // 14

// With context
const context = {
  user: {
    name: 'John',
    age: 25,
  },
};

const ageCheck = evaluateExpression(
  'user.age >= 18 ? "Adult" : "Minor"',
  context,
);
console.log(ageCheck.result); // "Adult"

Template Strings Example

import { evaluateExpression } from '@taioncom/taion-expression';

const context = { name: 'John', age: 30 };
const options = { enableTemplateStrings: true };

const greeting = evaluateExpression(
  '`Hello, ${name}! You are ${age} years old.`',
  context,
  options,
);
console.log(greeting.result); // "Hello, John! You are 30 years old."

Array Example

import { evaluateExpression } from '@taioncom/taion-expression';

const context = {
  items: ['apple', 'banana', 'cherry'],
  index: 1,
  numbers: [1, 2, 3, 4, 5],
};
const options = { enableArrays: true };

// Basic array indexing
const item = evaluateExpression('items[index]', context, options);
console.log(item.result); // "banana"

// Array literals
const newArray = evaluateExpression('[1, 2, 3, 4, 5]', {}, options);
console.log(newArray.result); // [1, 2, 3, 4, 5]

// Using array functions for operations
const joined = evaluateExpression('join(items, ", ")', context, options);
console.log(joined.result); // "apple, banana, cherry"

const isSorted = evaluateExpression('sort(numbers)', context, options);
console.log(isSorted.result); // [1, 2, 3, 4, 5]

const reversed = evaluateExpression('reverse(numbers)', context, options);
console.log(reversed.result); // [5, 4, 3, 2, 1]

// Using pre-defined helper functions
const sumArray = evaluateExpression('sum(numbers)', context, options);
console.log(sumArray.result); // 15

const avgValue = evaluateExpression('avg(numbers)', context, options);
console.log(avgValue.result); // 3

// Using arrow functions (requires enableArrowFunctions option)
const arrowOptions = {
  enableArrays: true,
  enableArrowFunctions: true,
};

// Use arrow functions directly in expressions
// When enableArrowFunctions option is true
const doubledNumbers = evaluateExpression(
  'map(numbers, x => x * 2)',
  context,
  arrowOptions,
);
console.log(doubledNumbers.result); // [2, 4, 6, 8, 10]

const evenNumbers = evaluateExpression(
  'filter(numbers, x => x % 2 == 0)',
  context,
  arrowOptions,
);
console.log(evenNumbers.result); // [2, 4]

// Arrow functions work with multiple parameters too
const sum = evaluateExpression(
  'reduce(numbers, (acc, x) => acc + x, 0)',
  context,
  arrowOptions,
);
console.log(sum.result); // 15

// And with empty parameter lists
const constant = evaluateExpression(
  'execute(() => 42)',
  { execute: (fn) => fn() },
  arrowOptions,
);
console.log(constant.result); // 42

Complex Example

import { evaluateExpression } from '@taioncom/taion-expression';

const expression = `
  if (order.total > 100) then
    if (user.isPremium) then
      order.total * 0.85 // 15% discount for premium users on orders over $100
    else
      order.total * 0.9  // 10% discount for regular users on orders over $100
  else
    order.total
`;

const context = {
  order: {
    total: 120,
  },
  user: {
    isPremium: true,
  },
};

const result = evaluateExpression(expression, context);
console.log(result.result); // 102 (120 * 0.85)

Error Handling

When parsing or evaluating expressions, the library provides detailed error messages to help troubleshoot issues:

import {
  evaluateExpression,
  safeEvaluateExpression,
} from '@taioncom/taion-expression';

// Using the standard evaluator with error handling
const result = evaluateExpression('1 + / 2');
if (!result.success) {
  console.error(result.error.message); // "Unexpected token '/' after expression"
}

// Using the safe evaluator which returns null on error
const safeResult = safeEvaluateExpression('1 + / 2');
console.log(safeResult); // null

Limitations

This expression language is intentionally limited in functionality to ensure safety and predictability. It is not intended to be a full-featured programming language.

  • No side effects: Expressions cannot modify the context or environment
  • No loops: To prevent infinite loops, the language does not include loop constructs
  • Limited recursion: Function calls are limited in depth to prevent stack overflow
  • Sandboxed execution: Expressions run in a sandboxed environment
  • No dynamic code execution: No eval() or similar functions are allowed

License

MIT

Trademark Notice

"Taion" is a registered trademark of Taion Oy. The MIT license grants rights to the source code only and does not grant permission to use the "Taion" name, logo, or trademarks. You may not use the "Taion" name in forks, derivative products, services, or marketing materials in any way that implies endorsement by or affiliation with Taion Oy without prior written permission.