Skip to content

veridtools/feel-runner

Repository files navigation

@veridtools/feel-runner

Veridtools Logo

npm license ci docs dependencies

Full FEEL expression engine for DMN 1.5 — zero dependencies, Decimal128 precision, 97%+ OMG conformance.

@veridtools/feel-runner evaluates FEEL (Friendly Enough Expression Language) expressions as defined in the OMG DMN 1.5 specification. It covers all 80+ standard builtins, temporal types, ranges, contexts, quantified expressions, and unary tests — the complete language.

Install

pnpm add @veridtools/feel-runner
# or
npm install @veridtools/feel-runner

Quick start

import { evaluate, unaryTest } from '@veridtools/feel-runner'

// Evaluate any FEEL expression
evaluate('sum([1, 2, 3]) * 2').value          // 12
evaluate('upper case("hello")').value          // "HELLO"
evaluate('date("2024-01-15").month').value     // 1
evaluate('0.1 + 0.2 = 0.3').value             // true (Decimal128!)

// With context variables
evaluate('price * quantity', { price: 10, quantity: 5 }).value  // 50

// Unary tests — for DMN decision table input cells
unaryTest('[18..65]', { '?': 30 }).value       // true
unaryTest('"A","B","C"', { '?': 'D' }).value   // false
unaryTest('not([1..10])', { '?': 15 }).value   // true

CLI

Installed

# Install globally
pnpm add -g @veridtools/feel-runner
# or without installing
npx @veridtools/feel-runner "1 + 2 * 3"

# Evaluate a FEEL expression
feel-runner "(1 + 2) * 3 - 4 / 2"

# With context variables
feel-runner "price * qty" --ctx '{"price":10,"qty":5}'

# Unary test — check if value is in range
feel-runner "[18..65]" --unary --input 30

# Unary test — check if value is in list
feel-runner '"A","B","C"' --unary --ctx '{"?":"B"}'

feel-runner --help

Try it locally (from the repo)

git clone https://github.com/veridtools/feel-runner
cd feel-runner
pnpm install

# Run without building (via tsx)
npx tsx bin/feel-runner.ts "(1 + 2) * 3 - 4 / 2"
npx tsx bin/feel-runner.ts "sum([1,2,3,4,5])"
npx tsx bin/feel-runner.ts "price * qty" --ctx '{"price":10,"qty":5}'
npx tsx bin/feel-runner.ts 'date("2024-01-15").month'
npx tsx bin/feel-runner.ts "[18..65]" --unary --input 30
npx tsx bin/feel-runner.ts '"A","B","C"' --unary --ctx '{"?":"B"}'
npx tsx bin/feel-runner.ts --help

# Or build first and run directly
pnpm build
node dist/bin/feel-runner.js "some x in [1,2,3] satisfies x > 2"

Options

feel-runner <expression> [options]

  -u, --unary         Evaluate as unary test (requires "?" in context)
  -i, --input <v>     Input value for unary test (shorthand for --ctx '{"?": v}')
  -c, --ctx <json>    Context variables as JSON object
  -n, --no-color      Disable ANSI colors
  -h, --help          Show help

Documentation

Full docs with interactive playground:

pnpm docs:dev       # Start docs server at localhost:5173
pnpm docs:build     # Build for production
pnpm docs:preview   # Preview production build

Documentation sections

  • Playground — Interactive FEEL evaluator in the browser
  • Getting Started — Install, quickstart, return types
  • Expressions — Arithmetic, strings, comparisons, if/for/some/every, functions, instance of
  • Unary Tests — Ranges, disjunctions, negation, wildcards
  • Types — All FEEL types and null semantics
  • Built-in Functions — All 80+ builtins with examples
  • Temporal — Dates, times, durations, timezone handling, calendar functions
  • Context & Variables — Passing variables, path expressions, recursion
  • API Referenceevaluate(), unaryTest(), FeelValue, EvaluationResult

Development

pnpm install          # Install dependencies
pnpm test             # Run all tests (unit + conformance)
pnpm test:watch       # Watch mode
pnpm typecheck        # TypeScript type checking
pnpm build            # Build the package (ESM + CJS)

Tests

The project has three test layers. See tests/README.md for the full breakdown.

Unit tests — src/**/*.test.ts

1271+ hand-written assertions across 23 test files, colocated next to the source files they test — covering every builtin, edge case, combination scenario, and language construct — including safeParse, ParseSyntaxError, ErrorNode, compile/cache behavior, and all negative/error paths.

npx vitest run src/

Conformance tests — tests/tck/

2965 official OMG TCK test cases from the DMN 1.5 specification, covering compliance levels 2 and 3. These are the authoritative spec tests — passing them means conforming to the standard.

npx vitest run tests/tck/   # ~2 min

DMN fixture tests — tests/fixtures/

Data-driven tests from the @veridtools/dmn-fixtures catalog — real DMN documents paired with expected outputs, validated against the OMG TCK and FEEL spec.

npx vitest run tests/fixtures/

Features

  • Zero dependencies — only decimal.js for Decimal128 arithmetic
  • Decimal128 precision0.1 + 0.2 = 0.3, exactly, always
  • Complete temporal support — date, time, date and time, year-month duration, day-time duration, timezone/offset, leap year validation, ISO 8601 formatting
  • Full builtin library — all 80+ standard DMN 1.5 functions + practical extensions (is blank, get or else, error, assert, uuid, to/from base64, last day of month, unix timestamps, partition)
  • Unary tests — DMN decision table input cells, all forms
  • Named argumentssubstring(string: "hello", start position: 2)
  • Typed function paramsfunction(x: number) x + 1
  • Recursion — functions in contexts can call themselves
  • Structured warnings — non-fatal issues returned alongside the value (PARSE_ERROR, NO_VARIABLE_FOUND, INVALID_TYPE, …)
  • safeParse() + ParseSyntaxError — error-recovering parser for IDE/tooling use cases; returns partial AST with ErrorNode sentinels and start/end character positions on every error
  • ESM + CJS — works in Node.js, Bun, and modern bundlers

Contributing

See CONTRIBUTING.md

License

MIT — LICENSE

About

FEEL expression evaluator and DMN decision runner

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors