Package Exports
- @echelon-framework/expression
Readme
@echelon-framework/expression
Sandboxed expression evaluator dla Echelon — computed bindings, conditional when, validation rules.
Status
Implemented — EchelonExpressionEngine (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ścicomputed.
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 doprototype,__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— przekroczonotimeoutMs.