Rindle

API index and search · Build metadata

Supporting declarations

packages/wasm/src/index.ts. These declarations explain referenced types. Only package-page symbols are package exports.

Exact source

WasmWriteTxn

/** A raw staged write transaction over the wasm engine — the surface an optimistic client
 *  mutator runs against (`get` reads the live state under this txn's staged overlay, so a
 *  read-dependent mutator sees its own writes; OPTIMISTIC-WRITES-DESIGN.md §4.1). */
export interface WasmWriteTxn {
    add(table: string, row: unknown[]): void;
    remove(table: string, row: unknown[]): void;
    edit(table: string, oldRow: unknown[], newRow: unknown[]): void;
    get(table: string, pk: unknown[]): unknown[] | undefined;
    /** Run a one-shot query over the state this txn is mutating — the live base plus this
     *  txn's own staged writes-so-far (read-your-writes; 203-MUTATOR-READS-DESIGN.md §5.2).
     *  Synchronous (over a lazy read-cache fork of the staged buffer). Returns the query's rows
     *  as keyed objects with their materialized `related` children nested by name (identical in
     *  shape to a `view.data` row), in the query's order. */
    query(ast: Ast): unknown[];
    commit(): Array<{
        queryId: number;
        events: unknown[];
    }>;
    rollback(): void;
}

ServerDeltaOp

/** One base-table row op of a coherent server delta (the §1.3 `D`), bare cells. */
export type ServerDeltaOp = {
    table: string;
    type: "add";
    row: unknown[];
} | {
    table: string;
    type: "remove";
    row: unknown[];
} | {
    table: string;
    type: "edit";
    row: unknown[];
    old: unknown[];
};

initWasm

/** Initialize the wasm module (idempotent). Call once at startup before `new WasmBackend`
 *  / `createWasmStore`. Browser/bundler: no args (the wasm is fetched). Node: the bytes are
 *  read from the package. Pass `moduleOrPath` to override (a `WebAssembly.Module`, URL, or bytes). */
export declare function initWasm(moduleOrPath?: unknown): Promise<void>;

WasmBackend

export declare class WasmBackend<S extends ColsMap> implements Backend {
    private readonly db;
    private handler;
    private boundaryHandler;
    /** Local-only table names (`201-LOCAL-ONLY-TABLES-DESIGN.md` §4): registered UNTRACKED (so the
     *  optimistic rewind never reverts them) and the only tables {@link writeLocal} accepts. */
    private readonly localTables;
    private readonly dispatchQueue;
    private draining;
    constructor(schema: Schema<S>);
    /** Register an additional base table after construction — for a SYNTHETIC aggregate table
     *  (`AGGREGATE-SYNC-DESIGN.md` §3.3) that is not in the typed schema. The
     *  `NormalizedBackend` registers each such `__agg_*` table once, before a query that reads
     *  it, so the local engine can join to it (the relationship `count` it backs is shipped by
     *  the server, never recomputed). Always synced (tracked) — synthetic tables are never local. */
    registerTable(name: string, spec: {
        columns: string[];
        primaryKey: number[];
    }): void;
    /** Direct-commit a batch of LOCAL-only writes (`201-LOCAL-ONLY-TABLES-DESIGN.md` §6): push them
     *  straight through the engine on the ordinary delivery path, OUTSIDE any optimistic cycle (a
     *  local table is untracked, so it never rebases). Rejects a synced/tracked table (M2).
     *  `onCommitted` fires between the engine commit and subscriber delivery ({@link writeWith}) —
     *  the post-commit anchor the persistence tap needs (207 §5.1). */
    writeLocal(mutations: Mutation[], onCommitted?: () => void): void;
    /** Remove a synthetic aggregate table registered by {@link registerTable}, once the last
     *  query reading it has been unregistered (`AGGREGATE-SYNC-DESIGN.md` §4): frees the engine
     *  source + its optimistic baseline so aggregate state is reclaimed, not permanent. Throws
     *  if a query still reads it (the backend refcounts readers, so it calls this only at 0). */
    unregisterTable(name: string): void;
    registerQuery(qid: QueryId, ast: Ast): void;
    unregisterQuery(qid: QueryId): void;
    mutate(mutations: Mutation[]): Promise<void>;
    onEvent(handler: (qid: QueryId, ev: ChangeEvent) => void): void;
    /** Register the Store's commit-boundary handler ({@link Backend.onCommitBoundary}): `dispatch`
     *  calls it around each commit's per-query batch delivery so the Store can fold every affected
     *  view before notifying any subscriber. */
    onCommitBoundary(handler: (phase: "begin" | "end") => void): void;
    /** Deliver one commit's per-query batches. Non-reentrant (#15): if a delivery is already in
     *  progress (a subscriber re-entered via write()), enqueue and let the active drain pick it
     *  up FIFO, so each query folds commits in order. Per-query isolated (#11): a view's fold or
     *  subscriber throwing does NOT drop sibling queries' batches — the first error is re-raised
     *  only after every query has been delivered.
     *
     *  Cross-view-atomic notification: each commit is bracketed with `boundaryHandler("begin"/"end")`
     *  so the Store folds ALL of this commit's views before notifying ANY subscriber (a subscriber
     *  re-reading a sibling view then sees post-commit data). `begin`/`end` stay balanced even if a
     *  fold throws (the `finally`), and a re-entrant write enqueued during the `end` flush drains as
     *  its own bracketed commit in the next loop turn — preserving per-query commit order (#15). */
    private dispatch;
    /** Run `f` against a raw staged write txn (with the §4.1 `get` read path), commit, and
     *  dispatch the resulting batches on the ordinary event stream. Inside an open server
     *  batch the engine buffers the events into the cycle instead (commit returns `[]`),
     *  so re-invocations dispatch nothing here — delivery is `serverBatchEnd`'s.
     *
     *  `onCommitted` runs after `tx.commit()` returns but before `dispatch` delivers to
     *  subscribers: a throw from `f` (pre-commit — engine untouched) skips it; a subscriber
     *  throw re-raised by `dispatch` happens after it. It is the only point where "the commit
     *  is applied" is knowable to a caller that must not confuse the two failure modes. */
    writeWith(f: (tx: WasmWriteTxn) => void, onCommitted?: () => void): void;
    /** Open a §1.3 reconcile cycle against the coherent server delta: the engine rewinds every
     *  tracked table (optimistic layer un-applied, delta folded in, each table's baseline re-forked)
     *  and starts buffering. Re-invoke the still-pending mutators via {@link writeWith}, then call
     *  {@link serverBatchEnd}. On error the rebase state is poisoned — discard the backend and
     *  re-hydrate. */
    serverBatchBegin(deltas: ServerDeltaOp[]): void;
    /** Close the cycle: the whole buffered stream (rewind + re-invocations) coalesces to
     *  the minimal net per query (§3 — a confirmed-correct prediction delivers nothing)
     *  and dispatches as ONE batch per affected query on the ordinary event stream. */
    serverBatchEnd(): void;
}

createWasmStore

/** Convenience: init the wasm + return a ready local {@link Store}. */
export declare function createWasmStore<S extends ColsMap>(schema: Schema<S>): Promise<Store<S>>;