import type { QueryClient } from '@tanstack/query-core'; import type { AnyBunderstackApp, InferSchema, InferSelect, InferTables } from './infer.js'; import type { NotifyScheduler, RealtimeClock } from './realtime-flush.js'; import type { RealtimeAction, RealtimeChange, RealtimeProcedure, RealtimeSyncHandle } from './realtime-stream.js'; export type { NotifyScheduler, RealtimeClock } from './realtime-flush.js'; export type { RealtimeAction, RealtimeChange, RealtimeEvent, RealtimeHeartbeat, RealtimeProcedure, RealtimeSyncHandle, } from './realtime-stream.js'; /** * The change for one table, with `record` typed as that table's row. * * Passing the app type to `syncRealtime` turns `tables` into a checked list of * exposed table names and `onChange` into a union discriminated by `table`, so * `change.table === 'todos'` narrows `change.record` to the todo row: * * ```ts * syncRealtime({ * api, * queryClient, * tables: ['todos'], * onChange: (change) => { * if (change.table === 'todos') console.log(change.record.done) * }, * }) * ``` */ export type RealtimeChangeFor> = { table: TTable; action: RealtimeAction; record: InferSelect[TTable]>; operationId?: string; }; /** * Untyped when no app type is supplied, so existing callers — and consumers * that only have a structural client — keep the loose `RealtimeChange`. */ export type RealtimeChangeOf = [TApp] extends [ never ] ? RealtimeChange : TApp extends AnyBunderstackApp ? TTable extends InferTables ? RealtimeChangeFor : RealtimeChange : RealtimeChange; /** Every exposed table name, or any string when no app type is supplied. */ export type RealtimeTableName = [TApp] extends [never] ? string : TApp extends AnyBunderstackApp ? InferTables : string; export type RealtimeQueryApi = { realtime: { changes: RealtimeProcedure; }; [table: string]: any; }; /** * How a change reaches the cache. * * `invalidate` (default) marks the table's queries stale and lets TanStack * Query refetch them — always correct, one request per change. * * `patch` writes the change into cached list results instead, so a write costs * no extra request. The event carries the action and the full row, and * Bunderstack's list contract is narrow enough to decide membership locally: * filters are `=`, `IN`, or `IS NULL`, and ordering is a single column. Any * list where that is not decidable — a text search, or a page that is not the * complete result — falls back to invalidation. */ export type RealtimeApplyStrategy = 'invalidate' | 'patch'; export type RealtimeSyncOptions> = { api: RealtimeQueryApi; queryClient: QueryClient; tables: TTable[]; signal?: AbortSignal; /** Defaults to `'invalidate'`. */ apply?: RealtimeApplyStrategy; /** * When buffered changes reach the cache. Defaults to `'frame'`, which * collapses a burst into one cache write and one invalidation per table. * Pass `'sync'` to write as each change arrives, as versions before 0.18 did. */ notifyScheduler?: NotifyScheduler; /** Timer functions, injectable for tests. */ clock?: RealtimeClock; /** Initial reconnect delay before jitter. Defaults to 1 second. */ retryMs?: number; /** Maximum reconnect delay before jitter. Defaults to 30 seconds. */ maxRetryMs?: number; onChange?: (change: RealtimeChangeOf) => void; onReconnect?: () => void | Promise; onError?: (error: unknown) => void; onRetry?: (retry: { attempt: number; delayMs: number; }) => void; }; export declare function syncRealtime>(options: RealtimeSyncOptions): RealtimeSyncHandle; //# sourceMappingURL=realtime.d.ts.map