@xpr-lang/xpr
v0.5.0
Published
Sandboxed cross-language expression language for data pipeline transforms
Maintainers
Readme
@xpr-lang/xpr
XPR is a sandboxed cross-language expression language for data pipeline transforms. This is the TypeScript/JavaScript reference runtime.
Install
bun add @xpr-lang/xpr
# or
npm install @xpr-lang/xprQuick Start
import { Xpr } from '@xpr-lang/xpr';
const engine = new Xpr();
engine.evaluate('items.filter(x => x.price > 50).map(x => x.name)', {
items: [
{ name: 'Widget', price: 25 },
{ name: 'Gadget', price: 75 },
{ name: 'Doohickey', price: 100 },
]
});
// → ["Gadget", "Doohickey"]API
evaluate(expression, context?)
Evaluates an XPR expression against an optional context object.
const engine = new Xpr();
engine.evaluate('1 + 2'); // → 3
engine.evaluate('user.name', { user: { name: 'Alice' } }); // → "Alice"
engine.evaluate('items.length', { items: [1, 2, 3] }); // → 3Returns the result as unknown. Throws XprError on parse or evaluation errors.
addFunction(name, fn)
Register a custom function callable from expressions:
const engine = new Xpr();
engine.addFunction('double', (x) => (x as number) * 2);
engine.addFunction('greet', (name) => `Hello, ${name}!`);
engine.evaluate('double(21)'); // → 42
engine.evaluate('greet("World")'); // → "Hello, World!"
engine.evaluate('items.map(x => double(x))', { items: [1, 2, 3] }); // → [2, 4, 6]Built-in Functions
Math: round, floor, ceil, abs, min, max
Type: type, int, float, string, bool
String methods: .len(), .upper(), .lower(), .trim(), .startsWith(), .endsWith(), .contains(), .split(), .replace(), .slice(), .indexOf(), .repeat(), .trimStart(), .trimEnd(), .charAt(), .padStart(), .padEnd()
Array methods: .map(), .filter(), .reduce(), .find(), .some(), .every(), .flatMap(), .sort(), .reverse(), .length, .includes(), .indexOf(), .slice(), .join(), .concat(), .flat(), .unique(), .zip(), .chunk(), .groupBy()
Object methods: .keys(), .values(), .entries(), .has()
Utility: range()
v0.2 Features
Let Bindings: Immutable scoped bindings allow you to define and reuse values within expressions:
engine.evaluate('let x = 1; let y = x + 1; y'); // → 2
engine.evaluate('let items = [1, 2, 3]; items.map(x => x * 2)', {}); // → [2, 4, 6]Spread Operator: Spread syntax for arrays and objects enables composition and merging:
engine.evaluate('[1, 2, ...[3, 4]]'); // → [1, 2, 3, 4]
engine.evaluate('{...{a: 1}, b: 2}'); // → {a: 1, b: 2}Conformance
This runtime supports Level 1–3 (all conformance levels):
- Level 1: Literals, arithmetic, comparison, logic, ternary, property access, function calls
- Level 2: Arrow functions, collection methods, string methods, template literals
- Level 3: Pipe operator (
|>), optional chaining (?.), nullish coalescing (??)
v0.2 additions: Let bindings, spread operator, 20 new built-in methods (10 array, 7 string, 2 object, 1 global)
Specification
See the XPR Language Specification for the full EBNF grammar, type system, operator precedence, and conformance test suite.
License
MIT
