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

@lemmabase/lemma-engine

v0.8.22

Published

A pure, declarative language for business rules.

Downloads

475

Readme

@lemmabase/lemma-engine

Lemma is a declarative language for business rules. This package is the engine, compiled to WebAssembly - runs in the browser, on Node, Bun, Deno, Cloudflare Workers, Vercel Edge, etc.

Pricing tiers, tax brackets, leave entitlement, eligibility checks, discount stacks: the rules that change, that auditors ask about, that legal writes in PDFs and engineers re-implement in operational code... Lemma is a language built specifically for your business rules. It is readable by stakeholders, executable anywhere, and impossible to drift out of sync.

spec pricing 2026-01-01

data money: measure
  -> unit eur 1.00
  -> decimals 2

data quantity : number
data is_vip   : false

rule unit_price:
  20 eur
  unless quantity >= 10 then 18 eur
  unless quantity >= 50 then 16 eur
  unless is_vip         then 15 eur

rule total:
  unit_price * quantity
import { Lemma } from '@lemmabase/lemma-engine';

const engine = await Lemma();
await engine.load(pricing, 'pricing.lemma');

const response = engine.run(null, 'pricing', null, { quantity: 50, is_vip: false }, null);
// response.results.unit_price → 16 eur
// response.results.total      → 800 eur

The Response carries every rule's value (or veto if no result could be computed), the input snapshot, and the source location of every rule that fired, allowing you to render an audit trail in your UI.

Why use it from JavaScript?

  • Deterministic. (spec, data, effective_date) → result. No DB, no clock, no ambient state. Same inputs → same outputs, every time.
  • Explainable. The Response tells you which rules contributed and why; pair it with the CLI for a full reasoning trace.
  • Time-aware. Multiple versions of the same spec coexist. Pass an effective date and the engine resolves the version in force on that day.
  • Statically checked. Type errors, missing data, cycles, measure-family mismatches - all caught at load() time. Bad specs never reach run().
  • Runs anywhere V8 does. ~2 MB WASM, no native binary, no postinstall script.
  • Editor in a tab. Includes an in-process language server and a Monaco adapter, so you can build a real Lemma editor experience client-side - diagnostics, completion, formatting... even without setting up a server.

Install

npm install @lemmabase/lemma-engine

Browser

import { Lemma } from '@lemmabase/lemma-engine';

const engine = await Lemma();

Lemma() initializes the WASM module once and returns an Engine. Serve over http(s), not file://. For manual control: init() then new Engine().

If your bundler emits IIFE, can't resolve import.meta.url, or refuses to ship lemma_bg.wasm as a separate asset, use the inlined entry - it embeds the wasm bytes in the JS bundle:

import { Lemma } from '@lemmabase/lemma-engine/iife';

esbuild users get an auto-rewriting plugin:

import { lemmaEngineEsbuildPlugin } from '@lemmabase/lemma-engine/esbuild';

esbuild.build({ /* ... */ plugins: [lemmaEngineEsbuildPlugin()] });

Node

Identical to the browser path:

import { Lemma } from '@lemmabase/lemma-engine';

const engine = await Lemma();

For zero-fetch startup with a preloaded module: initSync({ module }) then new Engine().

In-process LSP + Monaco

import { init } from '@lemmabase/lemma-engine';
import { LspClient } from '@lemmabase/lemma-engine/lsp-client';

await init();
const client = new LspClient(monaco);
await client.start();
await client.initialize();

client.onDiagnostics((uri, diagnostics) => { /* render */ });
client.didOpen('file:///pricing.lemma', 'lemma', 1, source);

A pre-wired Monaco adapter ships at @lemmabase/lemma-engine/monaco.

API

Engine (returned by Lemma() or new Engine()):

| Method | Description | |--------|-------------| | load(code, attribute?) | Parse and validate a .lemma spec set. Resolves on success; rejects with EngineError[]. | | load_batch(sources, dependency?) | Load many sources in one planning pass (see lemma.d.ts). | | fetch(name) | Download registry source only; resolves with { source, id }. Does not load. Rejects with EngineError[]. | | list() | JSON array of ResolvedRepository: each has repository and specs (spec sets). Always includes embedded lemma / spec units. | | format_repository(repo) | Canonical Lemma source for a loaded repository, formatted from the in-engine AST. Use "lemma" for the embedded units stdlib. | | schema(repo, name, effective?) | SpecSchema; repo null for workspace. | | run(repo, name, ruleNames, data, effective?, explain?) | Evaluate. Omit/null ruleNames for all rules; pass a non-empty array to scope. [] errors. Returns a Response. | | format(code, attribute?) | Canonical formatting; throws EngineError on parse error. |

Full TypeScript types are bundled - see lemma.d.ts.

Registry dependencies

Specs that reference uses … @org/pkg need that package available. fetch only downloads; call load_batch to load the dependency, then load your workspace:

import { Lemma } from '@lemmabase/lemma-engine';

const engine = await Lemma();
const { source, id } = await engine.fetch('@iso/countries');
await engine.load_batch({ '': source }, id);
await engine.load(sourceThatUsesStd, 'app.lemma');

In the browser, the registry must allow your origin (CORS). Use https or http://localhost when using fetch.

Status

Lemma is pre-1.0. The WASM API is stable for most use cases, but breaking changes may occur between minor versions. Pin your dependency version and review the changelog before upgrading.

WASM panic behavior

Rust panics cannot unwind on the wasm32 target, so an internal invariant violation (a bug) traps the WASM instance. The call throws a RuntimeError which you can catch with try/catch to fail gracefully, but the module's linear memory is poisoned — constructing a new Engine() from the same initialized module is not safe. To recover, re-initialize the WASM module (init() again) or, for robust containment, run the engine in a Web Worker and respawn the worker on trap. The panic message (prefixed BUG: ...) is logged to the console before the trap. All domain-level failures (invalid specs, bad data, impossible rules) are reported as EngineError[] or vetoes and never cause traps.

Related

  • lemmabase.com: public database for Lemma Specs
  • lemma: REPL, HTTP server, MCP server, formatter
  • lemma-engine: same engine as a Rust crate
  • lemma_engine on Hex: Elixir bindings via Rustler
  • VS Code / Cursor extension: search "Lemma Language" in the marketplace

License

Apache-2.0