Rindle

API index and search · Build metadata

@rindle/room/wasm

0.0.0 · Public export map; development manifest version (0.0.0).

Source revision 05d0bf2c2e56 · build details
Source revision: 05d0bf2c2e56.
TypeScript input SHA-256: aabe6cfcc4172b870d5e272142958e9ea8d8784c2aa23133156e5a7ee633318e
Generated 2026-09-04T23:58:25.590Z with TypeScript 6.0.3. Public TypeScript checks and declaration emit passed. Package runtime tests are separate.

Entry point source

initRoomWasm

FunctionDeclaration · Source: packages/room/src/wasm.ts:15 · Supporting declarations

Initialize the room wasm module (idempotent). Call once before WasmRoom.open. Node: bytes are read from the package. Browser/bundler: the wasm is fetched. Pass moduleOrPath to override (a WebAssembly.Module, URL, or bytes).

export declare function initRoomWasm(moduleOrPath?: unknown): Promise<void>;

WasmRoom

ClassDeclaration · Source: packages/room/pkg/rindle_room.d.ts:11 · Supporting declarations

One room instance: the upstream-fed base store plus its downstream serving state (materialized queries deduped by QueryKey, subscribers addressed by the host's opaque keys) and — once enableWrites runs — the §5.1 write plane, with at most one mutation transaction open at a time (the room is an actor; the host serializes mutations onto it).

/* tslint:disable */
/* eslint-disable */
/**
 * One room instance: the upstream-fed base store plus its downstream serving state
 * (materialized queries deduped by `QueryKey`, subscribers addressed by the host's
 * opaque keys) and — once [`enableWrites`](Self::enable_writes) runs — the §5.1
 * write plane, with **at most one mutation transaction open at a time** (the room is
 * an actor; the host serializes mutations onto it).
 */
export class WasmRoom {
    private constructor();
    free(): void;
    [Symbol.dispose](): void;
    /**
     * Advance the ledger rows for journal-committed mutations — **the ack** (§5.1
     * step 4; call once the journal append resolves). `entries_json` is a JSON array
     * of `{clientID, mid}`. Returns `{"headCv": n}` — drain
     * [`commitAll`](Self::commit_all) to ship the lmid frames — or `{"headCv": null}`
     * when everything was already covered.
     */
    ack(entries_json: string): string;
    /**
     * The ledger row's current value for `clientID` (0 if none) — what the wire has
     * confirmed.
     */
    ackedLmid(client_id: string): number;
    /**
     * The highest mid applied to the head for `clientID` (0 if none) — the dedup
     * watermark; diagnostics and the crash-replay tests read it.
     */
    appliedMid(client_id: string): number;
    /**
     * Apply one upstream `nbatch` frame's `batch` object (JSON text). Returns a status
     * object (JSON text): `{applied: "snapshot", rows}` | `{applied: "live", ops}` |
     * `{applied: "duplicate"}` | `{applied: "staleEpoch", expected, got}`. Throws when
     * the frame is garbage or the apply poisons the store — in both cases the host
     * tears down and re-subscribes under a new epoch (§3.4); there is no repair call.
     *
     * After a `live`/`snapshot` apply, drain the fan-out with
     * [`commitAll`](Self::commit_all).
     */
    apply(batch_json: string): string;
    /**
     * Build the §5.3 net-effect batch from the dirty entries + ledger co-edits.
     * Returns `undefined` when there is nothing to flush, else JSON text
     * `{changes, batchHash, lmids}`: `changes` is the `/apply-row-change-txn`
     * `changes[]` array (ingest shape, old-images = the CAS base chain), `batchHash`
     * the batch identity computed over its canonical bytes, `lmids` the
     * `{clientID, mid}` advances the batch covers. At most one flush may be in
     * flight — resolve with [`flushOk`](Self::flush_ok) or
     * [`flushConflict`](Self::flush_conflict); retries resubmit the SAME journaled
     * body, never a rebuilt one.
     */
    beginFlush(): string | undefined;
    /**
     * Open the transaction for `(clientID, mid)`. Returns `{"begin": "tx"}` (run the
     * mutator, then [`commitMutation`](Self::commit_mutation) or
     * [`rejectMutation`](Self::reject_mutation)) or `{"begin": "dedup"}` (an absorbed
     * redelivery — send nothing). Throws on a mid gap with the exact
     * `mutation gap for …` message the client's recovery keys on — forward it on an
     * `error` frame. At most one transaction may be open.
     *
     * `name`/`args_json` (optional, Slice I-ii) are the wire envelope's mutator name
     * and JSON-text args: should this mid end non-applied, its durable outcome row
     * echoes them on a DEOPT (self-contained re-invoke, mirroring the H-iv-b frame).
     * Omitting them degrades deopt rows to NULL name/args, nothing else.
     */
    beginMutation(client_id: string, mid: number, name?: string | null, args_json?: string | null): string;
    /**
     * Drain every materialized query once and return the fan-out as JSON text:
     * `[{sub, batch}, …]` — one entry per attached subscriber per query with a
     * non-empty net delta, each `batch` stamped with that subscriber's own epoch/seq.
     * Empty array when nothing changed (or the store is no longer live — a dead
     * incarnation must not ship a torn frame).
     */
    commitAll(): string;
    /**
     * Apply the open transaction to the head as one local commit: dirty entries are
     * captured, the applied watermark advances, and every attached query sees the ops.
     * Returns `{"headCv": n}` — drain [`commitAll`](Self::commit_all) and fan out NOW
     * (§5.1 step 2: data fanout is never gated on durability), then journal the
     * envelope and [`ack`](Self::ack) once the append commits. Throws only when the
     * commit tears the head (store poisoned — tear down).
     *
     * Under [`enableWritesV2`](Self::enable_writes_v2) the §3.3 commit gate runs
     * first; a containment violation returns `{"deopt": {reason, table, pk, …}}`
     * instead (`reason`: `"writeOutOfScope"` (+ `op`) | `"joinKeyChanged"`
     * (+ `column`) | `"absentReadUnproven"`): **nothing was applied**, the tx is
     * consumed and the mid burnt exactly like [`rejectMutation`](Self::reject_mutation)
     * (do NOT call it too) — journal the envelope as rejected and [`ack`](Self::ack)
     * as usual, answering the client with a deopt. Under the v1 enable the return is
     * always `{"headCv": n}`, byte-identical to before.
     */
    commitMutation(): string;
    /**
     * The last-applied upstream commit version (`undefined` before the seq-0 snapshot).
     * This is the journal cursor's `cv` half — persist `(epoch, cv)` to resume (§3.3).
     */
    cv(): number | undefined;
    /**
     * How many `(table, pk)` keys are dirty (§5.3 — P3's flush input).
     */
    dirtyLen(): number;
    /**
     * The highest mid the write authority has committed for `clientID` (0 if none) —
     * §8.1's `durable` level.
     */
    durableLmid(client_id: string): number;
    /**
     * Enable the §5.1 write plane over a live store: `owned_json` is a JSON array of
     * the tables mutators may write (§3.2's owned set — must all be in the upstream
     * hello). Registers the `_rindle_client_mutations` ledger; call once, right after
     * the seq-0 snapshot applies and before serving. Idempotence is deliberate-ly NOT
     * provided: enabling twice is a shell bug and throws.
     */
    enableWrites(owned_json: string): void;
    /**
     * Enable the write plane with per-table **scope specs** — the §3.3 room commit
     * gate (H-iv-a). `specs_json` is a JSON array of
     * `{ table, footprintWhere?, writable }` where `writable` is the lease block's
     * `RoomTableSpec.writable` shape (`{kind:"none"}` for a context table,
     * `{kind:"predicate", where?, joinKeyCols}` for a writable one) and
     * `footprintWhere` is the footprint's row-local wire `Condition` for the table
     * (drives the absent-read proof). Predicates compile NOW, loudly — a malformed or
     * non-row-local spec (e.g. a `correlatedSubquery`) throws and nothing is enabled.
     * With the gate armed, [`commitMutation`](Self::commit_mutation) can return a
     * `{"deopt": …}` verdict. Same once-only/live-store rules as
     * [`enableWrites`](Self::enable_writes), which remains the legacy table-granular
     * entry (its gate proves nothing and never deopts).
     */
    enableWritesV2(specs_json: string): void;
    /**
     * The upstream subscription epoch this store was opened under.
     */
    epoch(): number;
    /**
     * The authority rejected the in-flight batch on CAS (§5.4 `flush_conflict`):
     * `conflicts_json` is its `409` body's `conflicts` array —
     * `[{table, pk, current}]`, `current: null` for an absent row. Each conflicted
     * key converges to the authority's image (the local net effect is dropped);
     * everything else stays dirty and retries next flush. Returns
     * `{"headCv": n | null}` — drain [`commitAll`](Self::commit_all) after a
     * non-null cv to ship the corrective frames.
     */
    flushConflict(conflicts_json: string): string;
    /**
     * Whether a §5.3 flush is in flight (diagnostics; the shell also guards).
     */
    flushInFlight(): boolean;
    /**
     * The authority committed the in-flight batch (§5.3 step 6): consumed entries
     * retire (or re-base onto the image just written, if re-dirtied mid-flight),
     * durable watermarks advance, `pending ≤` them retires. Returns
     * `{"retired": n, "dirty": n}` — a non-zero `dirty` means writes landed during
     * the flight; schedule the next flush.
     */
    flushOk(): string;
    /**
     * The room's own commit order — what downstream frames are stamped with and what
     * the shell's `progress {cvMin}` release points are computed from. Advances on
     * every upstream apply and every local commit (see `RoomStore::head_cv`).
     */
    headCv(): number;
    /**
     * Baseline present and not poisoned — the store is serving.
     */
    isLive(): boolean;
    /**
     * A failed apply left this incarnation dead (§3.4): tear down, re-subscribe.
     */
    isPoisoned(): boolean;
    /**
     * Subscribe `sub` to the reserved per-client lmid query (`_rindle/clientLmid`):
     * the room composes the `_rindle_client_mutations WHERE client_id = <clientID>`
     * AST itself — identity comes from the connection's `init`, never client args.
     * Same return shape and envelope rules as [`subscribe`](Self::subscribe).
     */
    lmidSubscribe(sub: string, epoch: number, client_id: string, now_ms: number): string;
    /**
     * How many downstream queries are currently materialized (post-dedup).
     */
    materializationCount(): number;
    /**
     * Open the room's base store from the upstream `nhello` frame's `hello` object
     * (JSON text). `idle_ttl_ms` is the downstream retention grace: a materialized
     * query with no subscribers for that long is reclaimed by [`sweep`](Self::sweep).
     * Rejects malformed hellos loudly — nothing is constructed.
     */
    static open(hello_json: string, idle_ttl_ms: number): WasmRoom;
    /**
     * Applied-but-not-retired mutations (everything, until P3's write-behind).
     */
    pendingLen(): number;
    /**
     * Drop the open transaction's staged ops and consume its mid anyway — the reject
     * path (unknown mutator, mutator threw, staging refusal, a replayed non-applied
     * journal entry). The stream stays contiguous; the eventual [`ack`](Self::ack)
     * advances the ledger with no effects, snapping the author's prediction back.
     *
     * `kind` (`"rejected"` (default) | `"deopt"`) + `reason` are the shell's H-iv-b
     * classification of the verdict: the outcome is RECORDED (Slice I-ii) and its
     * durable row rides the next flush beside the covering lmid co-edit — one
     * authority transaction, so a post-downgrade client resolving through the daemon
     * never reads a burnt non-applied mid as applied. A deopt row echoes the
     * [`beginMutation`](Self::begin_mutation) envelope's `name`/`args`.
     */
    rejectMutation(kind?: string | null, reason?: string | null): void;
    /**
     * Seed the durable watermarks from the write authority's ledger — the boot probe
     * (§3.3; T2's committed-before-crash row). Call after [`enableWrites`] and
     * **before** the journal replay: seeded mids replay as dedup instead of
     * re-invoking. `seeds_json` is a JSON array of `{clientID, lmid}`. Returns
     * `{"headCv": n | null}` — the ledger rows ride a local commit so the client's
     * lmid slice confirms them.
     *
     * [`enableWrites`]: Self::enable_writes
     */
    seedDurable(seeds_json: string): string;
    /**
     * Materialize-on-presentation (§10.1): attach subscriber `sub` (the host's opaque
     * routing key) at `epoch` to the query for this approved wire `Ast` (JSON text) —
     * reusing the pipeline on a `QueryKey` hit. Returns
     * `{queryKey, reused, hello, snapshot}` (JSON text): send `nhello(hello)` then
     * `nbatch(snapshot)` (its `seq` is 0), then this subscriber's entries from each
     * [`commitAll`](Self::commit_all). Re-subscribing an existing `sub` replaces its
     * envelope — pass the bumped `epoch`, exactly as before.
     */
    subscribe(sub: string, epoch: number, ast_json: string, now_ms: number): string;
    /**
     * How many downstream subscribers are currently attached.
     */
    subscriberCount(): number;
    /**
     * Reclaim downstream queries idle past their grace window, on the host's clock.
     * Returns how many were destroyed.
     */
    sweep(now_ms: number): number;
    /**
     * Stage an add of a full-width row (JSON-array text). Clean refusal (throw, head
     * untouched) when the key exists, the table is not owned, or the width is wrong —
     * catch it and reject the mutation.
     */
    txAdd(table: string, row_json: string): void;
    /**
     * Stage an edit to a full-width row (JSON-array text) keyed by its pk cells. The
     * shell resolves partial updates against [`txGet`](Self::tx_get) first — only
     * concrete cells cross this boundary (JSON has no `undefined`). The pk must not
     * change; the row must exist.
     */
    txEdit(table: string, row_json: string): void;
    /**
     * The effective row for `pk_json` (a JSON array of pk cells, `primaryKey` order):
     * the live head under this transaction's own staged writes — read-your-writes for
     * read-dependent mutators, and what the keyed `update`/`delete`/`upsert` layers
     * probe before composing their writes. Returns the row as JSON-array text, or
     * `undefined` when absent.
     */
    txGet(table: string, pk_json: string): string | undefined;
    /**
     * Stage a remove of the row keyed `pk_json` (JSON array of pk cells). The change
     * is composed from the effective row; a missing key is a clean refusal (the keyed
     * `delete` layer no-ops before calling this).
     */
    txRemove(table: string, pk_json: string): void;
    /**
     * Detach subscriber `sub` (unsubscribe, socket close, lease expiry, revocation —
     * the host decides why). Idempotent: returns whether it was attached. Its query
     * stays materialized for `idle_ttl_ms` (a quick re-subscribe is cheap), then
     * [`sweep`](Self::sweep) reclaims it.
     */
    unsubscribe(sub: string, now_ms: number): boolean;
}