@gonvex/client 0.5.2-staging.2 → 0.5.2-staging.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +68 -2
  2. package/dist/browser-upgrades.d.ts +19 -0
  3. package/dist/browser-upgrades.js +157 -0
  4. package/dist/browser-upgrades.js.map +1 -0
  5. package/dist/client-upgrades.d.ts +26 -0
  6. package/dist/client-upgrades.js +41 -0
  7. package/dist/client-upgrades.js.map +1 -0
  8. package/dist/control.d.ts +2 -0
  9. package/dist/control.js +1 -0
  10. package/dist/control.js.map +1 -1
  11. package/dist/index.d.ts +348 -9
  12. package/dist/index.js +1576 -192
  13. package/dist/index.js.map +1 -1
  14. package/dist/indexeddb-read-view.d.ts +24 -0
  15. package/dist/indexeddb-read-view.js +164 -0
  16. package/dist/indexeddb-read-view.js.map +1 -0
  17. package/dist/indexeddb-replica.d.ts +41 -3
  18. package/dist/indexeddb-replica.js +405 -111
  19. package/dist/indexeddb-replica.js.map +1 -1
  20. package/dist/local-replica.d.ts +127 -4
  21. package/dist/local-replica.js +836 -85
  22. package/dist/local-replica.js.map +1 -1
  23. package/dist/outbox.d.ts +118 -10
  24. package/dist/outbox.js +391 -89
  25. package/dist/outbox.js.map +1 -1
  26. package/dist/paged-read-view.d.ts +13 -0
  27. package/dist/paged-read-view.js +60 -0
  28. package/dist/paged-read-view.js.map +1 -0
  29. package/dist/query-expression.d.ts +39 -2
  30. package/dist/query-expression.js +106 -5
  31. package/dist/query-expression.js.map +1 -1
  32. package/dist/replica-integrity.d.ts +2 -0
  33. package/dist/replica-integrity.js +10 -0
  34. package/dist/replica-integrity.js.map +1 -1
  35. package/dist/replica-record.d.ts +14 -0
  36. package/dist/replica-record.js +46 -0
  37. package/dist/replica-record.js.map +1 -0
  38. package/package.json +4 -2
package/dist/index.d.ts CHANGED
@@ -1,18 +1,23 @@
1
- import type { BrowserTelemetryInfo, ExecutionScope, JsonValue, MessageTrace, ServerCapabilities, ServerMessage } from "@gonvex/protocol";
1
+ import type { BrowserTelemetryInfo, ExecutionScope, JsonValue, MessageTrace, ServerCapabilities, ServerMessage, ReducerErrorClass } from "@gonvex/protocol";
2
+ import type { LocalRuntimeBinding } from "@gonvex/local-runtime/worker-client";
2
3
  import { type ErrorReporterOptions } from "./error-reporter.js";
3
4
  export { GonvexErrorReporter } from "./error-reporter.js";
4
5
  export type { ErrorReporterOptions, ErrorEventPayload, ErrorContext, ErrorAccount } from "./error-reporter.js";
5
6
  import { type OptimisticPatch, type OptimisticTransactionDefinition } from "./optimistic.js";
6
- import { type OutboxStore } from "./outbox.js";
7
+ import { type OutboxErrorClass, type ReducerOutboxScopeSummary, type ReducerOutboxState, type OutboxStore } from "./outbox.js";
7
8
  import { type LocalReplicaStorage, type LocalReplicaView, type ReplicaRow, type LiveQueryResult, type ReplicaCollectionState, type ReplicaCollectionSubscriptionState, type ReplicaCollectionPlan } from "./local-replica.js";
8
9
  import { type LiveQueryPlan, type OfflineLiveQueryResult } from "./query-expression.js";
9
10
  export * from "./error-reporter.js";
10
11
  export * from "./optimistic.js";
11
12
  export * from "./outbox.js";
12
13
  export * from "./kv-stores.js";
14
+ export * from "./client-upgrades.js";
15
+ export * from "./browser-upgrades.js";
13
16
  export * from "./signals.js";
