Skip to content

SyncClient

Defined in: packages/client/src/index.ts:1358

TRegistry extends SyncTableRegistry

appendEvent: (stream, payload) => Promise<EventAppendResult>

Defined in: packages/client/src/index.ts:1444

Append one client event to the Outbox (ADR-0053 decision 2) — the Event lane’s entry point, and the only way an app produces an event. Fire-and-forget by design: nothing echoes back, nothing is overlaid, nothing converges. The promise resolves on DURABLE local enqueue under the store’s declared durability, NOT on delivery; the flush loop drains the Outbox in the background (and after reconnect/boot), and the server’s per-event verdicts surface on onEventLaneReport.

Four refusals, all synchronous call-site failures rather than runtime conditions — the invariant “everything in the Outbox is well-formed” is what the flush loop and any best-guess view lean on:

The library stamps eventId (uuid — the server’s dedupe key, which is what makes at-least-once delivery idempotent end-to-end) and occurredAtUs, and returns both plus the local append ordinal.

stream/payload are typed as string/unknown: a registry’s Event streams ride a symbol and are type-erased by defineSyncRegistry’s return type, so the REGISTERED ZOD SCHEMA is the enforced contract (at append, and again at ingest for non-library callers).

string

unknown

Promise<EventAppendResult>


bootReport: () => Promise<BootReport | null>

Defined in: packages/client/src/index.ts:1697

Boot observability (ADR-0034): the engine’s most recent COMPLETED boot report, or null before the first boot finalizes (and after a stop()/destroy() that preceded initial sync). Pull — so a late-attaching tab can read a boot that predates it; in worker mode it round-trips to the worker’s stored report. The push counterpart is the onBootReport client option.

Promise<BootReport | null>


destroy: (options?) => Promise<void>

Defined in: packages/client/src/index.ts:1411

Wipe the entire local store (synced cache + overlay + journal + Outbox) and close the handle (ADR-0005). Refuses if mutations are still owed to the server — OR if the Outbox still holds staged events (ADR-0053 decision 8: the same “never discard without a server verdict” rule the owed-mutations refusal upholds) — unless force is set, so it never silently drops un-flushed writes or un-delivered events. The refusal names which of the two blocked it. Distinct from stop(), which only halts sync. Runs under the single lifecycle slot (ADR-0035 decision 4): a concurrent export — or another destroy/discardEphemeral/dropReadCache — rejects with a LifecycleBusyError rather than interleaving the wipe with a running export.

boolean

Promise<void>


desync: (key) => Promise<void>

Defined in: packages/client/src/index.ts:1615

Revert a lazy relation to dormant (ADR-0021 §2) — the inverse of on-demand activation: stop its consistency group’s stream, clear any persisted lazy + persistent activation (so the next boot holds it dormant again), and clean-truncate its local read cache. A later reference re-activates it from scratch. Refuses when the relation is eager (always-on, would immediately re-sync) or owes the server unsettled writes (the truncate would drop them — flush or discard first). The reclaim primitive a host wires to navigation/idle for a rarely-opened lazy view; for an ephemeral relation, idle-eviction is otherwise automatic at session end.

SyncTableName<TRegistry>

Promise<void>


diagnostics: (table?) => Promise<{ mutation: MutationDiagnostics; outbox?: OutboxStatus; }>

Defined in: packages/client/src/index.ts:1527

The store’s owed-state diagnostics: the mutation journal’s per-status counts, plus — when this client has an Event lane — the Outbox’s drain signal (ADR-0053 decision 8: the Event lane’s durable state takes a position on every lifecycle surface). outbox is the boolean signal rather than a count, for the reason onOutboxStatus carries none; it is absent on a client with no lane.

SyncTableName<TRegistry>

Promise<{ mutation: MutationDiagnostics; outbox?: OutboxStatus; }>


discardConflict: <TKey>(table, entityKey) => Promise<void>

Defined in: packages/client/src/index.ts:1505

Discard a conflicted entity (ADR-0015): clear its conflicted journal entry and kept optimistic Overlay, so the Read model falls back to the synced (server) value. Use when the user abandons a stale edit instead of resolving it as a new write.

TKey extends string

TKey

Record<string, string>

