Skip to content

CreateSyncClientOptions

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

TRegistry extends SyncTableRegistry

optional autoSync?: ConvergenceTrigger

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

Opt-in convergence driver (ADR-0005). Supply a ConvergenceTrigger (e.g. createBrowserConvergenceTrigger()) and the client drives flush/reconcile/retryFailed on the trigger’s schedule, started once sync is ready and stopped on stop()/destroy(). Omit it for fully-manual convergence (the mechanism primitives stay public either way).


optional batchEventUrl?: string

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

The Event lane’s ingestion endpoint (ADR-0053 decision 3) — "/api/events", or an absolute deployment URL ending in it, under the same hard-required-path rule as batchWriteUrl. Omit it and the client DERIVES it from batchWriteUrl (…/api/mutations…/api/events), which is correct for the ordinary deployment where one createSyncServer mounts both; set it explicitly when the two endpoints are not siblings.


batchWriteUrl: string

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


electricUrl: string

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


optional events?: EventLaneOptions

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

The Event lane’s client-level flush policy (ADR-0053): batch caps, the fallback interval, backoff tuning, and per-Event-stream overrides. NEVER on the registry — the registry is the contract, cadence is deployment tuning, and a batch-size tweak must not surface as a registry diff. Client batching is additionally clamped by the contracts-level request-shape limits the server enforces independently.


optional freshStore?: boolean

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

PROVABLY-fresh store hint (ADR-0032 S4 / backlog-0003): the caller guarantees this store is brand-new and schemaless — no prior schema, no synced rows, no persisted subscription state. When set (and sync is enabled, and the client owns schema exec — i.e. not the pgliteInstance path), the shape catch-up is started BEFORE the local boot phases (schema exec, journal recovery, and registry reconciliation) and buffered in memory, with commits gated until those phases finish — so the network catch-up overlaps them instead of running strictly after. On a far-from-database caller this collapses boot from local-phases + catch-up toward max(local-phases, catch-up).

MUST be set only when freshness is proven, never derived by probing — a claimed schemaless spare (the board’s claim path knows: a claimed spare is always fresh; a mapped/returning store never is). A wrong true on a warm store would start the streams from offset 0 and skip the subscription-state read, re-snapshotting instead of resuming. Absent/false → the exact sequential path (the default, correct for every warm store).


optional getAuthToken?: () => Promise<string | undefined>

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

Promise<string | undefined>


optional hasOpfsSyncAccess?: boolean

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

ADR-0049 D1: the placement probe’s OPFS-sync-access grant, threaded from the SharedWorker’s engine home (defineSyncWorker’s SW-direct bootstrap) into this boot so the client-owned create opens the OPFS-repacked backend. Absent/false is the honest IDBFS home — the declared backend: "idbfs" mode or a capability-absence fallback (a main thread can never hold handles either). Forwarded verbatim to createClientPGlite, which resolves the actual dataDir from it.


optional liveQueries?: object

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

Bounded zero-subscriber keep-alive for the live-query manager (ADR-0040 decision 4) — same block as DefineSyncWorkerOptions.liveQueries. Takes effect in BOTH client forms: the in-process client now owns its own manager (decision 6), so this policy governs its live-query dedup and retention just as it does the worker’s. Defaults: defaultKeepAliveMs 0 (tear a query down the instant its last consumer leaves), maxRetainedQueries 16, maxRetainedRows 50_000.

optional defaultKeepAliveMs?: number

optional maxRetainedQueries?: number

optional maxRetainedRows?: number


optional maxMutationAttempts?: number

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

Hard cap on send attempts before a still-failing mutation is quarantined (ADR-0005 congestion policy). Defaults to the library’s built-in cap.


optional onBootReport?: (report) => void

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

Boot observability (ADR-0034): invoked exactly once, at boot completion, with the finalized BootReport. The push counterpart of SyncClient.bootReport (the pull) for consumers that want the numbers without polling — dashboards, CI budget gates. Never fired before initial sync; a stop()/destroy() before then means it never fires.

BootReport

void


optional onConflict?: (conflicted) => void | Promise<void>

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

Invoked when mutations are conflicted — a stale write the server declined under the reject-if-stale Conflict policy (ADR-0015). The optimistic Overlay is kept, so the app shows a resolution/diff UI and resolves each as a new write (mutate.update) or discardConflicts it.

MutationDetail[]

void | Promise<void>


optional onConvergencePass?: (error) => void

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