17
+ export * from "./paged-read-view.js";
18
+ export { mergeReplicaRecord, type ReplicaRecordVersion, type VersionedReplicaRecord } from './replica-record.js';
14
19
  export * from "./external-auth.js";
15
- export { MemoryLocalReplicaStorage, type LocalReplicaStorage, type LocalReplicaView, type ReplicaChange, type ReplicaFreshness, type ReplicaRow, type ReplicaScope, type ReplicaSnapshot, type ReplicaTransaction, type ReplicaWindow, type LiveQueryResult, type ReplicaCollectionState, type ReplicaCollectionSubscriptionState, type ReplicaCollectionPlan, } from "./local-replica.js";
20
+ export { MemoryLocalReplicaStorage, type LocalReplicaStorage, type LocalReplicaSession, type LocalReplicaView, type ReplicaChange, type ReplicaFreshness, type ReplicaRow, type ReplicaScope, type ReplicaSnapshot, type ReplicaTransaction, type ReplicaWindow, type LiveQueryResult, type ReplicaCollectionState, type ReplicaCollectionSubscriptionState, type ReplicaCollectionPlan, } from "./local-replica.js";
16
21
  export * from "./query-expression.js";
17
22
  export * from "./indexeddb-replica.js";
18
23
  export * from "./control.js";
@@ -49,6 +54,11 @@ export type FunctionReference<Args extends JsonValue = JsonValue, Result extends
49
54
  conflict?: "reject" | "expectedVersion" | "merge";
50
55
  reason?: string;
51
56
  };
