/** * Offline-sync provider abstraction. * * The SDK ships TWO sync strategies for the Postgres ↔ client-SQLite * loop, picked at construction time: * * - **`crdt`** (default) — bespoke field-level Last-Write-Wins merge on * top of IndexedDB / SQLite via `LocalStore` + `SyncManager`. Works * offline, applies on reconnect, handles conflicts. No external * dependency beyond the SDK + engine. * * - **`electric`** — Electric SQL replication. Postgres logical- * replication slot → Electric service → client. Conflicts are * resolved server-side via CRDTs Electric implements internally. * Requires an Electric service running alongside Postgres + the * engine routes from `routes/electric.ts` that mint short-lived * JWTs the client uses to authenticate. * * Auth flow for the electric provider * ----------------------------------- * 1. Provider calls `POST {engineUrl}/api/electric/auth` (with * credentials; the engine reads the better-auth session). * 2. Engine returns `{ token, expiresAt, electricUrl }`. * 3. Provider opens a websocket to `${electricUrl}?token=`. * 4. Before each token expires, the provider re-requests a fresh one * (no user interaction). * * Pull/push semantics * ------------------- * Electric replicates continuously over the websocket — there's no * explicit "pull" call. The provider's `pull()` is a no-op that returns * once the initial sync handshake completes. `push()` is the same: local * writes go through Electric's normal replication path automatically. * Both shims exist so the OfflineProvider interface stays uniform across * crdt/electric. * * Subscriptions * ------------- * `subscribe('zvd_contacts', cb)` registers a callback fired whenever * Electric pushes a change for that table. The implementation uses the * websocket's `message` event with a routing table; one socket, many * subscriptions. */ export type OfflineProviderKind = 'crdt' | 'electric'; export interface OfflineProviderConfig { /** Which sync engine to use. Default: 'crdt'. */ provider?: OfflineProviderKind; /** Engine base URL — used for the token-mint call AND CRDT push/pull. */ engineUrl: string; /** * Override the Electric websocket URL. When omitted, the provider asks * the engine via `GET /api/electric/config` so operators have a single * place to configure it. Useful for tests + dev setups. */ electricUrl?: string; /** * Tables to record on the audit token claim. Does NOT restrict what * Electric replicates — Electric enforces that via its own config. */ tables?: string[]; /** * Override the `fetch` impl — handy for tests + SSR. Default: globalThis.fetch. */ fetch?: typeof fetch; /** * Override the WebSocket constructor — handy for tests + non-browser * runtimes. Default: globalThis.WebSocket. */ websocket?: typeof WebSocket; } /** * Public interface every provider implements. Today the CRDT provider * wraps `SyncManager`; the Electric provider wraps a websocket. Both * expose the same surface. */ export interface OfflineProvider { readonly kind: OfflineProviderKind; /** Pull remote rows into the local store. Cheap to call repeatedly. */ pull(): Promise; /** Push local mutations to the server. Returns the number of ops sent. */ push(): Promise; /** Subscribe to live changes on a table. Returns an unsubscribe fn. */ subscribe(table: string, cb: (rows: unknown[]) => void): () => void; /** Stop background sync + release resources. */ close(): Promise; } export declare class ElectricNotConfigured extends Error { constructor(reason: string); } export declare class ElectricUnavailable extends Error { constructor(reason: string); } /** * Build the configured offline-sync provider. * * For `crdt` (default): returns a thin adapter around `SyncManager`. * * For `electric`: returns the real Electric provider. Throws * `ElectricNotConfigured` synchronously when required config is missing * (no electricUrl AND no way to discover one), or `ElectricUnavailable` * lazily on the first network op when the engine reports Electric is * disabled. */ export declare function createOfflineProvider(config: OfflineProviderConfig): Promise; //# sourceMappingURL=index.d.ts.map