Promise<void>


discardEphemeral: (key) => Promise<void>

Defined in: packages/client/src/index.ts:1633

Drop an ephemeral relation’s local rows and revert it to dormant (ADR-0021) — the narrow, scoped twin of desync. It runs the identical group-teardown machinery (stop the group stream, clear the persisted lazy activation, reset the persisted subscription, clean-truncate every member), but under a STRICTER gate: EVERY member of the relation’s consistency group must be retention: "ephemeral" — it refuses (naming the offender) if any member is persistent. Where a desync from one tab reverts the shared group for every attached tab (the SharedWorker footgun), discardEphemeral is safe under multi-tab because an ephemeral window is per-delivery-session and inherently single-consumer — nothing durable, and no other tab, depends on it. Refuses an eager relation (always-on, would immediately re-sync) and a group that owes the server unsettled writes, exactly as desync does. The finalize primitive for a secure-delivery window: drop the local rows at session end without touching a durable relation. Note the drop is local-lifecycle only: a later re-subscription re-activates the lazy group and re-streams whatever the SERVER still serves — post-finalize non-redelivery is the server gate’s guarantee (e.g. a consumed server-owned cursor), not this method’s. Runs under the single lifecycle slot (ADR-0035 decision 4): a concurrent export (or destroy/dropReadCache) rejects with a LifecycleBusyError rather than interleaving the cache truncate with a running export.

SyncTableName<TRegistry>

Promise<void>


discardQuarantined: <TKey>(table, entityKey) => Promise<void>

Defined in: packages/client/src/index.ts:1517

Discard a quarantined entity (ADR-0006): clear its quarantined journal entry and kept optimistic Overlay, so the Read model falls back to the synced (server) value. The rollback path for a write the server permanently rejected — e.g. an RLS policy denial (42501) routed to quarantine. After the discard the phantom optimistic row is gone and the entity accepts new mutations again (no longer blocked behind the quarantined head). Symmetric to SyncClient.discardConflict; the overlay is kept when another still-owed write depends on it. No-op for an entity with no quarantined entry.

TKey extends string

TKey

Record<string, string>

Promise<void>


drizzle: PgliteDatabase<ExtractTablesWithRelations<{ }, RegistryTables<TRegistry>>>

Defined in: packages/client/src/index.ts:1359


dropReadCache: () => Promise<void>

Defined in: packages/client/src/index.ts:1421

Drop and rebuild the reconstructible synced read cache, preserving the overlay, the mutation journal, and the Outbox (ADR-0006; ADR-0053 decision 8 — the Outbox is not read cache, so this never touches it). The next sync refills it. Use to recover from a corrupt or stale read cache without losing un-flushed writes. Runs under the single lifecycle slot (ADR-0035 decision 4) — it drops and rebuilds the synced tables, so an export must not capture a half-rebuilt cache; a concurrent export (or destroy/discardEphemeral) rejects with a LifecycleBusyError.

Promise<void>


ensureSynced: (keys) => Promise<void>

Defined in: packages/client/src/index.ts:1600

Activate one or more lazy relations (ADR-0021): open their consistency-group subscription if held out of the eager boot, resolving once each group’s STREAM IS STARTED — reads are then tripwire-safe, but the initial catch-up may still be in flight (local rows can be legitimately empty/stale until it lands; await groupReady per relation for catch-up completion — deliberately separate so an offline client still reads its persisted local rows instead of hanging on the network). Idempotent — eager or already-started relations resolve immediately. Use to pre-activate before a raw/client.drizzle read, or as the manual escape hatch the tripwire points to.

readonly SyncTableName<TRegistry>[]

Promise<void>


exportData: (options?) => Promise<DataExportResult>

Defined in: packages/client/src/index.ts:1750

Take a data export (ADR-0035): the PORTABLE artefact — the synced tables and the enum types they depend on, schema + data, nothing of pgxsinkit’s machinery — as SQL loadable into a vanilla Postgres. It is a generated enum DDL header concatenated ahead of pg_dump -t <table> ... --no-owner (one -t per physical synced table; ephemeral/read-projection entries excluded by construction), run against the same memory-backed THROWAWAY clone the diagnostic dump uses — so the live engine is never touched.