Invoked after each automatic convergence pass with its error, or null on success (only when autoSync is set).

unknown

void


optional onQuarantine?: (quarantined) => void | Promise<void>

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

Invoked when mutations are quarantined (permanently rejected by the server, terminal). The library surfaces them here rather than silently dropping or retry-looping (ADR-0006). Surface, then either re-author + resubmit or roll back via SyncClient.discardQuarantined — which clears the kept overlay + quarantined journal rows so the entity accepts new mutations again.

MutationDetail[]

void | Promise<void>


optional onReject?: (rejected) => void | Promise<void>

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

Invoked when a pessimistic write-unit is rejected (ADR-0022) — a business decline from the authoritative endpoint (capacity/quota/uniqueness). The inverse of onConflict: the optimistic Overlay was auto-discarded for the whole unit, so the app surfaces the typed reason rather than a resolve UI.

MutationDetail[]

void | Promise<void>


optional onSchemaChange?: (event) => void | Promise<void>

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

Invoked when a supported store’s registry fingerprint changes. rebuilt means the clean read cache was rebuilt at the new shape; deferred means local mutations are still owed and must drain first.

LocalStoreVersionEvent

void | Promise<void>


optional onStatusChange?: (status) => void

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

SyncRuntimeStatus

void


optional onSyncError?: (error) => void

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

Invoked when a read-path sync commit fails after exhausting its retries (ADR-0009 decision 5). The runtime enters the degraded phase and holds the read cache at the last applied commit instead of silently diverging from the server; recovery is a later commit or a restart/refetch.

Error

void


optional onTableInitialSync?: (tableKey) => void

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

string

void


optional pgliteBootAssets?: Promise<PgliteBootAssets>

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

Pre-warmed PGlite boot assets (the WASM modules + filesystem bundle), awaited and passed straight into PGlite.create. The intent is to hide PGlite’s ~2.5s cold boot pglite.create cost — dominated by the WASM fetch+compile — behind user think-time: the host starts fetching/compiling these on an earlier screen (e.g. the login/identity picker) and hands the still-pending promise here, so by the time a store is opened the assets are already resolved and PGlite.create skips its own lazy asset load. Ignored when pgliteInstance is supplied (the caller owns that instance’s boot). A rejected/failed warm is caught to undefined and never fails the boot — PGlite falls back to loading its own assets, so this is a pure best-effort accelerator.


optional pgliteInstance?: ClientPGlite

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

A fully-provisioned PGlite instance the CALLER owns end-to-end. The client runs NONE of its post-create boot steps against it — no schema exec, prepare hooks, or registry reconciliation (journal recovery still runs, as it does on every path). Use it only when the caller has already applied the registry schema itself. Contrast the three PGlite-provenance seams:

  • storePath (default) — the client creates the store AND runs every post-create step.
  • precreatedPglite — the caller creates the raw store (via createClientPGlite), but the client still runs every post-create step (schema, prepare hooks, and reconciliation), exactly as storePath does.
  • pgliteInstance — the caller creates AND provisions the store; the client runs none of them.

A caller-owned instance is REFUSED with NonPersistentStoreError if it is provably non-persistent (a new PGlite() default, or an in-memory store) — pgxsinkit’s durability semantics assume a persisted store (ADR-0036). Acknowledge a deliberate test store by spreading testStoreAcknowledgment() from @pgxsinkit/client/testing.

Mutually exclusive with precreatedPglite (supplying both throws).


optional precreatedPglite?: Promise<ClientPGlite>

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

A raw PGlite instance the caller created EAGERLY (via createClientPGlite) — typically on an earlier screen, to hide the ~1.9s cold initdb/IDBFS open behind user think-time — but for which the client still owns EVERYTHING else: schema exec, prepare hooks, journal recovery, and registry reconciliation all run exactly as on the storePath path. This is the difference from pgliteInstance (which skips schema, prepare hooks, and reconciliation because the caller owns them); see that option’s JSDoc for the three-way distinction.

The promise form lets the still-pending eager create be handed straight in. Precedence/validation:

  • Supplying both this and pgliteInstance throws — they claim different ownership.
  • storePath is used ONLY as the fallback store name if this promise REJECTS: a failed eager create is caught, logged on the boot rail, and the normal storePath create path runs instead (also consuming pgliteBootAssets if provided). The pattern is a pure accelerator, never a boot dependency.
  • A successfully-adopted instance is subject to the same NonPersistentStoreError refusal as pgliteInstance (checked after resolution, so the refusal propagates rather than being swallowed by the reject-fallback).