57
+ localExecution?: 1;
58
+ /** SDK-owned version check for replay; never an application argument. */
59
+ receiptPath?: string;
60
+ artifactHash?: string;
61
+ intentEntropy?: string;
52
62
  live?: {
53
63
  entity: string;
54
64
  key: string;
@@ -85,12 +95,128 @@ export declare class GonvexClientError extends Error {
85
95
  readonly code: GonvexClientErrorCode;
86
96
  readonly path?: string;
87
97
  readonly operation?: "query" | "reducer" | "action";
98
+ /**
99
+ * For `server` Reducer errors: the runtime's classification, or a legacy
100
+ * inference when an older runtime sent none. Undefined means a legacy
101
+ * runtime's unclassified error, which is handled as a rejection.
102
+ */
103
+ readonly errorClass?: ReducerErrorClass;
104
+ /** True when the same call (same idempotency key) may succeed later. */
105
+ readonly retryable?: boolean;
88
106
  constructor(message: string, options: {
89
107
  code: GonvexClientErrorCode;
90
108
  path?: string;
91
109
  operation?: "query" | "reducer" | "action";
110
+ errorClass?: ReducerErrorClass;
111
+ retryable?: boolean;
92
112
  });
93
113
  }
114
+ /** One durable reducer intent, as exposed to application UI. */
115
+ export type OutboxIntent = {
116
+ /** The reducer id / idempotency key. Stable across retries, reloads and tabs. */
117
+ id: string;
118
+ /** Local queue sequence number. Lower numbers were issued first. */
119
+ entryId: number;
120
+ reducer: string;
121
+ state: ReducerOutboxState;
122
+ /** Failed deliveries counted toward the retry budget. */
123
+ attempts: number;
124
+ lastError?: string;
125
+ errorClass?: OutboxErrorClass;
126
+ createdAt: number;
127
+ nextAttemptAt: number;
128
+ /** When the intent became `failed` or `rejected`. */
129
+ settledAt?: number;
130
+ args: unknown;
131
+ /** Short, display-safe JSON preview of the arguments. */
132
+ argsSummary: string;
133
+ /** Rows this intent's optimistic prediction touched (best effort). */
134
+ entities: Array<{
135
+ entity: string;
136
+ id: string;
137
+ }>;
138
+ };
139
+ /** Per-row delivery status derived from the outbox. */
140
+ export type EntityIntentStatus = "syncing" | "failed" | "rejected";
141
+ export type ReducerRejectionEvent = {
142
+ reducerId: string;
143
+ path: string;
144
+ error: string;
145
+ errorClass?: OutboxErrorClass;
146
+ };
147
+ /**
148
+ * Why a locally executing Reducer ran without a local result.
149
+ * - `incompleteReplica`: the body read rows the Local Replica does not hold
150
+ * (no generated local collection, or one that has not hydrated yet).
151
+ * - `localError`: a replayed prediction failed locally for another reason.
152
+ */
153
+ export type LocalExecutionFallbackReason = "incompleteReplica" | "localError";
154
+ /**
155
+ * Emitted when the client degrades from local execution to a queued-only
156
+ * intent: the change is durable and will reach the server, but it has no
157
+ * optimistic result, so it is not visible until the server commits it (and
158
+ * never while offline).
159
+ */
160
+ export type LocalExecutionFallbackEvent = {
161
+ /** Reducer path. */
162
+ path: string;
163
+ /** Durable intent id, the Reducer's idempotency key. */
164
+ intentId: string;
165
+ /**
166
+ * `call`: the Reducer call returned `{ status: "queued" }` without a local
167
+ * result. `replay`: re-executing a pending intent lost the prediction it had.
168
+ */
169
+ phase: "call" | "replay";
170
+ reason: LocalExecutionFallbackReason;
171
+ /** The table whose rows were missing, for `incompleteReplica`. */
172
+ table?: string;
173
+ /** The local error message. */
174
+ error: string;
175
+ };
176
+ /**
177
+ * Which local dependency tables the client keeps hydrated so locally
178
+ * executing Reducers can run from their first call. See
179
+ * {@link GonvexClientOptions.localDependencyResidency}.
180
+ */
181
+ export type LocalDependencyResidency = "bounded" | "off" | {
182
+ /** Largest declared `maxRows` of a collection kept resident. Default 1000. */
183
+ maxRows?: number;
184
+ /** Largest declared `maxBytes` of a collection kept resident. Default: no byte bound. */
185
+ maxBytes?: number;
186
+ };
187
+ /** Default row bound of `localDependencyResidency: "bounded"`. */
188
+ export declare const DEFAULT_LOCAL_DEPENDENCY_RESIDENT_MAX_ROWS = 1000;
189
+ export type OutboxScope = ReducerOutboxScopeSummary & {
190
+ /** True for the identity this client is currently signed in as. */
191
+ current: boolean;
192
+ };
193
+ export type OutboxRetryOptions = {
194
+ /**
195
+ * Counted delivery failures (transient server errors and timeouts) before an
196
+ * intent is parked as `failed`. Default 10. `Infinity` retries forever.
197
+ */
198
+ maxAttempts?: number;
199
+ /** Cap for the exponential backoff between attempts. Default 60s. */
200
+ maxBackoffMs?: number;
201
+ };
202
+ export type ResetLocalReplicaOptions = {
203
+ /**
204
+ * Keep the durable outbox (default true). Pending, failed and rejected
205
+ * intents survive the reset and their predictions are re-applied on top of
206
+ * the rehydrated data. `false` also deletes every intent of the active
207
+ * identity that is not already inflight or committed; use it only for an
208
+ * explicit "discard unsynced changes" action.
209
+ */
210
+ keepOutbox?: boolean;
211
+ };
212
+ export type ResetLocalReplicaResult = {
213
+ /** Intents deleted because `keepOutbox: false` was requested. */
214
+ discardedIntents: number;
215
+ /** Replica Collections and Live Queries re-requested from the server. */
216
+ resubscribed: number;
217
+ };
218
+ export declare const DEFAULT_OUTBOX_MAX_ATTEMPTS = 10;
219
+ export declare const DEFAULT_OUTBOX_RETRY_MAX_BACKOFF_MS = 60000;
94
220
  export type ConnectionState = {
95
221
  isWebSocketConnected: boolean;
96
222
  hasEverConnected: boolean;
@@ -153,6 +279,34 @@ export type GonvexClientAuth = {
153
279
  };
154
280
  };
155
281
  export type GonvexClientOptions = GonvexClientAuth & {
282
+ /** Anonymous, online-only connection scoped to one tenant ID or routing domain. */
283
+ public?: {
284
+ tenant: string;
285
+ };
286
+ clientContract?: import("./client-upgrades.js").ClientContract;
287
+ onUpdateRequired?: (reason: string) => void;
288
+ /** Supplied by generated client bindings, once for the entire application. */
289
+ localRuntime?: LocalRuntimeBinding & {
290
+ clientContract?: import("./client-upgrades.js").ClientContract;
291
+ collections?: readonly FunctionReference[];
292
+ /** Per locally executing Reducer, the tables its body reads locally (from codegen). */
293
+ localDependencies?: Readonly<Record<string, readonly string[]>>;
294
+ };
295
+ /**
296
+ * Keep the generated local collections that locally executing Reducers
297
+ * depend on subscribed for the whole session, so a Reducer's first call
298
+ * runs locally instead of falling back to a queued-only intent.
299
+ *
300
+ * `"bounded"` (default) keeps a dependency table resident only when its
301
+ * generated collection declares `maxRows` of at most 1000 (the smallest
302
+ * `maxRows` among the table's unfiltered Replica Collections). Larger or
303
+ * undeclared collections stay page-driven: the screens that show them
304
+ * subscribe. Pass `{ maxRows, maxBytes }` to change the bounds, or `"off"`
305
+ * to disable residency.
306
+ */
307
+ localDependencyResidency?: LocalDependencyResidency;
308
+ /** Observe local-execution fallbacks; see {@link GonvexClient.onLocalExecutionFallback}. */
309
+ onLocalExecutionFallback?: (event: LocalExecutionFallbackEvent) => void;
156
310
  /**
157
311
  * Keep listenerless live queries subscribed for this long so route
158
312
  * backtracking can reuse their current result without WebSocket churn.
@@ -174,10 +328,13 @@ export type GonvexClientOptions = GonvexClientAuth & {
174
328
  databaseName?: string;
175
329
  enabled?: boolean;
176
330
  store?: OutboxStore;
331
+ retry?: OutboxRetryOptions;
177
332
  };
178
333
  /** Transactional normalized store used by Replica Collections and Live Queries. */
179
334
  localReplica?: {
180
335
  storage?: LocalReplicaStorage;
336
+ maxResidentRows?: number;
337
+ maxResidentBytes?: number;
181
338
  };
182
339
  errorReporting?: false | Omit<ErrorReporterOptions, "transport" | "project" | "tenant">;
183
340
  timeouts?: GonvexTimeoutOptions;
@@ -197,10 +354,34 @@ export type GonvexTelemetryEvent = {
197
354
  };
198
355
  export declare class GonvexClient {
199
356
  private readonly url;
357
+ private readonly localTableBindings;
358
+ private readonly localBinding?;
359
+ private readonly localExecutor?;
360
+ private readonly localStorage?;
361
+ private localIdentity?;
362
+ private localLane;
363
+ private preparationLane;
364
+ private localReplayScheduled;
365
+ private waitingLocalEdits;
366
+ private replacingLocal;
367
+ private readonly unsubscribeLocal?;
368
+ private readonly localCollectionClosers;
369
+ private readonly localCollectionKeys;
370
+ private readonly localExecutionTables;
371
+ private readonly reducerRejectionHandlers;
372
+ private readonly localFallbackHandlers;
373
+ private readonly residentDependencyTables;
374
+ private readonly outboxRetry;
375
+ private unauthenticatedRetries;
376
+ private intentsSnapshotValue;
377
+ private readonly intentListeners;
378
+ private intentsRefreshRunning;
379
+ private intentsRefreshDirty;
200
380
  private socket;
201
381
  private readonly handlers;
202
382
  private readonly querySubscriptions;
203
383
  private readonly replicaSubscriptions;
384
+ private readonly replicaMetadataListeners;
204
385
  private readonly oneShotQueries;
205
386
  private readonly telemetryHandlers;
206
387
  private readonly pendingMessages;
@@ -210,6 +391,7 @@ export declare class GonvexClient {
210
391
  private querySubscribeFlushTimer;
211
392
  private serverCapabilities;
212
393
  private activeArtifactHashValue;
394
+ private readonly publicTenant?;
213
395
  private auth;
214
396
  private authInFlight;
215
397
  private latestAuthFrameId;
@@ -219,6 +401,7 @@ export declare class GonvexClient {
219
401
  private authFetchGeneration;
220
402
  private authRetriedAfterError;
221
403
  private readonly authErrorHandlers;
404
+ private readonly developerCredentialHandlers;
222
405
  private managedAuthAttempt;
223
406
  private telemetryEnabled;
224
407
  private readonly querySubscriptionRetentionMs;
@@ -238,11 +421,19 @@ export declare class GonvexClient {
238
421
  private hasAuthoritativeReplicaScope;
239
422
  private replicaReady;
240
423
  private replicaFrames;
424
+ private queuedReplicaWatermark?;
241
425
  private processedReplicaWatermarkRevision;
242
- private readonly pendingReplicaTransactions;
426
+ private readonly pendingReplicaFrames;
243
427
  private readonly unsubscribeOutbox;
428
+ private readonly sharedOutboxStore?;
429
+ private readonly unsubscribePeerOutbox?;
430
+ private readonly unsubscribePeerReplica?;
431
+ private peerRefreshScheduled;
432
+ private peerRefreshDirty;
244
433
  private readonly unsubscribeBrowserOnline;
245
434
  private drainingOutbox;
435
+ /** A wake-up (timer, enqueue, reconnect) that arrived while a drain was running. */
436
+ private outboxDrainRequested;
246
437
  private outboxDrainTimer;
247
438
  private readonly sessionScopeHandlers;
248
439
  private readonly errorReporter;
@@ -254,11 +445,104 @@ export declare class GonvexClient {
254
445
  private readonly pendingCalls;
255
446
  private readonly connectionStateHandlers;
256
447
  private readonly supportCommandHandlers;
448
+ private readonly pendingNativeErrors;
257
449
  private isWebSocketConnected;
258
450
  private hasEverConnected;
259
451
  private connectionCount;
260
452
  private readonly timeouts;
453
+ private readonly clientContract?;
454
+ private readonly updateRequiredHandler?;
455
+ private updateRequired;
456
+ private lastOnlineAtMs;
261
457
  constructor(url: string, options?: GonvexClientOptions);
458
+ /**
459
+ * Authoritative sync failures arrive after an offline call returned locally.
460
+ * The intent also stays in the outbox as `rejected` until it is discarded
461
+ * or retried, so a UI that mounts later can still show it.
462
+ */
463
+ onReducerRejection(listener: (event: ReducerRejectionEvent) => void): () => void;
464
+ /**
465
+ * Observe every point where a locally executing Reducer degrades to a
466
+ * queued-only intent (no local result). The intent is still durable and is
467
+ * delivered to the server; this exists so apps can log and fix the missing
468
+ * local data. Returns an unsubscribe function.
469
+ */
470
+ onLocalExecutionFallback(listener: (event: LocalExecutionFallbackEvent) => void): () => void;
471
+ private reportLocalFallback;
472
+ /** Every durable intent of the current identity, oldest first. */
473
+ listIntents(): Promise<OutboxIntent[]>;
474
+ /**
475
+ * Synchronous snapshot for external stores (React `useSyncExternalStore`).
476
+ * Kept current while at least one {@link subscribeIntents} listener exists.
477
+ */
478
+ intentsSnapshot(): readonly OutboxIntent[];
479
+ /** Observe intent changes; call {@link intentsSnapshot} for the new value. */
480
+ subscribeIntents(listener: () => void): () => void;
481
+ /**
482
+ * Delivery status for one row from the current snapshot: `failed` or
483
+ * `rejected` when an intent touching it needs attention, `syncing` while one
484
+ * is still queued, otherwise undefined.
485
+ */
486
+ entityIntentStatus(entity: string, id: string): EntityIntentStatus | undefined;
487
+ /**
488
+ * Re-arm a `failed` or `rejected` intent with a fresh retry budget. The
489
+ * original idempotency key is reused, so an attempt that had actually
490
+ * committed is replayed by the server rather than applied twice.
491
+ */
492
+ retryIntent(id: string): Promise<boolean>;
493
+ /**
494
+ * Drop a `pending`, `failed` or `rejected` intent: it will never be sent,
495
+ * its optimistic prediction is removed and later local intents are rebased.
496
+ * Inflight and committed intents cannot be discarded. Discarding an intent
497
+ * whose earlier attempt timed out does not undo a commit that the server
498
+ * may already have applied; the replica then shows the server's truth.
499
+ */
500
+ discardIntent(id: string): Promise<boolean>;
501
+ /**
502
+ * Discard the persisted Local Replica of the active identity (IndexedDB,
503
+ * Expo SQLite or any configured storage) and rehydrate it from the server.
504
+ *
505
+ * Online only: without an authenticated connection the call rejects with a
506
+ * `GonvexClientError` (`code: "disconnected"`) and changes nothing, so the
507
+ * user is never left with an empty cache that cannot be refilled. The saved
508
+ * offline session (identity and replica directive) is kept.
509
+ *
510
+ * By default the outbox is untouched: pending, failed and rejected intents
511
+ * stay durable, and the predictions of every live intent are re-applied
512
+ * immediately and recomputed as server data arrives. Active Replica
513
+ * Collections and Live Queries are re-requested without their old cursors,
514
+ * so the server sends full snapshots.
515
+ */
516
+ resetLocalReplica(options?: ResetLocalReplicaOptions): Promise<ResetLocalReplicaResult>;
517
+ /** Outbox owners with durable entries, including identities that never returned. */
518
+ listOutboxScopes(): Promise<OutboxScope[]>;
519
+ /**
520
+ * Permanently delete another identity's durable intents. The active scope
521
+ * cannot be purged this way; use {@link discardIntent} for its entries.
522
+ */
523
+ purgeOutboxScope(scope: string): Promise<number>;
524
+ /** Purge every outbox scope except the current identity's. Never runs automatically. */
525
+ purgeForeignOutboxScopes(): Promise<number>;
526
+ private refreshIntents;
527
+ private publishIntents;
528
+ private restoreLocalSession;
529
+ private ensureLocalCollections;
530
+ private hydrateMissingLocalTable;
531
+ private localSnapshot;
532
+ private localReadCoverage;
533
+ private isUncoveredLocalRead;
534
+ private executeLocal;
535
+ private inLocalLane;
536
+ private replaceLocalPredictions;
537
+ private coordinateOutbox;
538
+ private refreshPeerOutbox;
539
+ private scheduleLocalReplay;
540
+ private reportLocalRejection;
541
+ private rebaseLocalEntries;
542
+ private rebaseLocalEntriesLocked;
543
+ private runLocalReducer;
544
+ /** Preload code for a mounted control without reading data or executing an intent. */
545
+ prepareReducer(ref: FunctionReference): Promise<void>;
262
546
  /** The single normalized authoritative + optimistic application data store. */
263
547
  get localReplica(): LocalReplicaView;
264
548
  replicaSignature(ref: FunctionReference, args?: JsonValue): string;
@@ -266,11 +550,16 @@ export declare class GonvexClient {
266
550
  retainedLiveQuery<T extends ReplicaRow = ReplicaRow>(signature: string): LiveQueryResult<T>;
267
551
  /** Resolve an ordered ID batch from one normalized entity store. */
268
552
  replicaEntities<T extends ReplicaRow = ReplicaRow>(entity: string, ids: readonly string[]): Array<T | undefined>;
553
+ /** Retain only the data an active view observes; cold rows remain on disk. */
554
+ retainReplicaEntities(entity: string, ids: readonly string[]): () => void;
555
+ retainReplicaWindow(signature: string): () => void;
269
556
  /** Read rows and server-owned completeness for a persisted Replica Collection. */
270
557
  replicaCollectionState<T extends ReplicaRow = ReplicaRow>(ref: FunctionReference, args?: JsonValue): ReplicaCollectionState<T>;
271
558
  /** Run the generated Live Query plan over the bounded normalized cache. */
272
- offlineLiveQuery<T extends ReplicaRow = ReplicaRow>(ref: FunctionReference, args?: JsonValue): OfflineLiveQueryResult<T>;
273
- /** Number of reducers waiting for a definitive server result. */
559
+ offlineLiveQuery<T extends ReplicaRow = ReplicaRow>(ref: FunctionReference, args?: JsonValue, options?: {
560
+ window?: boolean;
561
+ }): OfflineLiveQueryResult<T>;
562
+ /** Number of reducers still queued for delivery (excludes failed and rejected intents). */
274
563
  outboxCount(): Promise<number>;
275
564
  connectionState(): ConnectionState;
276
565
  /** Metadata advertised by the runtime in its latest session.ready frame. */
@@ -294,6 +583,15 @@ export declare class GonvexClient {
294
583
  * degrading to an unauthenticated session.
295
584
  */
296
585
  onAuthError(handler: (error: string) => void): () => void;
586
+ /**
587
+ * Subscribe to rotated developer-mode reconnect credentials. The runtime
588
+ * consumes each developer credential when it accepts a connection and
589
+ * returns a single-use successor; the client already uses that successor
590
+ * for its own reconnects. Auth providers subscribe so they can keep the
591
+ * newest credential in tab-scoped storage and resume developer mode after a
592
+ * page reload. The value is a secret: never log it or put it in a URL.
593
+ */
594
+ onDeveloperCredential(handler: (token: string) => void): () => void;
297
595
  private applyAuth;
298
596
  connect(): void;
299
597
  close(): void;
@@ -318,7 +616,9 @@ export declare class GonvexClient {
318
616
  /** Subscribe to a bounded Replica Collection. */
319
617
  subscribeReplica<Args extends JsonValue = JsonValue, Result extends JsonValue = JsonValue>(ref: FunctionReference<Args, Result>, args: Args | undefined, onMessage: ReplicaSubscriptionHandler): () => void;
320
618
  /** Watch a bounded Replica Collection through the normalized Local Replica. */
321
- watchReplica<T extends JsonValue = JsonValue, Args extends JsonValue = JsonValue>(ref: FunctionReference<Args, T>, args?: Args): {
619
+ watchReplica<T extends JsonValue = JsonValue, Args extends JsonValue = JsonValue>(ref: FunctionReference<Args, T>, args?: Args, options?: {
620
+ deferStart?: boolean;
621
+ }): {
322
622
  localReplicaResult: () => T[] | undefined;
323
623
  localReplicaState: () => ReplicaCollectionSubscriptionState | undefined;
324
624
  status: () => {
@@ -332,14 +632,17 @@ export declare class GonvexClient {
332
632
  * latest query result is retained only as the transport-shaped skeleton;
333
633
  * its row window is always rebuilt from LocalReplica membership/entities.
334
634
  */
335
- watchLiveQuery<T extends JsonValue = JsonValue, Args extends JsonValue = JsonValue>(ref: FunctionReference<Args, T>, args?: Args): {
635
+ watchLiveQuery<T extends JsonValue = JsonValue, Args extends JsonValue = JsonValue>(ref: FunctionReference<Args, T>, args?: Args, options?: {
636
+ deferStart?: boolean;
637
+ }): {
336
638
  localLiveQueryResult: () => T | undefined;
337
639
  onUpdate(handler: WatchUpdateHandler): () => void;
338
640
  };
339
641
  private handleReplicaMessage;
340
642
  private enqueueReplicaFrame;
643
+ private enqueueReplicaWatermark;
341
644
  private enqueueReplicaTransaction;
342
- private drainPendingReplicaTransactions;
645
+ private drainPendingReplicaFrames;
343
646
  private acceptReplicaReady;
344
647
  private handleReplicaWatermark;
345
648
  private emitReplicaMessage;
@@ -356,6 +659,8 @@ export declare class GonvexClient {
356
659
  private unsubscribeReplicaListener;
357
660
  private activateOutboxScope;
358
661
  private activateReplicaDirective;
662
+ private setReplicaReady;
663
+ private setOutboxReady;
359
664
  private quarantineReplicaScope;
360
665
  private rejectMissingReplicaDirective;
361
666
  private rejectReplicaDirective;
@@ -365,12 +670,32 @@ export declare class GonvexClient {
365
670
  private rejectOptimisticReducer;
366
671
  private ackOptimisticReducer;
367
672
  private drainOutbox;
673
+ /**
674
+ * Record a non-rejection delivery failure and arm the next attempt.
675
+ * - update_required: keep the intent pending and stop for an app update.
676
+ * - unauthenticated: keep the intent, re-authenticate, retry with backoff
677
+ * that never spends the retry budget.
678
+ * - network: connectivity loss; retried on reconnect without spending budget.
679
+ * - transient (and timeouts): exponential backoff, parked as `failed` once
680
+ * the retry budget is spent.
681
+ */
682
+ private recordDeliveryFailure;
683
+ /**
684
+ * Arm a timer for the earliest backed-off entry. Timer clocks and
685
+ * `Date.now()` can disagree by a millisecond, so a wake-up may find its
686
+ * entry not quite due; without this the queue would wait for an unrelated
687
+ * event to resume.
688
+ */
689
+ private scheduleNextOutboxAttempt;
690
+ /** Re-send auth on the open socket so a lost tenant session is restored. */
691
+ private requestReauthentication;
368
692
  private scheduleOutboxDrain;
369
693
  reducer<T extends JsonValue = JsonValue, Args extends JsonValue = JsonValue>(ref: FunctionReference<Args, T>, args: Args, options: CallOptions & {
370
694
  offline: "queue";
371
695
  }): Promise<T | QueuedReducerOutcome>;
372
696
  reducer<T extends JsonValue = JsonValue, Args extends JsonValue = JsonValue>(ref: FunctionReference<Args, T>, args?: Args, options?: CallOptions): Promise<T>;
373
697
  private runOptimisticReducer;
698
+ private requireClientUpdate;
374
699
  private canSendReducerNow;
375
700
  action<T extends JsonValue = JsonValue, Args extends JsonValue = JsonValue>(ref: FunctionReference<Args, T>, args?: Args, options?: CallOptions): Promise<T>;
376
701
  query<T extends JsonValue = JsonValue, Args extends JsonValue = JsonValue>(ref: FunctionReference<Args, T>, args?: Args, options?: CallOptions): Promise<T>;
@@ -428,6 +753,8 @@ export declare class GonvexClient {
428
753
  /** Send a bounded native error-telemetry frame using authenticated connection attribution. */
429
754
  reportError(type: "register" | "envelope" | "heartbeat", payload: unknown): Promise<void>;
430
755
  private sendNativeError;
756
+ private flushPendingNativeErrors;
757
+ private sendNativeErrorFrame;
431
758
  private sendAuth;
432
759
  private sendAuthFrame;
433
760
  private settleManagedAuthAttempt;
@@ -440,3 +767,15 @@ export declare class GonvexClient {
440
767
  private sendNow;
441
768
  private flushPendingMessages;
442
769
  }
770
+ /** Row status from a list of intents: failed > rejected > syncing. */
771
+ export declare function entityStatusFromIntents(intents: readonly OutboxIntent[], entity: string, id: string): EntityIntentStatus | undefined;
772
+ /**
773
+ * Dependency tables of locally executing Reducers that stay resident. A
774
+ * table qualifies when its unfiltered generated collection declares a small
775
+ * enough `maxRows` (and `maxBytes`, when bounded). Collections without a
776
+ * declared bound are never resident: their size is unknown.
777
+ */
778
+ export declare function residentLocalDependencyTables(binding: {
779
+ collections?: readonly FunctionReference[];
780
+ localDependencies?: Readonly<Record<string, readonly string[]>>;
781
+ } | undefined, policy?: LocalDependencyResidency): string[];