Unlike the other two exports it GUARDS the journal (decision 3): a strict export requires a DRAINED journal — all mutation counts zero, including acked writes whose synced echo has not landed (they live only in the Overlay). The drain flushes drainable rows and awaits convergence up to drainJournal.timeoutMs (default 15_000); non-drainable states (failed/quarantined/conflicted) fail FAST with a DataExportDrainError carrying the diagnostics. drainJournal: false is the escape hatch — export synced state as-is (unflushed writes absent; report.escapeHatch records it). An offline device with a clean journal exports strictly and instantly; one with a dirty journal cannot produce a strict export (its lossless option is exportStore).

Awaits engine-ready rather than rejecting during boot, then runs the whole drain+dump under the single lifecycle slot — a concurrent export (or destroy/discardEphemeral) rejects with a LifecycleBusyError. Resolves to the SQL File (application/sql) plus a DataExportReport (drain + clone-pipeline phase timings, the applied -t table list, and the escape-hatch flag).

DataExportOptions

Promise<DataExportResult>


exportDiagnostics: (options?) => Promise<DiagnosticExportResult>

Defined in: packages/client/src/index.ts:1728

Take a diagnostic dump (ADR-0035): human-readable SQL of EVERYTHING the store holds — synced tables, the _overlay/_mutations journal (unflushed writes included — the evidence a diagnostic exists for), the pgxsinkit metadata schema, the read-model views, and the reconcile functions/triggers — via pg_dump. To keep pg_dump’s DEALLOCATE ALL away from the live engine, the dump runs against a memory-backed THROWAWAY clone booted from a live datadir dump (ADR-0035 addendum): the running store is never suspended and no tab is disrupted. Awaits engine-ready rather than rejecting during boot, then runs under the single lifecycle slot — a concurrent export (or destroy/discardEphemeral) rejects immediately with a LifecycleBusyError. Resolves to the SQL File (application/sql) plus a DiagnosticDumpReport (phase timings + a diagnostics snapshot). Active ephemeral (pg_temp) clusters are absent by construction (ADR-0035 decision 5 — pg_dump ignores temp objects).

DiagnosticExportOptions

Promise<DiagnosticExportResult>


exportStore: (options?) => Promise<StoreExportResult>

Defined in: packages/client/src/index.ts:1715

Take a store backup (ADR-0035): a full-fidelity, PGlite-restorable tarball of the whole local store — synced cache, Overlay, and Mutation journal (unflushed writes included) — via PGlite’s dumpDataDir. Taken LIVE (a CHECKPOINT serialised behind engine work, then the dump; no engine suspension, no tab disruption), so it never blocks and is the only lossless export an offline device with unflushed writes can take. Awaits engine-ready rather than rejecting during boot, then runs under the single lifecycle slot: a second export (or, later, destroy/discardEphemeral) attempted while one is in flight rejects immediately with a LifecycleBusyError — retry once it settles. Resolves to the artefact File plus an ExportReport (phase timings + a diagnostics snapshot).

StoreExportOptions

Promise<StoreExportResult>


flush: (table?) => Promise<void>

Defined in: packages/client/src/index.ts:1482

SyncTableName<TRegistry>

Promise<void>


flushEvents: () => Promise<void>

Defined in: packages/client/src/index.ts:1453

Drain the Outbox now — the Event lane’s manual primitive, the twin of flush. Assembles batches in append (seq) order across every Event stream, POSTs them, and applies the per-event verdicts, until nothing more is eligible this pass. A no-op while the lane is in batch-level backoff, and a no-op for a registry with no Event streams. With autoSync installed the lane drives itself (appends nudge a pass, an interval is the fallback, and boot/reconnect drain what was written offline); this is the escape hatch for a fully-manual host.

Promise<void>


groupReady: (table) => Promise<void>

Defined in: packages/client/src/index.ts:1669

Per-group readiness (ADR-0032 decision 6): a promise resolving the moment the given table’s consistency group is up-to-date. Resolves immediately for an already-ready (or sync-disabled) group; stays pending for a still-dormant lazy relation until it is activated and caught up. The opt-in progressive-paint signal beside the all-eager-groups ready gate. status.groups carries the same readiness as a synchronous snapshot.