optional prepareLocalDbAfterSchema?: (pglite) => Promise<void>

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

ClientPGlite

Promise<void>


optional prepareLocalDbBeforeSchema?: (pglite) => Promise<void>

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

ClientPGlite

Promise<void>


optional readSilenceMs?: number

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

The read-silence window (ms) after which a runtime claiming ready drops to degraded (reason “stream”). A pulled cable HANGS the live long-poll — nothing fails (the stall probe hears only settled attempts), nothing delivers — so without this a session that once reached ready would report “up to date” for as long as the outage lasts. A healthy stream is never silent (the long-poll cycles ~every 20-25s), so the default of 45s spans two full cycles. Self-recovering: the next delivered batch returns ready. Status honesty only — nothing is retired or torn down.


registry: TRegistry

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


optional requestHeaders?: Record<string, string>

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

Static headers added to every read-shape and write request, alongside the per-request Authorization (which always wins). The toolkit is agnostic about deployment-gateway credentials, so this is the seam for them — e.g. a Supabase Cloud apikey header the platform function gateway expects. Sent even when no getAuthToken is supplied.


optional resetSubscriptionKeys?: string[]

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


optional restoreFrom?: File | Blob

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

Restore the store from a store backup (ADR-0035 decision 6) — a File/Blob tarball as produced by SyncClient.exportStore. The client creates its store with the backup handed to PGlite’s loadDataDir, so it boots ON the backup’s datadir (synced cache + Overlay + Mutation journal, all the bytes that travelled inside it). Three restore-only rules apply, none of them optional:

  • Fresh target only. Refused with RestoreTargetExistsError if a store already exists at the resolved storePath — restore never overlays a live store (that would corrupt the datadir); the remedy is a deliberate SyncClient.destroy of the existing store first.
  • Comes online iff the recovered journal is clean (ADR-0046). If journal recovery found NOTHING to quarantine — an empty recovered journal, the guaranteed-clean server-built bootstrap-artifact case — the restore boots ONLINE, honouring syncEnabled/autoSync exactly as a normal boot (streams, flush, convergence). If recovered mutations were quarantined, the boot stays OFFLINE (no shape streams, no read fetch, no flush): the app inspects SyncClient.diagnostics, releases/discards the quarantined rows, then a subsequent NORMAL boot of the (now-persisted) store brings sync online. loadDataDir happens exactly once, on this restore boot. An explicit syncEnabled: false keeps it offline.
  • Journal quarantined. Every non-terminal recovered row (pending/sending/failed) is moved to quarantined — nothing recovered from a backup auto-flushes (the write path has no mutationId dedupe ledger, so replay is unsafe on last-write-wins tables). Release (retryFailed) or discard (discardQuarantined) them explicitly. When this pass quarantines nothing, the restore comes online (above).

Mutually exclusive with pgliteInstance AND precreatedPglite — restore owns the store’s creation (loadDataDir is a create-time seed), so a caller-supplied instance conflicts (supplying either with restoreFrom throws).


optional storePath?: string

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

The local store’s name (ADR-0036) — a PLAIN path/name, never a PGlite storage URL. The storage backend is DERIVED from the engine home (capability-selected opfs-repacked with IndexedDB fallback in a browser, or the filesystem on Bun/Node); a scheme-bearing string (anything containing ://) is rejected with InvalidStorePathError at boot. Defaults to a built-in overlay store name when omitted. A memory-backed store is not a product configuration — for the test/ephemeral lane, spread memoryStoreForTests(...) from @pgxsinkit/client/testing instead of naming one here.


optional syncEnabled?: boolean

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


optional writeRequestHeaders?: Record<string, string>

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

Extra static headers sent on the write path only (the mutation-flush POST), merged over requestHeaders ({...requestHeaders, ...writeRequestHeaders}). Read/shape requests never see these. The seam exists because the two ingress points have opposite geometry: the write function is DB-bound, so pinning it to the database’s region (e.g. an x-region header) keeps its chatty function→DB protocol on a ~1ms loop; the read proxy’s upstream is a globally-distributed CDN (Electric Cloud), so pinning reads away from the caller pays intercontinental round trips per catch-up hop. Put region/DB-affinity headers here; keep gateway credentials the reads also need (e.g. apikey) in the shared requestHeaders.