@rxferrix/client 0.0.0-stage → 0.2.0

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 (97) hide show
  1. package/dist/api.d.ts +60 -0
  2. package/dist/api.d.ts.map +1 -0
  3. package/dist/api.js +22 -0
  4. package/dist/api.js.map +1 -0
  5. package/dist/auth.d.ts +256 -0
  6. package/dist/auth.d.ts.map +1 -0
  7. package/dist/auth.js +541 -0
  8. package/dist/auth.js.map +1 -0
  9. package/dist/bytes.d.ts +21 -0
  10. package/dist/bytes.d.ts.map +1 -0
  11. package/dist/bytes.js +51 -0
  12. package/dist/bytes.js.map +1 -0
  13. package/dist/canonical.d.ts +13 -0
  14. package/dist/canonical.d.ts.map +1 -0
  15. package/dist/canonical.js +66 -0
  16. package/dist/canonical.js.map +1 -0
  17. package/dist/client.d.ts +170 -0
  18. package/dist/client.d.ts.map +1 -0
  19. package/dist/client.js +638 -0
  20. package/dist/client.js.map +1 -0
  21. package/dist/diff.d.ts +20 -0
  22. package/dist/diff.d.ts.map +1 -0
  23. package/dist/diff.js +100 -0
  24. package/dist/diff.js.map +1 -0
  25. package/dist/errors.d.ts +24 -0
  26. package/dist/errors.d.ts.map +1 -0
  27. package/dist/errors.js +34 -0
  28. package/dist/errors.js.map +1 -0
  29. package/dist/index.d.ts +14 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +12 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/local_query_set.d.ts +56 -0
  34. package/dist/local_query_set.d.ts.map +1 -0
  35. package/dist/local_query_set.js +108 -0
  36. package/dist/local_query_set.js.map +1 -0
  37. package/dist/logging.d.ts +15 -0
  38. package/dist/logging.d.ts.map +1 -0
  39. package/dist/logging.js +17 -0
  40. package/dist/logging.js.map +1 -0
  41. package/dist/optimistic_updates.d.ts +48 -0
  42. package/dist/optimistic_updates.d.ts.map +1 -0
  43. package/dist/optimistic_updates.js +113 -0
  44. package/dist/optimistic_updates.js.map +1 -0
  45. package/dist/paginated_query.d.ts +118 -0
  46. package/dist/paginated_query.d.ts.map +1 -0
  47. package/dist/paginated_query.js +199 -0
  48. package/dist/paginated_query.js.map +1 -0
  49. package/dist/protocol.d.ts +136 -0
  50. package/dist/protocol.d.ts.map +1 -0
  51. package/dist/protocol.js +11 -0
  52. package/dist/protocol.js.map +1 -0
  53. package/dist/query_state.d.ts +16 -0
  54. package/dist/query_state.d.ts.map +1 -0
  55. package/dist/query_state.js +2 -0
  56. package/dist/query_state.js.map +1 -0
  57. package/dist/remote_query_set.d.ts +37 -0
  58. package/dist/remote_query_set.d.ts.map +1 -0
  59. package/dist/remote_query_set.js +87 -0
  60. package/dist/remote_query_set.js.map +1 -0
  61. package/dist/request_manager.d.ts +57 -0
  62. package/dist/request_manager.d.ts.map +1 -0
  63. package/dist/request_manager.js +163 -0
  64. package/dist/request_manager.js.map +1 -0
  65. package/dist/storage.d.ts +45 -0
  66. package/dist/storage.d.ts.map +1 -0
  67. package/dist/storage.js +120 -0
  68. package/dist/storage.js.map +1 -0
  69. package/dist/testing.d.ts +68 -0
  70. package/dist/testing.d.ts.map +1 -0
  71. package/dist/testing.js +97 -0
  72. package/dist/testing.js.map +1 -0
  73. package/dist/web_socket_manager.d.ts +88 -0
  74. package/dist/web_socket_manager.d.ts.map +1 -0
  75. package/dist/web_socket_manager.js +291 -0
  76. package/dist/web_socket_manager.js.map +1 -0
  77. package/package.json +50 -4
  78. package/src/api.ts +86 -0
  79. package/src/auth.ts +646 -0
  80. package/src/bytes.ts +57 -0
  81. package/src/canonical.ts +61 -0
  82. package/src/client.ts +740 -0
  83. package/src/diff.ts +87 -0
  84. package/src/errors.ts +36 -0
  85. package/src/index.ts +60 -0
  86. package/src/local_query_set.ts +130 -0
  87. package/src/logging.ts +26 -0
  88. package/src/optimistic_updates.ts +137 -0
  89. package/src/paginated_query.ts +299 -0
  90. package/src/protocol.ts +152 -0
  91. package/src/query_state.ts +12 -0
  92. package/src/remote_query_set.ts +105 -0
  93. package/src/request_manager.ts +199 -0
  94. package/src/storage.ts +171 -0
  95. package/src/testing.ts +120 -0
  96. package/src/web_socket_manager.ts +322 -0
  97. package/README.md +0 -3