SyncTableName<TRegistry>

Promise<void>


haltActivity: () => void

Defined in: packages/client/src/index.ts:1399

Synchronously abort all sync/write activity (in-flight write fetches, shape-stream long-polls, convergence scheduling) without awaiting. Idempotent. The first action of every teardown path — stop()/destroy() call it, and the SharedWorker host calls it before draining subscribes / disposing live queries so no teardown step races a still-live engine. Not a substitute for stop()/destroy(): the awaited teardown (unsubscribe, dispose, pglite.close) still follows. Callers rarely invoke it directly.

void


hydratingTablesFor: (query) => readonly string[]

Defined in: packages/client/src/index.ts:1679

The referenced consistency groups’ member tables that are NOT YET caught up at call time (ADR-0021 / ADR-0032 decision 6): scan the compiled SQL for every synced relation the query reads (∪ use), map each to its consistency group, and return those whose group has not completed its initial catch-up. Empty when sync is disabled OR every referenced group is already ready — the steady-state fast path in which the live-rows seam builds no hydrated promise. The seam (and the worker bridge) use this to gate hydrating uniformly across eager AND lazy groups; ACTIVATION is separate and stays lazy-only. Returns plain table-name strings (not keyof TRegistry) to keep the client covariant in its registry.

string

readonly string[]

readonly string[]


isSynced: (key) => boolean

Defined in: packages/client/src/index.ts:1605

Whether a relation’s group has started and hydrated (ADR-0021). False for a still-dormant lazy relation; true for eager relations once boot completes (and always when sync is disabled).

SyncTableName<TRegistry>

boolean


liveQueryDiagnostics: () => Promise<LiveQueryDiagnostics[]>

Defined in: packages/client/src/index.ts:1704

Live-query diagnostics (ADR-0040 decision 5): a point-in-time snapshot of the live-query manager’s entries — opaque fingerprint digests plus counts/timings only, NEVER SQL, params, or row values. Both client forms return the real snapshot: in WORKER mode this pulls the worker manager’s snapshot over the bridge; the IN-PROCESS client returns its own manager’s snapshot directly.

Promise<LiveQueryDiagnostics[]>


localReadReady: Promise<void>

Defined in: packages/client/src/index.ts:1373

Local-read readiness (ADR-0041): resolves once PGlite is open, the durable schema is ready, registry reconciliation has completed, and the drizzle read facade is built — so cached rows are queryable. Resolving this stage requires NO write runtime, NO sync start, and NO network I/O, so an offline boot resolves it promptly. Under the ADR-0041 Option B contract createSyncClient() (and, in stage 2, attachSyncClient()) resolves at exactly this stage; the write and sync tail continues in the background. Monotonic and idempotent.


mutate: object

Defined in: packages/client/src/index.ts:1487

batch: (items) => Promise<void>

readonly MutationBatchItem<TRegistry>[]

Promise<void>

create: <TKey>(table, input) => Promise<void>

TKey extends string

TKey

SyncTableCreateInput<TRegistry, TKey>

Promise<void>

delete: <TKey>(table, entityKey) => Promise<void>

TKey extends string

TKey

Record<string, string>

Promise<void>

update: <TKey>(table, entityKey, patch) => Promise<void>

TKey extends string

TKey

Record<string, string>

SyncTableUpdateInput<TRegistry, TKey>

Promise<void>


mutations: MutationsApi<TRegistry>

Defined in: packages/client/src/index.ts:1538

The registry-wide reactive mutation-status surface: a global per-status summary and a filtered normalized detail list over EVERY writable journal, each available one-shot or as a live subscription. Identical on the in-process and worker-attached client. Render a global sync indicator with ONE subscribeSummary instead of one journal live query per writable table; consumers never touch the generated journal relation names. See MutationsApi.


onEventLaneReport: (listener) => () => void

Defined in: packages/client/src/index.ts:1481

The Event lane’s verdict/report surface (ADR-0053 decision 2): per flush pass, the TERMINAL non-acked verdicts (refused — the server’s gating hook said no; rejected — a schema-invalid or oversized payload for a KNOWN stream), the deferred ones (an Event stream the server does not yet know — ordinary rollout skew; the rows stay and retry), and the batch-level backoff transitions. acked is not reported: a high-volume append-only lane would drown the app in its own success.

