CreateSyncClientOptions
Defined in: packages/client/src/index.ts:922
Type Parameters
Section titled “Type Parameters”TRegistry
Section titled “TRegistry”TRegistry extends SyncTableRegistry
Properties
Section titled “Properties”autoSync?
Section titled “autoSync?”
optionalautoSync?: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).
batchEventUrl?
Section titled “batchEventUrl?”
optionalbatchEventUrl?: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
Section titled “batchWriteUrl”batchWriteUrl:
string
Defined in: packages/client/src/index.ts:925
electricUrl
Section titled “electricUrl”electricUrl:
string
Defined in: packages/client/src/index.ts:924
events?
Section titled “events?”
optionalevents?: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.
freshStore?
Section titled “freshStore?”
optionalfreshStore?: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).
getAuthToken?
Section titled “getAuthToken?”
optionalgetAuthToken?: () =>Promise<string|undefined>
Defined in: packages/client/src/index.ts:926
Returns
Section titled “Returns”Promise<string | undefined>
hasOpfsSyncAccess?
Section titled “hasOpfsSyncAccess?”
optionalhasOpfsSyncAccess?: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.
liveQueries?
Section titled “liveQueries?”
optionalliveQueries?: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.
defaultKeepAliveMs?
Section titled “defaultKeepAliveMs?”
optionaldefaultKeepAliveMs?:number
maxRetainedQueries?
Section titled “maxRetainedQueries?”
optionalmaxRetainedQueries?:number
maxRetainedRows?
Section titled “maxRetainedRows?”
optionalmaxRetainedRows?:number
maxMutationAttempts?
Section titled “maxMutationAttempts?”
optionalmaxMutationAttempts?: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.
onBootReport?
Section titled “onBootReport?”
optionalonBootReport?: (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.
Parameters
Section titled “Parameters”report
Section titled “report”Returns
Section titled “Returns”void
onConflict?
Section titled “onConflict?”
optionalonConflict?: (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.
Parameters
Section titled “Parameters”conflicted
Section titled “conflicted”Returns
Section titled “Returns”void | Promise<void>
onConvergencePass?
Section titled “onConvergencePass?”
optionalonConvergencePass?: (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).
Parameters
Section titled “Parameters”unknown
Returns
Section titled “Returns”void
onQuarantine?
Section titled “onQuarantine?”
optionalonQuarantine?: (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.
Parameters
Section titled “Parameters”quarantined
Section titled “quarantined”Returns
Section titled “Returns”void | Promise<void>
onReject?
Section titled “onReject?”
optionalonReject?: (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.
Parameters
Section titled “Parameters”rejected
Section titled “rejected”Returns
Section titled “Returns”void | Promise<void>
onSchemaChange?
Section titled “onSchemaChange?”
optionalonSchemaChange?: (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.
Parameters
Section titled “Parameters”Returns
Section titled “Returns”void | Promise<void>
onStatusChange?
Section titled “onStatusChange?”
optionalonStatusChange?: (status) =>void
Defined in: packages/client/src/index.ts:996
Parameters
Section titled “Parameters”status
Section titled “status”SyncRuntimeStatus
Returns
Section titled “Returns”void
onSyncError?
Section titled “onSyncError?”
optionalonSyncError?: (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.
Parameters
Section titled “Parameters”Error
Returns
Section titled “Returns”void
onTableInitialSync?
Section titled “onTableInitialSync?”
optionalonTableInitialSync?: (tableKey) =>void
Defined in: packages/client/src/index.ts:997
Parameters
Section titled “Parameters”tableKey
Section titled “tableKey”string
Returns
Section titled “Returns”void
pgliteBootAssets?
Section titled “pgliteBootAssets?”
optionalpgliteBootAssets?: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.
pgliteInstance?
Section titled “pgliteInstance?”
optionalpgliteInstance?: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
storePathdoes. 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).
precreatedPglite?
Section titled “precreatedPglite?”
optionalprecreatedPglite?: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
storePathcreate 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).
prepareLocalDbAfterSchema?
Section titled “prepareLocalDbAfterSchema?”
optionalprepareLocalDbAfterSchema?: (pglite) =>Promise<void>
Defined in: packages/client/src/index.ts:995
Parameters
Section titled “Parameters”pglite
Section titled “pglite”Returns
Section titled “Returns”Promise<void>
prepareLocalDbBeforeSchema?
Section titled “prepareLocalDbBeforeSchema?”
optionalprepareLocalDbBeforeSchema?: (pglite) =>Promise<void>
Defined in: packages/client/src/index.ts:994
Parameters
Section titled “Parameters”pglite
Section titled “pglite”Returns
Section titled “Returns”Promise<void>
readSilenceMs?
Section titled “readSilenceMs?”
optionalreadSilenceMs?: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
Section titled “registry”registry:
TRegistry
Defined in: packages/client/src/index.ts:923
requestHeaders?
Section titled “requestHeaders?”
optionalrequestHeaders?: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.
resetSubscriptionKeys?
Section titled “resetSubscriptionKeys?”
optionalresetSubscriptionKeys?:string[]
Defined in: packages/client/src/index.ts:993
restoreFrom?
Section titled “restoreFrom?”
optionalrestoreFrom?: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.
loadDataDirhappens exactly once, on this restore boot. An explicitsyncEnabled: falsekeeps it offline. - Journal quarantined. Every non-terminal recovered row (
pending/sending/failed) is moved toquarantined— nothing recovered from a backup auto-flushes (the write path has nomutationIddedupe 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).
storePath?
Section titled “storePath?”
optionalstorePath?: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.
syncEnabled?
Section titled “syncEnabled?”
optionalsyncEnabled?:boolean
Defined in: packages/client/src/index.ts:945
writeRequestHeaders?
Section titled “writeRequestHeaders?”
optionalwriteRequestHeaders?: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.