package/dist/client.js ADDED
@@ -0,0 +1,638 @@
1
+ import { normalizeArgs, queryToken } from "./canonical.js";
2
+ import { CLIENT_CLOSED, RxFerrixError } from "./errors.js";
3
+ import { LocalQuerySet } from "./local_query_set.js";
4
+ import { createLogger } from "./logging.js";
5
+ import { OptimisticQueryResults, } from "./optimistic_updates.js";
6
+ import { PaginatedQueryImpl, } from "./paginated_query.js";
7
+ import { DiffMismatch } from "./diff.js";
8
+ import { RemoteQuerySet, TransitionVersionMismatch } from "./remote_query_set.js";
9
+ import { RequestManager } from "./request_manager.js";
10
+ import { WebSocketManager } from "./web_socket_manager.js";
11
+ function deriveSyncUrl(url) {
12
+ let parsed;
13
+ try {
14
+ parsed = new URL(url);
15
+ }
16
+ catch {
17
+ throw new Error(`RxFerrixClient: invalid deployment URL ${JSON.stringify(url)}`);
18
+ }
19
+ switch (parsed.protocol) {
20
+ case "http:":
21
+ case "ws:":
22
+ parsed.protocol = "ws:";
23
+ break;
24
+ case "https:":
25
+ case "wss:":
26
+ parsed.protocol = "wss:";
27
+ break;
28
+ default:
29
+ throw new Error(`RxFerrixClient: unsupported URL protocol ${parsed.protocol}`);
30
+ }
31
+ parsed.pathname = parsed.pathname.replace(/\/+$/, "") + "/api/sync";
32
+ parsed.search = "";
33
+ parsed.hash = "";
34
+ return parsed.toString();
35
+ }
36
+ function randomSessionId() {
37
+ const c = globalThis.crypto;
38
+ if (c?.randomUUID)
39
+ return c.randomUUID();
40
+ // RFC 4122 v4 fallback.
41
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (ch) => {
42
+ const r = (Math.random() * 16) | 0;
43
+ return (ch === "x" ? r : (r & 0x3) | 0x8).toString(16);
44
+ });
45
+ }
46
+ /** Seconds-since-epoch `exp` claim of a JWT, if the token is a decodable JWT. */
47
+ function jwtExpiry(token) {
48
+ const parts = token.split(".");
49
+ if (parts.length !== 3 || !parts[1])
50
+ return null;
51
+ try {
52
+ const b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
53
+ const padded = b64 + "=".repeat((4 - (b64.length % 4)) % 4);
54
+ const json = typeof atob === "function" ? atob(padded) : "";
55
+ const payload = JSON.parse(json);
56
+ return typeof payload.exp === "number" ? payload.exp : null;
57
+ }
58
+ catch {
59
+ return null;
60
+ }
61
+ }
62
+ /** Refresh this long before a JWT's `exp`. */
63
+ const TOKEN_REFRESH_LEEWAY_MS = 30_000;
64
+ const MAX_TIMEOUT_MS = 2_147_483_647;
65
+ /**
66
+ * The RxFerrix sync client: subscribes to queries over a WebSocket and runs mutations and actions.
67
+ *
68
+ * ```ts
69
+ * const client = new RxFerrixClient("http://localhost:3210");
70
+ * const watch = client.watchQuery(api.todos.list, {});
71
+ * watch.onUpdate(() => console.log(watch.localQueryResult()));
72
+ * await client.mutation(api.todos.add, { text: "hi" });
73
+ * ```
74
+ */
75
+ export class RxFerrixClient {
76
+ /** The http(s) base URL this client was created with. */
77
+ url;
78
+ /** The WebSocket URL (`ws(s)://host/api/sync`). */
79
+ syncUrl;
80
+ sessionId;
81
+ logger;
82
+ ws;
83
+ localQueries = new LocalQuerySet();
84
+ remoteQueries = new RemoteQuerySet();
85
+ requests = new RequestManager();
86
+ optimistic;
87
+ listeners = new Map();
88
+ connectionListeners = new Set();
89
+ cachedConnectionState;
90
+ flushScheduled = false;
91
+ closed = false;
92
+ /**
93
+ * Set after a reconnect while live queries have not yet received results from the new socket. The local view then
94
+ * still shows results from the old socket, so it is not "at" the new socket's ts; mutation completion waits.
95
+ */
96
+ resyncQuerySetVersion = null;
97
+ // Auth
98
+ auth = null;
99
+ authToken = null;
100
+ /** The token held by the server on this socket (null = none sent / cleared). */
101
+ serverToken = null;
102
+ /** Identity version sent on this socket (the server's identity version once processed). */
103
+ identityVersion = 0;
104
+ /** Identity version whose confirmation (a Transition reaching it) turns `isAuthenticated` on. */
105
+ awaitingAuthConfirmation = null;
106
+ isAuthenticated = false;
107
+ authGeneration = 0;
108
+ authRefreshTimer = null;
109
+ removeUnloadListener;
110
+ constructor(url, options = {}) {
111
+ if (typeof url !== "string")
112
+ throw new Error("RxFerrixClient: url must be a string");
113
+ this.url = url;
114
+ this.syncUrl = deriveSyncUrl(url);
115
+ this.sessionId = randomSessionId();
116
+ this.logger = createLogger({
117
+ verbose: options.verbose ?? false,
118
+ reportDebugInfoToConsole: options.reportDebugInfoToConsole ?? false,
119
+ });
120
+ this.optimistic = new OptimisticQueryResults(this.logger);
121
+ const WS = options.webSocketConstructor ?? globalThis.WebSocket;
122
+ if (!WS) {
123
+ throw new Error("RxFerrixClient: no global WebSocket available; pass `webSocketConstructor` (e.g. from the `ws` package)");
124
+ }
125
+ this.ws = new WebSocketManager({ url: this.syncUrl, sessionId: this.sessionId, webSocketConstructor: WS, logger: this.logger }, {
126
+ onOpen: () => this.onSocketOpen(),
127
+ onResume: () => this.syncToServer(),
128
+ onMessage: (message) => this.onMessage(message),
129
+ onClose: () => this.onSocketClosed(),
130
+ onStateChange: () => this.notifyConnectionState(),
131
+ });
132
+ this.cachedConnectionState = this.computeConnectionState();
133
+ this.removeUnloadListener = this.installUnloadListener(options.unsavedChangesWarning);
134
+ this.ws.start();
135
+ }
136
+ // ---------------------------------------------------------------------------------------------------------------
137
+ // Queries
138
+ /**
139
+ * Creates a watch on a query. Nothing is sent until `onUpdate` registers the first callback; all watches on the
140
+ * same `(udfPath, canonicalJSON(args))` share one server subscription.
141
+ */
142
+ watchQuery(ref, ...args) {
143
+ const udfPath = ref._path;
144
+ const normalized = normalizeArgs(args[0]);
145
+ const token = queryToken(udfPath, normalized);
146
+ return {
147
+ onUpdate: (callback) => this.subscribe(token, udfPath, normalized, callback),
148
+ localQueryResult: () => {
149
+ const state = this.optimistic.get(token);
150
+ if (state.status === "error")
151
+ throw state.error;
152
+ return state.status === "success" ? state.value : undefined;
153
+ },
154
+ localQueryState: () => this.optimistic.get(token),
155
+ };
156
+ }
157
+ /** Runs a query once: subscribes, waits for the first result, then unsubscribes. */
158
+ query(ref, ...args) {
159
+ if (this.closed)
160
+ return Promise.reject(new RxFerrixError("Client is closed", { code: CLIENT_CLOSED }));
161
+ const watch = this.watchQuery(ref, ...args);
162
+ return new Promise((resolve, reject) => {
163
+ let unsubscribe = null;
164
+ let done = false;
165
+ const check = () => {
166
+ if (done)
167
+ return;
168
+ const state = watch.localQueryState();
169
+ if (state.status === "loading")
170
+ return;
171
+ done = true;
172
+ if (unsubscribe)
173
+ unsubscribe();
174
+ if (state.status === "success")
175
+ resolve(state.value);
176
+ else
177
+ reject(state.error);
178
+ };
179
+ unsubscribe = watch.onUpdate(check);
180
+ check();
181
+ });
182
+ }
183
+ /**
184
+ * Creates a reactive paginated query over a query that takes `paginationOpts` and returns a `PaginationResult`
185
+ * (see `paginated_query.ts`). Pages are subscribed while the returned object has subscribers.
186
+ *
187
+ * ```ts
188
+ * const messages = client.paginatedQuery(api.messages.list, { channel }, { initialNumItems: 20 });
189
+ * messages.subscribe(() => render(messages.getCurrent())); // { results, status, loadMore, ... }
190
+ * ```
191
+ */
192
+ paginatedQuery(ref, args, options) {
193
+ return new PaginatedQueryImpl(this, ref, args, options);
194
+ }
195
+ subscribe(token, udfPath, args, callback) {
196
+ if (this.closed)
197
+ return () => { };
198
+ let set = this.listeners.get(token);
199
+ if (!set) {
200
+ set = new Set();
201
+ this.listeners.set(token, set);
202
+ }
203
+ // Wrap so the same callback can be registered twice and removed independently.
204
+ const entry = () => callback();
205
+ set.add(entry);
206
+ const { needsFlush } = this.localQueries.addRef(udfPath, args);
207
+ if (needsFlush)
208
+ this.scheduleFlush();
209
+ let active = true;
210
+ return () => {
211
+ if (!active)
212
+ return;
213
+ active = false;
214
+ const current = this.listeners.get(token);
215
+ current?.delete(entry);
216
+ if (current && current.size === 0)
217
+ this.listeners.delete(token);
218
+ if (this.localQueries.removeRef(token))
219
+ this.scheduleFlush();
220
+ };
221
+ }
222
+ /** Batches query-set changes made in the same tick into one ModifyQuerySet. */
223
+ scheduleFlush() {
224
+ if (this.flushScheduled || this.closed)
225
+ return;
226
+ this.flushScheduled = true;
227
+ queueMicrotask(() => {
228
+ this.flushScheduled = false;
229
+ if (this.closed)
230
+ return;
231
+ this.flushQuerySet();
232
+ });
233
+ }
234
+ flushQuerySet() {
235
+ const { message, removed } = this.localQueries.flush(this.ws.canSend());
236
+ if (removed.length > 0) {
237
+ for (const queryId of removed)
238
+ this.remoteQueries.remove(queryId);
239
+ this.recomputeAndNotify();
240
+ }
241
+ if (message)
242
+ this.ws.send(message);
243
+ }
244
+ // ---------------------------------------------------------------------------------------------------------------
245
+ // Mutations and actions
246
+ /**
247
+ * Runs a mutation. The returned promise resolves with the mutation's result once the client's queries reflect the
248
+ * mutation (read-your-writes); it rejects with a {@link RxFerrixError} if the mutation fails.
249
+ */
250
+ mutation(ref, ...argsAndOptions) {
251
+ if (this.closed)
252
+ return Promise.reject(new RxFerrixError("Client is closed", { code: CLIENT_CLOSED }));
253
+ const args = normalizeArgs(argsAndOptions[0]);
254
+ const options = argsAndOptions[1];
255
+ const requestId = this.requests.allocateRequestId();
256
+ const message = { type: "Mutation", requestId, udfPath: ref._path, args };
257
+ const promise = this.requests.trackMutation(message);
258
+ if (options?.optimisticUpdate) {
259
+ const update = options.optimisticUpdate;
260
+ const typedArgs = args;
261
+ this.optimistic.addUpdate(requestId, (store) => update(store, typedArgs));
262
+ this.recomputeAndNotify();
263
+ }
264
+ this.sendUnsentRequests();
265
+ this.notifyConnectionState();
266
+ return promise;
267
+ }
268
+ /** Runs an action. Rejects with a "connection lost" error if the socket drops while it is in flight. */
269
+ action(ref, ...args) {
270
+ if (this.closed)
271
+ return Promise.reject(new RxFerrixError("Client is closed", { code: CLIENT_CLOSED }));
272
+ const requestId = this.requests.allocateRequestId();
273
+ const message = { type: "Action", requestId, udfPath: ref._path, args: normalizeArgs(args[0]) };
274
+ const promise = this.requests.trackAction(message);
275
+ this.sendUnsentRequests();
276
+ this.notifyConnectionState();
277
+ return promise;
278
+ }
279
+ sendUnsentRequests() {
280
+ if (!this.ws.canSend())
281
+ return;
282
+ for (const message of this.requests.unsent()) {
283
+ if (!this.ws.send(message))
284
+ break;
285
+ this.requests.markSent(message.requestId);
286
+ }
287
+ }
288
+ // ---------------------------------------------------------------------------------------------------------------
289
+ // Auth
290
+ /**
291
+ * Sets the auth token source. The client fetches a token right away (holding back query subscriptions until it
292
+ * has one), sends it with `Authenticate`, re-sends it on every reconnect, refreshes JWTs shortly before they expire,
293
+ * and retries once with `forceRefresh: true` when the server rejects the token.
294
+ *
295
+ * `onChange(true)` fires once the server has confirmed the token; `onChange(false)` when auth is lost or cleared.
296
+ */
297
+ setAuth(fetchToken, onChange) {
298
+ if (this.closed)
299
+ return;
300
+ this.auth = { fetchToken, onChange, retriedAfterAuthError: false };
301
+ void this.fetchAndApplyToken(false, true);
302
+ }
303
+ /** Removes the token: the server falls back to an anonymous identity. */
304
+ clearAuth() {
305
+ const previous = this.auth;
306
+ this.auth = null;
307
+ this.authGeneration++;
308
+ this.clearAuthRefreshTimer();
309
+ this.applyToken(null);
310
+ if (this.ws.isPaused)
311
+ this.ws.resume();
312
+ this.setAuthenticated(false, previous?.onChange);
313
+ }
314
+ async fetchAndApplyToken(forceRefresh, pause) {
315
+ const auth = this.auth;
316
+ if (!auth)
317
+ return;
318
+ const generation = ++this.authGeneration;
319
+ if (pause)
320
+ this.ws.pause();
321
+ let token = null;
322
+ try {
323
+ token = (await auth.fetchToken({ forceRefresh })) ?? null;
324
+ }
325
+ catch (e) {
326
+ this.logger.error("fetchToken threw; continuing unauthenticated", e);
327
+ token = null;
328
+ }
329
+ if (generation !== this.authGeneration || this.auth !== auth || this.closed)
330
+ return;
331
+ this.applyToken(token);
332
+ if (token === null)
333
+ this.setAuthenticated(false, auth.onChange);
334
+ this.scheduleTokenRefresh(token);
335
+ if (pause)
336
+ this.ws.resume();
337
+ }
338
+ /** Records the desired token and sends `Authenticate` when the server's token differs. */
339
+ applyToken(token) {
340
+ this.authToken = token;
341
+ this.syncToServer();
342
+ }
343
+ sendAuthenticateIfNeeded() {
344
+ if (this.authToken === this.serverToken)
345
+ return;
346
+ const baseVersion = this.identityVersion;
347
+ const sent = this.ws.send({ type: "Authenticate", baseVersion, token: this.authToken });
348
+ if (!sent)
349
+ return;
350
+ this.identityVersion = baseVersion + 1;
351
+ this.serverToken = this.authToken;
352
+ this.awaitingAuthConfirmation = this.authToken !== null ? this.identityVersion : null;
353
+ }
354
+ scheduleTokenRefresh(token) {
355
+ this.clearAuthRefreshTimer();
356
+ if (!token)
357
+ return;
358
+ const exp = jwtExpiry(token);
359
+ if (exp === null)
360
+ return;
361
+ const delay = Math.min(MAX_TIMEOUT_MS, Math.max(0, exp * 1000 - Date.now() - TOKEN_REFRESH_LEEWAY_MS));
362
+ this.authRefreshTimer = setTimeout(() => {
363
+ this.authRefreshTimer = null;
364
+ void this.fetchAndApplyToken(true, false);
365
+ }, delay);
366
+ }
367
+ clearAuthRefreshTimer() {
368
+ if (this.authRefreshTimer !== null) {
369
+ clearTimeout(this.authRefreshTimer);
370
+ this.authRefreshTimer = null;
371
+ }
372
+ }
373
+ onAuthError(message) {
374
+ this.logger.warn(`authentication rejected: ${message.error}`);
375
+ const auth = this.auth;
376
+ // The server closes the socket after AuthError; the next socket must not resend the rejected token blindly.
377
+ this.ws.reconnect("AuthError");
378
+ if (auth && !auth.retriedAfterAuthError) {
379
+ auth.retriedAfterAuthError = true;
380
+ void this.fetchAndApplyToken(true, true);
381
+ return;
382
+ }
383
+ this.authToken = null;
384
+ this.clearAuthRefreshTimer();
385
+ this.setAuthenticated(false, auth?.onChange);
386
+ }
387
+ setAuthenticated(value, onChange) {
388
+ const changed = this.isAuthenticated !== value;
389
+ this.isAuthenticated = value;
390
+ if (changed)
391
+ this.notifyConnectionState();
392
+ if (onChange && (changed || !value)) {
393
+ try {
394
+ onChange(value);
395
+ }
396
+ catch (e) {
397
+ this.logger.error("auth onChange threw", e);
398
+ }
399
+ }
400
+ }
401
+ // ---------------------------------------------------------------------------------------------------------------
402
+ // Socket lifecycle
403
+ /** A new socket is open and `Connect` was sent: rebuild the server's state from scratch. */
404
+ onSocketOpen() {
405
+ this.remoteQueries.resetVersion();
406
+ this.localQueries.resetForNewSocket();
407
+ this.identityVersion = 0;
408
+ this.serverToken = null;
409
+ this.awaitingAuthConfirmation = null;
410
+ this.syncToServer();
411
+ // The view still shows the previous socket's results until the re-added queries report from this socket.
412
+ const resent = this.localQueries.sentQuerySetVersion;
413
+ this.resyncQuerySetVersion = resent > 0 ? resent : null;
414
+ }
415
+ /** Sends everything the server does not know yet, in protocol order: Authenticate, ModifyQuerySet, requests. */
416
+ syncToServer() {
417
+ if (!this.ws.canSend())
418
+ return;
419
+ this.sendAuthenticateIfNeeded();
420
+ this.flushQuerySet();
421
+ this.sendUnsentRequests();
422
+ }
423
+ onSocketClosed() {
424
+ const rejected = this.requests.onSocketClosed();
425
+ for (const r of rejected)
426
+ r.settle();
427
+ if (rejected.length > 0)
428
+ this.notifyConnectionState();
429
+ }
430
+ onMessage(message) {
431
+ switch (message.type) {
432
+ case "Transition":
433
+ this.onTransition(message);
434
+ return;
435
+ case "MutationResponse": {
436
+ const udfPath = this.requests.udfPathOf(message.requestId) ?? "?";
437
+ this.logger.logLines("mutation", udfPath, message.logLines);
438
+ const settled = this.requests.onMutationResponse(message, this.observedTs());
439
+ if (settled)
440
+ this.finishMutations([settled]);
441
+ return;
442
+ }
443
+ case "ActionResponse": {
444
+ const udfPath = this.requests.udfPathOf(message.requestId) ?? "?";
445
+ this.logger.logLines("action", udfPath, message.logLines);
446
+ const settle = this.requests.onActionResponse(message);
447
+ if (settle) {
448
+ settle();
449
+ this.notifyConnectionState();
450
+ }
451
+ return;
452
+ }
453
+ case "FatalError":
454
+ this.logger.error(`server reported a fatal error: ${message.error}`);
455
+ this.ws.reconnect(`FatalError: ${message.error}`);
456
+ return;
457
+ case "AuthError":
458
+ this.onAuthError(message);
459
+ return;
460
+ case "Ping":
461
+ return; // Pong is sent by the socket manager.
462
+ default:
463
+ this.logger.warn("unknown server message", message);
464
+ }
465
+ }
466
+ /** The ts the local view is consistent with, or null while resyncing after a reconnect. */
467
+ observedTs() {
468
+ return this.resyncQuerySetVersion === null ? this.remoteQueries.version.ts : null;
469
+ }
470
+ onTransition(message) {
471
+ let result;
472
+ try {
473
+ result = this.remoteQueries.transition(message, (queryId) => this.localQueries.getById(queryId) !== undefined);
474
+ }
475
+ catch (e) {
476
+ if (e instanceof TransitionVersionMismatch) {
477
+ this.logger.warn(e.message);
478
+ this.ws.reconnect("TransitionVersionMismatch");
479
+ return;
480
+ }
481
+ if (e instanceof DiffMismatch) {
482
+ // A new connection starts from full results.
483
+ this.logger.warn(e.message);
484
+ this.ws.reconnect("DiffMismatch");
485
+ return;
486
+ }
487
+ throw e;
488
+ }
489
+ this.ws.markHealthy();
490
+ for (const { queryId, lines } of result.logLines) {
491
+ this.logger.logLines("query", this.localQueries.getById(queryId)?.udfPath ?? "?", lines);
492
+ }
493
+ const end = message.endVersion;
494
+ if (this.resyncQuerySetVersion !== null && end.querySet >= this.resyncQuerySetVersion) {
495
+ this.resyncQuerySetVersion = null;
496
+ }
497
+ if (this.awaitingAuthConfirmation !== null && end.identity >= this.awaitingAuthConfirmation) {
498
+ this.awaitingAuthConfirmation = null;
499
+ if (this.auth)
500
+ this.auth.retriedAfterAuthError = false;
501
+ this.setAuthenticated(true, this.auth?.onChange);
502
+ }
503
+ const ts = this.observedTs();
504
+ const settled = ts === null ? [] : this.requests.removeCompleted(ts);
505
+ this.finishMutations(settled, result.changed.length > 0);
506
+ }
507
+ /** Drops the settled mutations' optimistic updates, updates the view and notifies watchers, then settles. */
508
+ finishMutations(settled, forceRecompute = false) {
509
+ this.optimistic.dropUpdates(settled.map((s) => s.requestId));
510
+ if (forceRecompute || settled.length > 0)
511
+ this.recomputeAndNotify();
512
+ for (const s of settled)
513
+ s.settle();
514
+ if (settled.length > 0)
515
+ this.notifyConnectionState();
516
+ }
517
+ // ---------------------------------------------------------------------------------------------------------------
518
+ // View
519
+ serverView() {
520
+ const view = new Map();
521
+ for (const query of this.localQueries.queries()) {
522
+ const state = this.remoteQueries.result(query.queryId);
523
+ if (state)
524
+ view.set(query.token, { udfPath: query.udfPath, args: query.args, state });
525
+ }
526
+ return view;
527
+ }
528
+ /** Rebuilds the visible view; after the whole update is applied, notifies the watchers of changed queries. */
529
+ recomputeAndNotify() {
530
+ const changed = this.optimistic.recompute(this.serverView());
531
+ const callbacks = [];
532
+ for (const token of changed) {
533
+ const set = this.listeners.get(token);
534
+ if (set)
535
+ callbacks.push(...set);
536
+ }
537
+ for (const callback of callbacks) {
538
+ try {
539
+ callback();
540
+ }
541
+ catch (e) {
542
+ this.logger.error("query watcher threw", e);
543
+ }
544
+ }
545
+ }
546
+ // ---------------------------------------------------------------------------------------------------------------
547
+ // Connection state
548
+ /** The current connection state. Referentially stable until something changes. */
549
+ connectionState() {
550
+ return this.cachedConnectionState;
551
+ }
552
+ subscribeToConnectionState(callback) {
553
+ this.connectionListeners.add(callback);
554
+ return () => {
555
+ this.connectionListeners.delete(callback);
556
+ };
557
+ }
558
+ computeConnectionState() {
559
+ const counts = this.requests.counts();
560
+ return {
561
+ isWebSocketConnected: this.ws.state === "ready",
562
+ hasInflightRequests: counts.mutations + counts.actions > 0,
563
+ hasEverConnected: this.ws.hasEverConnected,
564
+ connectionCount: this.ws.connectionCount,
565
+ connectionRetries: this.ws.connectionRetries,
566
+ inflightMutations: counts.mutations,
567
+ inflightActions: counts.actions,
568
+ timeOfOldestInflightRequest: counts.oldestStartedAt === null ? null : new Date(counts.oldestStartedAt),
569
+ isAuthenticated: this.isAuthenticated,
570
+ };
571
+ }
572
+ notifyConnectionState() {
573
+ // Called from the socket manager's constructor path before fields are ready.
574
+ if (!this.connectionListeners)
575
+ return;
576
+ const next = this.computeConnectionState();
577
+ const prev = this.cachedConnectionState;
578
+ if (prev &&
579
+ prev.isWebSocketConnected === next.isWebSocketConnected &&
580
+ prev.hasInflightRequests === next.hasInflightRequests &&
581
+ prev.hasEverConnected === next.hasEverConnected &&
582
+ prev.connectionCount === next.connectionCount &&
583
+ prev.connectionRetries === next.connectionRetries &&
584
+ prev.inflightMutations === next.inflightMutations &&
585
+ prev.inflightActions === next.inflightActions &&
586
+ prev.timeOfOldestInflightRequest?.getTime() === next.timeOfOldestInflightRequest?.getTime() &&
587
+ prev.isAuthenticated === next.isAuthenticated) {
588
+ return;
589
+ }
590
+ this.cachedConnectionState = next;
591
+ for (const listener of [...this.connectionListeners]) {
592
+ try {
593
+ listener(next);
594
+ }
595
+ catch (e) {
596
+ this.logger.error("connection state listener threw", e);
597
+ }
598
+ }
599
+ }
600
+ // ---------------------------------------------------------------------------------------------------------------
601
+ /** Closes the socket for good. Pending mutations and actions are rejected. */
602
+ close() {
603
+ if (this.closed)
604
+ return;
605
+ this.closed = true;
606
+ this.authGeneration++;
607
+ this.clearAuthRefreshTimer();
608
+ this.ws.stop();
609
+ this.removeUnloadListener();
610
+ this.requests.rejectAll(new RxFerrixError("Client is closed", { code: CLIENT_CLOSED }));
611
+ this.listeners.clear();
612
+ this.notifyConnectionState();
613
+ }
614
+ installUnloadListener(enabled) {
615
+ const w = globalThis;
616
+ if (enabled === false || typeof w.window === "undefined" || typeof w.addEventListener !== "function") {
617
+ return () => { };
618
+ }
619
+ const handler = (e) => {
620
+ if (!this.requests.hasInflightMutations())
621
+ return;
622
+ e.preventDefault();
623
+ const message = "Changes you made may not be saved. Are you sure you want to leave?";
624
+ e.returnValue = message;
625
+ return message;
626
+ };
627
+ w.addEventListener("beforeunload", handler);
628
+ return () => w.removeEventListener?.("beforeunload", handler);
629
+ }
630
+ /** @internal Exposed for tests and devtools. */
631
+ get _debug() {
632
+ const queryIds = new Map();
633
+ for (const q of this.localQueries.queries())
634
+ queryIds.set(q.token, q.queryId);
635
+ return { queryIds };
636
+ }
637
+ }
638
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}