An EPHEMERAL subscription, deliberately — a durable client-side verdict table would be retention-bearing state for a debugging need. With nothing subscribed the library logs each report at warn level rather than dropping it, because once a terminal row is deleted the Outbox cannot answer what happened to it.

(report) => void

() => void


onOutboxStatus: (listener) => () => void

Defined in: packages/client/src/index.ts:1463

The drain signal (ADR-0053 decision 2): subscribe to the Outbox’s empty ↔ non-empty transitions, with the CURRENT state delivered on subscribe. Returns an unsubscribe.

The invalidation hook for a best-guess view that composes pending events with down-synced aggregates: when the Outbox drains, the aggregate is authoritative again. Deliberately carries no count — a count that updates only on transitions is stale by construction, and one that updates per append is a worse live query; for richer detail, query the Outbox table (getOutboxTable(registry)).

(status) => void

() => void


outboxStatus: () => Promise<OutboxStatus>

Defined in: packages/client/src/index.ts:1469

The drain signal as a one-shot READ — the pull twin of onOutboxStatus’s push (the bootReport pattern). Reads the store, so it is always current: a tab attaching long after the engine’s last transition folds its initial state from here rather than waiting for the next one.

Promise<OutboxStatus>


pglite: ClientPGlite

Defined in: packages/client/src/index.ts:1360


prepareQuery: (input) => Promise<PreparedQueryResult<SyncTableName<TRegistry>>>

Defined in: packages/client/src/index.ts:1645

The read-path safety seam (ADR-0021): scan the compiled sql for the lazy relations it reads (∪ the optional use) and activate them — so a lazy relation auto-activates on any reference (FROM, JOIN, subquery, WHERE). Resolves once it is safe to run the query (streams started, tripwire satisfied) and returns the activated keys (PreparedQueryResult) so a consumer can further await groupReady per key for catch-up completion — the React hooks drive hydrating off exactly that. A backstop throws LazyRelationNotActivatedError only if a referenced relation could not be activated. Exposed for the React live hooks (which own their query build); query/queryRow are the higher-level non-live wrappers. Raw, non-Drizzle SQL is out of scope — pass use, or ensureSynced first.

PrepareQueryInput<TRegistry>

Promise<PreparedQueryResult<SyncTableName<TRegistry>>>


query: <TRows>(build) => Promise<TRows>

Defined in: packages/client/src/index.ts:1575

Run a one-shot (non-live) typed pure-Drizzle query with the lazy-relation safety net (ADR-0021). Pass the builder callback directly — pgxsinkit scans the compiled SQL and activates + awaits every lazy relation it reads (FROM, JOIN, subquery, WHERE) before it runs, and the tripwire rejects any lazy relation the SQL still references but that is not active, so the result is never silently empty/stale. The guaranteed-safe alternative to a bare client.drizzle read. If the builder embeds a raw sql template fragment, use queryRaw and declare the lazy relations in use.

TRows extends readonly unknown[]

GuardedQueryFn<TRegistry, TRows>

Promise<TRows>


queryRaw: <TRows>(spec) => Promise<TRows>

Defined in: packages/client/src/index.ts:1586

query for a builder that embeds a raw sql template fragment (ADR-0021). The compiled-SQL scan can miss a lazy relation named as a bare/unquoted identifier inside raw SQL, so declare those in use — they are activated and awaited before the query runs. Pure-Drizzle reads should use query instead (no use needed).

TRows extends readonly unknown[]

GuardedRawQuerySpec<TRegistry, TRows>

Promise<TRows>


queryRawRow: <TRows>(spec) => Promise<TRows[number] | null>

Defined in: packages/client/src/index.ts:1588

queryRaw returning the first row, or null when empty.

TRows extends readonly unknown[]

GuardedRawQuerySpec<TRegistry, TRows>

Promise<TRows[number] | null>


queryRow: <TRows>(build) => Promise<TRows[number] | null>

Defined in: packages/client/src/index.ts:1577

query returning the first row, or null when empty.

TRows extends readonly unknown[]

GuardedQueryFn<TRegistry, TRows>

