@gonvex/client 0.1.19 → 0.1.20

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.
package/README.md CHANGED
@@ -66,6 +66,42 @@ await client.clearQueryCache({ allScopes: true });
66
66
  Dexie is loaded asynchronously only after a cache-capable session is confirmed,
67
67
  so IndexedDB setup does not delay the WebSocket query path.
68
68
 
69
+ ## Durable Sync Collections
70
+
71
+ Sync functions materialize bounded, authorized single-table collections in a
72
+ normalized IndexedDB store and resume them from a durable Postgres cursor:
73
+
74
+ ```ts
75
+ const watch = client.watchSync<Task>(
76
+ { kind: "sync", path: "tasks.recent" },
77
+ { workspaceId: "workspace-a" },
78
+ );
79
+
80
+ const stop = watch.onUpdate(() => {
81
+ render(watch.localSyncResult() ?? []);
82
+ console.log(watch.status()); // { isLoading, isUpToDate }
83
+ });
84
+ ```
85
+
86
+ Configure or disable the sync store when constructing the client:
87
+
88
+ ```ts
89
+ const client = new GonvexClient(url, {
90
+ sync: {
91
+ databaseName: "my-product-sync",
92
+ maxBytes: 150 * 1024 * 1024,
93
+ },
94
+ });
95
+
96
+ const memoryOnly = new GonvexClient(url, { sync: false });
97
+ ```
98
+
99
+ The default global IndexedDB budget is 100 MiB. Server-declared per-collection
100
+ row/byte budgets still apply, and least-recently-used collections are evicted
101
+ first. Storage is isolated by runtime, project, tenant, authenticated identity,
102
+ and permissions. Sync is not an offline write queue; mutations and actions
103
+ retain the fail-closed policy below.
104
+
69
105
  ## Lightweight Error Tracking
70
106
 
71
107
  Capture global browser failures and failed Gonvex operations with the same
@@ -145,6 +181,7 @@ The package exports:
145
181
  - `ConvexReactClient` compatibility alias
146
182
  - `GonvexClientError`, `ConnectionState`, timeout defaults
147
183
  - transparent persistent query caching and lower-level experimental cache helpers
184
+ - `subscribeSync`, `watchSync`, and normalized persistent sync storage
148
185
  - browser capability and telemetry helpers
149
186
  - `GonvexErrorReporter` and automatic operation error reporting
150
187
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { BrowserTelemetryInfo, JsonValue, MessageTrace, ServerMessage } from "@gonvex/protocol";
1
+ import type { BrowserTelemetryInfo, JsonValue, MessageTrace, ServerCapabilities, ServerMessage } from "@gonvex/protocol";
2
2
  import { type QueryCacheOptions, type QueryCacheStatus } from "./query-cache.js";
3
3
  import { type SyncStoreOptions } from "./sync-store.js";
4
4
  import { type ErrorReporterOptions } from "./error-reporter.js";
@@ -84,6 +84,11 @@ export type GonvexClientOptions = GonvexClientAuth & {
84
84
  * Defaults to 250ms; set a longer bounded window for local-first apps.
85
85
  */
86
86
  querySubscriptionRetentionMs?: number;
87
+ /**
88
+ * Keep listenerless durable syncs open briefly across React remounts.
89
+ * Defaults to 250ms, preventing close/open/snapshot churn in StrictMode.
90
+ */
91
+ syncSubscriptionRetentionMs?: number;
87
92
  sync?: false | SyncStoreOptions;
88
93
  errorReporting?: false | Omit<ErrorReporterOptions, "endpoint" | "project" | "tenant">;
89
94
  timeouts?: GonvexTimeoutOptions;
@@ -111,7 +116,10 @@ export declare class GonvexClient {
111
116
  private readonly telemetryHandlers;
112
117
  private readonly pendingMessages;
113
118
  private readonly pendingSyncOpens;
119
+ private readonly pendingQuerySubscribes;
120
+ private readonly syncPersistence;
114
121
  private syncOpenFlushTimer;
122
+ private querySubscribeFlushTimer;
115
123
  private serverCapabilities;
116
124
  private auth;
117
125
  private authInFlight;
@@ -121,9 +129,11 @@ export declare class GonvexClient {
121
129
  private readonly queryCacheWaitForScope;
122
130
  private readonly queryCacheReadTimeoutMs;
123
131
  private readonly querySubscriptionRetentionMs;
132
+ private readonly syncSubscriptionRetentionMs;
124
133
  private readonly syncStore;
125
134
  private queryCacheDirective;
126
135
  private queryCacheGeneration;
136
+ private syncScopeGeneration;
127
137
  private queryCacheNegotiatedSocketGeneration;
128
138
  private syncIdentityGeneration;
129
139
  private readonly sessionScopeHandlers;
@@ -140,6 +150,8 @@ export declare class GonvexClient {
140
150
  private readonly timeouts;
141
151
  constructor(url: string, options?: GonvexClientOptions);
142
152
  connectionState(): ConnectionState;
153
+ /** Metadata advertised by the runtime in its latest session.ready frame. */
154
+ serverInfo(): Readonly<ServerCapabilities>;
143
155
  subscribeToConnectionState(handler: ConnectionStateHandler): () => void;
144
156
  private notifyConnectionState;
145
157
  setAuth(auth: GonvexClientAuth): void;
@@ -169,7 +181,9 @@ export declare class GonvexClient {
169
181
  onUpdate(handler: WatchUpdateHandler): () => void;
170
182
  };
171
183
  private handleSyncMessage;
184
+ private acceptSyncReady;
172
185
  private emitSyncMessage;
186
+ private markSyncSubscriptionsOutOfDate;
173
187
  private startSync;
174
188
  private sendSyncOpen;
175
189
  private syncOpenRequest;
@@ -186,9 +200,28 @@ export declare class GonvexClient {
186
200
  * nothing is subscribed to this query.
187
201
  */
188
202
  retryQuery(ref: FunctionReference, args?: JsonValue): void;
203
+ /**
204
+ * Flush a queue of mutations in one `mutation.callMany` frame (queue order,
205
+ * one websocket round trip). Each entry settles independently — a failed
206
+ * call does not reject the batch — so offline queues can apply per-row
207
+ * outcomes. Falls back to sequential `mutation` calls on runtimes that do
208
+ * not advertise the `mutationBatch` capability.
209
+ */
210
+ mutationMany<T = JsonValue>(calls: Array<{
211
+ ref: FunctionReference;
212
+ args?: JsonValue;
213
+ }>, options?: CallOptions): Promise<Array<{
214
+ status: "ok";
215
+ result: T;
216
+ } | {
217
+ status: "error";
218
+ error: GonvexClientError;
219
+ }>>;
189
220
  private call;
221
+ private registerCall;
190
222
  private unsubscribeQueryListener;
191
223
  private sendSubscription;
224
+ private flushQuerySubscribes;
192
225
  private resumeQuerySubscriptions;
193
226
  private enqueueSyncPersistence;
194
227
  private scheduleSyncRetry;
@@ -200,6 +233,8 @@ export declare class GonvexClient {
200
233
  private installQueryCacheDirective;
201
234
  private recoverWarmSyncDirective;
202
235
  private resetQueryCacheScope;
236
+ private resetQueryResultCacheState;
237
+ private resetSyncCacheState;
203
238
  private startQueryCacheRead;
204
239
  private persistQueryResult;
205
240
  private deleteCachedQuery;