@gonvex/client 0.1.25 → 0.1.26
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/dist/index.d.ts +87 -2
- package/dist/index.js +299 -15
- package/dist/index.js.map +1 -1
- package/dist/optimistic.d.ts +41 -0
- package/dist/optimistic.js +98 -0
- package/dist/optimistic.js.map +1 -0
- package/dist/outbox.d.ts +86 -0
- package/dist/outbox.js +324 -0
- package/dist/outbox.js.map +1 -0
- package/dist/signals.d.ts +20 -0
- package/dist/signals.js +259 -0
- package/dist/signals.js.map +1 -0
- package/dist/sync-store.d.ts +5 -0
- package/dist/sync-store.js +4 -0
- package/dist/sync-store.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { BrowserTelemetryInfo, JsonValue, MessageTrace, ServerCapabilities,
|
|
|
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";
|
|
5
|
+
import { OptimisticOverlay, type OptimisticPatch } from "./optimistic.js";
|
|
5
6
|
export * from "./cache.js";
|
|
6
7
|
export * from "./cache-coordinator.js";
|
|
7
8
|
export * from "./browser-cache.js";
|
|
@@ -12,8 +13,21 @@ export * from "./persistent-cache.js";
|
|
|
12
13
|
export * from "./query-cache.js";
|
|
13
14
|
export * from "./sync-store.js";
|
|
14
15
|
export * from "./error-reporter.js";
|
|
16
|
+
export * from "./optimistic.js";
|
|
17
|
+
export * from "./outbox.js";
|
|
18
|
+
export * from "./signals.js";
|
|
15
19
|
export type { QueryCacheDirective } from "@gonvex/protocol";
|
|
16
20
|
type SubscriptionHandler = (message: ServerMessage) => void;
|
|
21
|
+
export type SyncReadyMessage = Extract<ServerMessage, {
|
|
22
|
+
type: "sync.ready";
|
|
23
|
+
}> & {
|
|
24
|
+
/** True when the server cut this collection at its row or byte budget. */
|
|
25
|
+
truncated?: boolean;
|
|
26
|
+
};
|
|
27
|
+
export type SyncMessage = Extract<ServerMessage, {
|
|
28
|
+
type: "sync.snapshot" | "sync.delta" | "sync.needHashes" | "sync.syncing" | "sync.reset" | "sync.error";
|
|
29
|
+
}> | SyncReadyMessage;
|
|
30
|
+
export type SyncSubscriptionHandler = (message: SyncMessage) => void;
|
|
17
31
|
type WatchUpdateHandler = () => void;
|
|
18
32
|
type TelemetryHandler = (event: GonvexTelemetryEvent) => void;
|
|
19
33
|
type ConnectionStateHandler = (state: ConnectionState) => void;
|
|
@@ -31,7 +45,7 @@ export type GonvexClientErrorCode = "server" | "timeout" | "disconnected" | "clo
|
|
|
31
45
|
* - `timeout`: no response arrived within the operation timeout. For
|
|
32
46
|
* mutations/actions the write may or may not have been applied.
|
|
33
47
|
* - `disconnected`: the socket dropped while the operation was pending.
|
|
34
|
-
* Mutations/actions fail closed
|
|
48
|
+
* Mutations/actions fail closed unless a mutation opted into the outbox.
|
|
35
49
|
* - `closed`: the client was explicitly closed.
|
|
36
50
|
* - `auth`: authentication was rejected.
|
|
37
51
|
*/
|
|
@@ -69,12 +83,37 @@ export declare const DEFAULT_ACTION_TIMEOUT_MS = 60000;
|
|
|
69
83
|
export type CallOptions = {
|
|
70
84
|
/** Per-call override of the operation timeout. `0` disables. */
|
|
71
85
|
timeoutMs?: number;
|
|
86
|
+
/** Ordered row changes to expose until the mutation settles. */
|
|
87
|
+
optimistic?: OptimisticPatch[];
|
|
88
|
+
/** Queue transport failures durably instead of rejecting. Default `reject`. */
|
|
89
|
+
offline?: "queue" | "reject";
|
|
90
|
+
};
|
|
91
|
+
/** Returned when an offline mutation has been accepted by the local outbox. */
|
|
92
|
+
export type QueuedMutationOutcome = {
|
|
93
|
+
status: "queued";
|
|
94
|
+
mutationId: string;
|
|
72
95
|
};
|
|
96
|
+
export type GonvexAuthTokenFetcher = (args: {
|
|
97
|
+
/** True when the server just rejected the current token — bypass any cache. */
|
|
98
|
+
forceRefreshToken: boolean;
|
|
99
|
+
}) => Promise<string | null | undefined>;
|
|
73
100
|
export type GonvexClientAuth = {
|
|
74
101
|
project?: string;
|
|
75
102
|
token?: string;
|
|
76
103
|
tenant?: string;
|
|
77
104
|
telemetry?: boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Async source of the auth token, mirroring Convex's `fetchToken` contract.
|
|
107
|
+
* When installed, the client re-fetches before every auth send — on first
|
|
108
|
+
* connect, on every reconnect, and once more with `forceRefreshToken: true`
|
|
109
|
+
* when the server rejects the current token — so a socket that outlives a
|
|
110
|
+
* short-lived JWT (e.g. an ~1h Firebase ID token) reauthenticates with a
|
|
111
|
+
* live credential instead of replaying the expired one. A `token` passed in
|
|
112
|
+
* the same `setAuth` call is trusted and sent as-is; resolving `null` signs
|
|
113
|
+
* the session out; a rejected fetch keeps the currently installed token so
|
|
114
|
+
* an offline start is not signed out.
|
|
115
|
+
*/
|
|
116
|
+
fetchToken?: GonvexAuthTokenFetcher;
|
|
78
117
|
/**
|
|
79
118
|
* Non-secret identity hint ({@link https://datatracker.ietf.org/doc/html/rfc7519 JWT}
|
|
80
119
|
* `sub` and `iss` claims) that stands in for a token when deriving the local
|
|
@@ -103,6 +142,14 @@ export type GonvexClientOptions = GonvexClientAuth & {
|
|
|
103
142
|
*/
|
|
104
143
|
syncSubscriptionRetentionMs?: number;
|
|
105
144
|
sync?: false | SyncStoreOptions;
|
|
145
|
+
/**
|
|
146
|
+
* Durable mutation queue settings. Every replay keeps its original
|
|
147
|
+
* idempotency key, making an accidental cross-tab double-send server-safe.
|
|
148
|
+
*/
|
|
149
|
+
outbox?: {
|
|
150
|
+
databaseName?: string;
|
|
151
|
+
enabled?: boolean;
|
|
152
|
+
};
|
|
106
153
|
errorReporting?: false | Omit<ErrorReporterOptions, "endpoint" | "project" | "tenant">;
|
|
107
154
|
timeouts?: GonvexTimeoutOptions;
|
|
108
155
|
};
|
|
@@ -137,6 +184,9 @@ export declare class GonvexClient {
|
|
|
137
184
|
private auth;
|
|
138
185
|
private authInFlight;
|
|
139
186
|
private authWatchdogTimer;
|
|
187
|
+
private authFetchGeneration;
|
|
188
|
+
private authRetriedAfterError;
|
|
189
|
+
private readonly authErrorHandlers;
|
|
140
190
|
private telemetryEnabled;
|
|
141
191
|
private readonly queryCache;
|
|
142
192
|
private readonly queryCacheWaitForScope;
|
|
@@ -144,6 +194,14 @@ export declare class GonvexClient {
|
|
|
144
194
|
private readonly querySubscriptionRetentionMs;
|
|
145
195
|
private readonly syncSubscriptionRetentionMs;
|
|
146
196
|
private readonly syncStore;
|
|
197
|
+
private readonly mutationOutbox;
|
|
198
|
+
private readonly overlay;
|
|
199
|
+
private readonly optimisticMutationIds;
|
|
200
|
+
private readonly outboxReady;
|
|
201
|
+
private readonly unsubscribeOutbox;
|
|
202
|
+
private readonly unsubscribeOverlay;
|
|
203
|
+
private drainingOutbox;
|
|
204
|
+
private outboxDrainTimer;
|
|
147
205
|
private queryCacheDirective;
|
|
148
206
|
private queryCacheGeneration;
|
|
149
207
|
private syncScopeGeneration;
|
|
@@ -162,12 +220,24 @@ export declare class GonvexClient {
|
|
|
162
220
|
private connectionCount;
|
|
163
221
|
private readonly timeouts;
|
|
164
222
|
constructor(url: string, options?: GonvexClientOptions);
|
|
223
|
+
/** The client's materialized optimistic state for pending-row indicators. */
|
|
224
|
+
get optimisticOverlay(): OptimisticOverlay;
|
|
225
|
+
/** Number of mutations waiting for a definitive server result. */
|
|
226
|
+
outboxCount(): Promise<number>;
|
|
165
227
|
connectionState(): ConnectionState;
|
|
166
228
|
/** Metadata advertised by the runtime in its latest session.ready frame. */
|
|
167
229
|
serverInfo(): Readonly<ServerCapabilities>;
|
|
168
230
|
subscribeToConnectionState(handler: ConnectionStateHandler): () => void;
|
|
169
231
|
private notifyConnectionState;
|
|
170
232
|
setAuth(auth: GonvexClientAuth): void;
|
|
233
|
+
/**
|
|
234
|
+
* Subscribe to unrecoverable auth rejections: the server refused the
|
|
235
|
+
* credentials and, when a token fetcher is installed, a force-refreshed
|
|
236
|
+
* token did not fix it. Lets apps route to sign-in instead of silently
|
|
237
|
+
* degrading to an unauthenticated session.
|
|
238
|
+
*/
|
|
239
|
+
onAuthError(handler: (error: string) => void): () => void;
|
|
240
|
+
private applyAuth;
|
|
171
241
|
connect(): void;
|
|
172
242
|
close(): void;
|
|
173
243
|
private rejectPendingCalls;
|
|
@@ -184,7 +254,7 @@ export declare class GonvexClient {
|
|
|
184
254
|
localQueryResult(): T | undefined;
|
|
185
255
|
onUpdate(handler: WatchUpdateHandler): () => void;
|
|
186
256
|
};
|
|
187
|
-
subscribeSync(ref: FunctionReference, args: JsonValue | undefined, onMessage:
|
|
257
|
+
subscribeSync(ref: FunctionReference, args: JsonValue | undefined, onMessage: SyncSubscriptionHandler): () => void;
|
|
188
258
|
watchSync<T extends JsonValue = JsonValue>(ref: FunctionReference, args?: JsonValue): {
|
|
189
259
|
localSyncResult(): T[] | undefined;
|
|
190
260
|
status(): {
|
|
@@ -196,6 +266,8 @@ export declare class GonvexClient {
|
|
|
196
266
|
private handleSyncMessage;
|
|
197
267
|
private acceptSyncReady;
|
|
198
268
|
private emitSyncMessage;
|
|
269
|
+
private materializeSyncMessage;
|
|
270
|
+
private emitOptimisticCollection;
|
|
199
271
|
private markSyncSubscriptionsOutOfDate;
|
|
200
272
|
private startSync;
|
|
201
273
|
private sendSyncOpen;
|
|
@@ -204,6 +276,15 @@ export declare class GonvexClient {
|
|
|
204
276
|
private unsubscribeSyncListener;
|
|
205
277
|
private persistSyncSnapshot;
|
|
206
278
|
private persistSyncDelta;
|
|
279
|
+
private restoreOutbox;
|
|
280
|
+
private addOptimisticMutation;
|
|
281
|
+
private settleOptimisticMutation;
|
|
282
|
+
private rejectOptimisticMutation;
|
|
283
|
+
private drainOutbox;
|
|
284
|
+
private scheduleOutboxDrain;
|
|
285
|
+
mutation<T = JsonValue>(ref: FunctionReference, args: JsonValue, options: CallOptions & {
|
|
286
|
+
offline: "queue";
|
|
287
|
+
}): Promise<T | QueuedMutationOutcome>;
|
|
207
288
|
mutation<T = JsonValue>(ref: FunctionReference, args?: JsonValue, options?: CallOptions): Promise<T>;
|
|
208
289
|
action<T = JsonValue>(ref: FunctionReference, args?: JsonValue, options?: CallOptions): Promise<T>;
|
|
209
290
|
query<T = JsonValue>(ref: FunctionReference, args?: JsonValue, options?: CallOptions): Promise<T>;
|
|
@@ -256,6 +337,10 @@ export declare class GonvexClient {
|
|
|
256
337
|
private emitTelemetry;
|
|
257
338
|
private reportTelemetry;
|
|
258
339
|
private sendAuth;
|
|
340
|
+
private sendAuthFrame;
|
|
341
|
+
private fetchAndSendAuth;
|
|
342
|
+
private refreshRejectedAuth;
|
|
343
|
+
private notifyAuthError;
|
|
259
344
|
private armAuthWatchdog;
|
|
260
345
|
private send;
|
|
261
346
|
private sendNow;
|