JSPM

  • Created
  • Published
  • Downloads 988
  • Score
    100M100P100Q113628F
  • License BUSL-1.1

Sandboxed expression evaluator dla Echelon (computed fields, validation rules).

Package Exports

  • @echelon-framework/expression

Readme

@echelon-framework/expression

Sandboxed expression evaluator dla Echelon — computed bindings, conditional when, validation rules.

Status

ImplementedEchelonExpressionEngine (rc.14+). Zero deps, własny parser + AST walker.

Szybki start

import { EchelonExpressionEngine } from '@echelon-framework/expression';

const engine = new EchelonExpressionEngine();

engine.evaluate('price * (1 - discount / 100)', { price: 100, discount: 15 });
// → 85

engine.evaluate('order.items[0].qty + order.items[1].qty', {
  order: { items: [{ qty: 2 }, { qty: 3 }] },
});
// → 5

engine.evaluate('role == "premium" && score >= 80 ? "VIP" : "STD"', {
  role: 'premium',
  score: 92,
});
// → "VIP"

API

  • parse(expr) → { ok: true } | { ok: false, error } — walidacja syntaxu bez wykonywania (dla lintera).
  • evaluate(expr, scope, options?) → unknown — ewaluacja w sandboxie; options.timeoutMs (default 50ms).
  • references(expr) → string[] — statycznie wykryte ścieżki referencyjne (np. order.items.0.qty) do budowy grafu zależności computed.

Obsługiwane wyrażenia

  • Literały: 123, 3.14, "text", 'text', true, false, null
  • Arytmetyka: + - * / %
  • Porównania: == != < <= > >=
  • Logika: && || !
  • Null-coalescing: ??
  • Ternary: cond ? a : b
  • Member/index access: a.b.c, items[0], users[userId]
  • Array literals: [1, 2, 3]
  • Wywołania whitelistowanych funkcji: abs, min, max, round, floor, ceil, sqrt, pow, len, includes, startsWith, endsWith, lower, upper, trim, coalesce, isNull, isEmpty, number, string, boolean
  • Niestandardowe funkcje: new EchelonExpressionEngine({ functions: { myFn: (args) => ... } })

Sandbox i bezpieczeństwo

  • Brak eval, new Function, dostępu do prototype, __proto__, constructor.
  • Whitelist scope — tylko klucze przekazane do evaluate(expr, scope) są widoczne.
  • Timeout — default 50ms; dalsze wywołania rzucają EvaluationTimeoutError.
  • Determinizm — brak Math.random, Date.now; deterministyczne wbudowane funkcje.
  • Cache AST — LRU, default 256 (parsowanie raz, ewaluacja wielokrotna).

Integracja z runtime

Engine jest udostępniany jako singleton przez provideEchelon({ expressionEngine: new EchelonExpressionEngine(...) }) i używany przez runtime w:

  • computed: { key: 'expr' } — derived data,
  • when: 'expr' — conditional rendering,
  • bind: { prop: '$expr: ...' } — inline bindings.

Errors

  • LexerError(pos) — nielegalny znak w źródle.
  • ParserError(pos) — błąd składni.
  • EvaluationError — błąd runtime (np. nieznana funkcja).
  • EvaluationTimeoutError — przekroczono timeoutMs.