Promise<TRows[number] | null>


rawExec: (sql, options?) => Promise<Results[]>

Defined in: packages/client/src/index.ts:1549

rawQuery for multi-statement SQL, returning one Results per statement.

string

RawQueryOptions

Promise<Results[]>


rawQuery: (sql, params?, options?) => Promise<Results>

Defined in: packages/client/src/index.ts:1547

The INSPECTION read surface (debug pages, REPLs, ad-hoc counts) — identical on the in-process and worker-attached client (on the latter the statement runs in the worker). The statement runs raw against the local store: it BYPASSES the mutation journal and optimistic overlay, and any write it issues stays local and will NOT converge. For app data reads prefer the live-rows hooks / subscribeLiveRows (or the guarded query family); reach for this only to look at the store, not to read app state or mutate it.

string

unknown[]

RawQueryOptions

Promise<Results>


readMutationDetails: (table?) => Promise<MutationDetail[]>

Defined in: packages/client/src/index.ts:1486

SyncTableName<TRegistry>

Promise<MutationDetail[]>


ready: Promise<void>

Defined in: packages/client/src/index.ts:1389


reconcile: (table?) => Promise<void>

Defined in: packages/client/src/index.ts:1483

SyncTableName<TRegistry>

Promise<void>


recoverSending: (table?) => Promise<void>

Defined in: packages/client/src/index.ts:1485

SyncTableName<TRegistry>

Promise<void>


retryFailed: (table?) => Promise<void>

Defined in: packages/client/src/index.ts:1484

SyncTableName<TRegistry>

Promise<void>


start: () => Promise<void>

Defined in: packages/client/src/index.ts:1391

Promise<void>


status: SyncRuntimeStatus

Defined in: packages/client/src/index.ts:1390


stop: () => Promise<void>

Defined in: packages/client/src/index.ts:1400

Promise<void>


subscribeLiveRows: <TRow>(input, onRows) => Promise<LiveRowsSubscription<TRow>>

Defined in: packages/client/src/index.ts:1687

The live-rows seam (ADR-0032 S2 §4): register a reactive query and receive its initial ordered snapshot plus subsequent updates via onRows. The React live hooks consume THIS (not pglite.live directly), so they run unchanged against both the in-process client (which implements it over pglite.live) and the worker-attached client (which implements it over the bridge). Prefer the higher-level @pgxsinkit/react hooks; this is the lower-level primitive they build on.

TRow extends Record<string, unknown> = Record<string, unknown>

SubscribeLiveRowsInput

(rows) => void

Promise<LiveRowsSubscription<TRow>>


tables: { [TKey in string]: SyncClientTableHandle<TRegistry, TKey> }

Defined in: packages/client/src/index.ts:1362


transaction: (options, run) => Promise<SyncTransactionResult>

Defined in: packages/client/src/index.ts:1658

Author an atomic write-unit (ADR-0022 §2). The callback receives collecting table handles; every mutation it issues is tagged into one unit and enqueued atomically when the callback returns.

  • mode: "pessimistic"server-authoritative: the unit flush-routes to the authoritative endpoint and this call resolves only once the server has decided. The result’s acks carry each member’s outcome — acked, conflicted (overlay kept, ADR-0015), or rejected (overlay auto-discarded for the whole unit, surfaced via onReject, ADR-0022 §4). Throws on transport failure (overlay kept). A pessimistic block may also issue SyncTransactionTableHandle.updateBlind — an update-by-key with no local base row and no overlay, for a write target excluded from the actor’s read shape.
  • mode: "optimistic" — an atomic batch enqueue that flushes in the background (empty acks).

WriteMode

(tx) => void | Promise<void>

Promise<SyncTransactionResult>


views: RegistryViews<TRegistry>

Defined in: packages/client/src/index.ts:1361


writeReady: Promise<void>

Defined in: packages/client/src/index.ts:1380

Write readiness (ADR-0041): resolves once the mutation runtime is constructed and boot recovery has completed (plus restore quarantine on a restore boot) — enqueue is safe. Every write-path method awaits this internally, so a write issued the instant localReadReady resolves completes once writeReady lands rather than failing opaquely. Resolves with NO network I/O. Monotonic and idempotent.