Prism · guide

Compile once

A config that is stored is compiled to a document of its own, and run from that.

Install it
pnpm add @niscorp/prism @niscorp/strata zod
Step 1 of 3

A booking

A booking as the box office stores it: who, which show, which seats, and what a seat costs in cents. Every guide here reads this row or a few like it.

A booking
import { compile, execute } from '@niscorp/prism';

const booking = {
  id: 'B-2041',
  member: { name: 'Grace', pass: 'season' },
  show: { title: 'The Tempest', starts_at: '2026-10-24T19:30:00+02:00' },
  seats: ['C4', 'C5'],
  seat_price_cents: 3800,
};
Step 2 of 3

Compile

compile checks a config once, resolves its sugar, and answers an intermediate form. That form is JSON too: it can be stored in a database, kept in a cache, or sent over a wire.

It carries a fingerprint of the config, and what the compiler counted in it.

Compile
const forTheDoor = {
  name: { $ref: '$.member.name' },
  admit: { $length: { $ref: '$.seats' } },
};
const ir = await compile(forTheDoor, { name: 'door', version: '1.0.0' });
console.log(ir.meta.fingerprint.slice(0, 16), JSON.stringify(ir.meta.stats.opCount));
Step 3 of 3

Execute

execute runs the compiled form against a source. It does not check or resolve anything again, so it runs from what was stored, in another process or on another day.

Execute
console.log(execute(ir, booking));
console.log(execute(ir, { member: { name: 'Alan' }, seats: ['A1', 'A2', 'A3'] }));
Then

Run it.

The start of the fingerprint and the operators the compiler counted, and then the same compiled config run for two bookings.

Run it
npx tsx compile.mts
It prints
45a7283a24324f85 {"$ref":2,"$length":1}
{ name: 'Grace', admit: 2 }
{ name: 'Alan', admit: 3 }