@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.
- package/dist/api.d.ts +60 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +22 -0
- package/dist/api.js.map +1 -0
- package/dist/auth.d.ts +256 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +541 -0
- package/dist/auth.js.map +1 -0
- package/dist/bytes.d.ts +21 -0
- package/dist/bytes.d.ts.map +1 -0
- package/dist/bytes.js +51 -0
- package/dist/bytes.js.map +1 -0
- package/dist/canonical.d.ts +13 -0
- package/dist/canonical.d.ts.map +1 -0
- package/dist/canonical.js +66 -0
- package/dist/canonical.js.map +1 -0
- package/dist/client.d.ts +170 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +638 -0
- package/dist/client.js.map +1 -0
- package/dist/diff.d.ts +20 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +100 -0
- package/dist/diff.js.map +1 -0
- package/dist/errors.d.ts +24 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +34 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/local_query_set.d.ts +56 -0
- package/dist/local_query_set.d.ts.map +1 -0
- package/dist/local_query_set.js +108 -0
- package/dist/local_query_set.js.map +1 -0
- package/dist/logging.d.ts +15 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +17 -0
- package/dist/logging.js.map +1 -0
- package/dist/optimistic_updates.d.ts +48 -0
- package/dist/optimistic_updates.d.ts.map +1 -0
- package/dist/optimistic_updates.js +113 -0
- package/dist/optimistic_updates.js.map +1 -0
- package/dist/paginated_query.d.ts +118 -0
- package/dist/paginated_query.d.ts.map +1 -0
- package/dist/paginated_query.js +199 -0
- package/dist/paginated_query.js.map +1 -0
- package/dist/protocol.d.ts +136 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +11 -0
- package/dist/protocol.js.map +1 -0
- package/dist/query_state.d.ts +16 -0
- package/dist/query_state.d.ts.map +1 -0
- package/dist/query_state.js +2 -0
- package/dist/query_state.js.map +1 -0
- package/dist/remote_query_set.d.ts +37 -0
- package/dist/remote_query_set.d.ts.map +1 -0
- package/dist/remote_query_set.js +87 -0
- package/dist/remote_query_set.js.map +1 -0
- package/dist/request_manager.d.ts +57 -0
- package/dist/request_manager.d.ts.map +1 -0
- package/dist/request_manager.js +163 -0
- package/dist/request_manager.js.map +1 -0
- package/dist/storage.d.ts +45 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +120 -0
- package/dist/storage.js.map +1 -0
- package/dist/testing.d.ts +68 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +97 -0
- package/dist/testing.js.map +1 -0
- package/dist/web_socket_manager.d.ts +88 -0
- package/dist/web_socket_manager.d.ts.map +1 -0
- package/dist/web_socket_manager.js +291 -0
- package/dist/web_socket_manager.js.map +1 -0
- package/package.json +50 -4
- package/src/api.ts +86 -0
- package/src/auth.ts +646 -0
- package/src/bytes.ts +57 -0
- package/src/canonical.ts +61 -0
- package/src/client.ts +740 -0
- package/src/diff.ts +87 -0
- package/src/errors.ts +36 -0
- package/src/index.ts +60 -0
- package/src/local_query_set.ts +130 -0
- package/src/logging.ts +26 -0
- package/src/optimistic_updates.ts +137 -0
- package/src/paginated_query.ts +299 -0
- package/src/protocol.ts +152 -0
- package/src/query_state.ts +12 -0
- package/src/remote_query_set.ts +105 -0
- package/src/request_manager.ts +199 -0
- package/src/storage.ts +171 -0
- package/src/testing.ts +120 -0
- package/src/web_socket_manager.ts +322 -0
- 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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"}
|