@rebasepro/client 0.24.0 → 0.24.1-canary.gcb918fc

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.
@@ -1,8 +1,11 @@
1
- import { DeleteProps, CollectionConfig, FetchCollectionProps, ListenCollectionProps, FetchOneProps, SaveProps, CollectionUpdateMeta, ChannelMessage, TableMetadata, BranchInfo, RebaseApiError, type RealtimeConnectionState } from "@rebasepro/types";
1
+ import { DeleteProps, CollectionConfig, FetchCollectionProps, ListenCollectionProps, FetchOneProps, ListenOneTarget, SaveProps, CollectionUpdateMeta, ChannelMessage, TableMetadata, BranchInfo, RebaseApiError, type RealtimeConnectionState } from "@rebasepro/types";
2
2
  import type { SqlScriptResult } from "@rebasepro/types";
3
3
  export interface RebaseWebSocketConfig {
4
4
  websocketUrl: string;
5
- /** Optional auth token getter for WebSocket authentication */
5
+ /**
6
+ * Where the token the socket authenticates with comes from, asked each
7
+ * time it authenticates. A falsy answer leaves it anonymous.
8
+ */
6
9
  getAuthToken?: () => Promise<string | null>;
7
10
  /** Optional WebSocket constructor to override globalThis.WebSocket (e.g. for Node environments) */
8
11
  WebSocket?: typeof WebSocket;
@@ -17,6 +20,11 @@ export interface RebaseWebSocketConfig {
17
20
  export declare class RebaseWebSocketClient {
18
21
  private websocketUrl;
19
22
  private ws;
23
+ /**
24
+ * Where the socket's token comes from. A client built by
25
+ * `createRebaseClient()` resolves it through the HTTP transport, so
26
+ * `client.setAuthTokenGetter()` and `client.setToken()` reach both.
27
+ */
20
28
  getAuthToken?: () => Promise<string | null>;
21
29
  private listeners;
22
30
  /** Channel-name → handlers, for broadcast and presence frames. */
@@ -68,6 +76,26 @@ export declare class RebaseWebSocketClient {
68
76
  get hasSocket(): boolean;
69
77
  /** So the "no WebSocket in this environment" warning is said once, not per call. */
70
78
  private warnedNoWebSocket;
79
+ /**
80
+ * What the server said in its `hello` it does for this socket: empty
81
+ * until then, after a close, and for a server that sends no `hello`.
82
+ */
83
+ private serverOptIns;
84
+ /** This socket's id on the server, from its `hello` (with `channel_seq`). */
85
+ private serverClientId;
86
+ /** When the current socket last delivered anything, heartbeats included. */
87
+ private lastFrameAt;
88
+ private livenessTimer;
89
+ /** Give up on the current socket as though it had closed. Set per socket. */
90
+ private dropSocket;
91
+ /** Whether the server agreed, in its `hello`, to `name` for this socket. */
92
+ hasServerOptIn(name: string): boolean;
93
+ /**
94
+ * This socket's id on the server, as its broadcasts' `senderId` in a
95
+ * channel's history. Known once a server that numbers retained channels
96
+ * for it (`channel_seq`) has said hello.
97
+ */
98
+ get socketClientId(): string | undefined;
71
99
  /** Subscribe to broadcast/presence frames for one channel. */
72
100
  onChannelMessage(channel: string, handler: (message: ChannelMessage) => void): () => void;
73
101
  /** Notified after the socket comes back, so channels can re-join. */
@@ -94,11 +122,11 @@ export declare class RebaseWebSocketClient {
94
122
  */
95
123
  private maxReconnectAttempts;
96
124
  /**
97
- * How many failed redials make a blip an outage: the point at which every
98
- * registration is told `CONNECTION_LOST` and {@link state} reads
99
- * `disconnected`. Three is 2 + 4 + 8 s of backoff, about 14 s down.
125
+ * Reports the outage once the connection has been down for
126
+ * {@link OUTAGE_REPORT_AFTER_MS}. Armed by the first redial after a drop,
127
+ * cleared when a socket opens or the caller disconnects.
100
128
  */
101
- private lostAfterAttempts;
129
+ private outageTimer;
102
130
  /**
103
131
  * Whether a socket of this client has ever opened — what makes the next
104
132
  * open a *reconnect*, whose server has forgotten every subscription and
@@ -150,7 +178,13 @@ export declare class RebaseWebSocketClient {
150
178
  */
151
179
  authenticate(token: string): Promise<void>;
152
180
  /**
153
- * Set the auth token getter function
181
+ * Replace where this socket's token comes from, and authenticate an open,
182
+ * unauthenticated socket with it.
183
+ *
184
+ * @deprecated Use `client.setAuthTokenGetter()` instead — on a client from
185
+ * `createRebaseClient()` the socket already resolves its token through it,
186
+ * together with HTTP, and setting one here splits the two. Will be removed
187
+ * in a future release.
154
188
  */
155
189
  setAuthTokenGetter(getAuthToken: () => Promise<string | null>): void;
156
190
  /**
@@ -163,6 +197,15 @@ export declare class RebaseWebSocketClient {
163
197
  */
164
198
  disconnect(permanent?: boolean): void;
165
199
  private initWebSocket;
200
+ /** Read the server's `hello`: what it agreed to, and start watching for heartbeats. */
201
+ private receiveHello;
202
+ /**
203
+ * Redial when two heartbeats in a row have not arrived. Anything the
204
+ * server sends counts as a beat, so a busy socket is never judged on them.
205
+ */
206
+ private watchLiveness;
207
+ private stopLivenessWatch;
208
+ private forgetServerOptIns;
166
209
  private processMessageQueue;
167
210
  /**
168
211
  * Whether a frame that waited in the queue should go out on the socket
@@ -193,6 +236,7 @@ export declare class RebaseWebSocketClient {
193
236
  * failed. When the socket is back they are re-subscribed, and the fresh
194
237
  * `onUpdate` is the recovery.
195
238
  */
239
+ private clearOutageTimer;
196
240
  private reportConnectionLost;
197
241
  private notifyError;
198
242
  /**
@@ -231,6 +275,14 @@ export declare class RebaseWebSocketClient {
231
275
  fetchOne<M extends Record<string, unknown>>(props: FetchOneProps<M>): Promise<Record<string, unknown> | undefined>;
232
276
  save<M extends Record<string, unknown>>(props: SaveProps<M>): Promise<Record<string, unknown>>;
233
277
  delete<M extends Record<string, unknown>>(props: DeleteProps<M>): Promise<void>;
278
+ /**
279
+ * @deprecated Will leave the public `client.ws` type in the next minor.
280
+ * Not part of the app-facing client: the admin UI's SQL console reaches it
281
+ * through `<Rebase>`, and it answers only a caller with `database:write`.
282
+ * App code has no supported SQL or branch path on the client; run SQL
283
+ * server-side (`isSQLAdmin(driver.admin)`), and use `client.admin` for
284
+ * users and roles.
285
+ */
234
286
  executeSql(sql: string, options?: {
235
287
  database?: string;
236
288
  role?: string;
@@ -244,7 +296,14 @@ export declare class RebaseWebSocketClient {
244
296
  runSqlScript(sql: string, options?: {
245
297
  database?: string;
246
298
  role?: string;
299
+ signal?: AbortSignal;
247
300
  }): Promise<SqlScriptResult>;
301
+ /**
302
+ * Stop a console run its caller gave up on: never written if it has not
303
+ * been yet, and cancelled on a server whose `hello` listed `cancel_sql`. A server
304
+ * that does not is left to finish it, bounded by its `statement_timeout`.
305
+ */
306
+ private cancelSqlRun;
248
307
  fetchAvailableDatabases(): Promise<string[]>;
249
308
  fetchAvailableRoles(): Promise<string[]>;
250
309
  fetchApplicationRoles(): Promise<string[]>;
@@ -253,17 +312,41 @@ export declare class RebaseWebSocketClient {
253
312
  count<M extends Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<number>;
254
313
  fetchUnmappedTables(mappedPaths?: string[]): Promise<string[]>;
255
314
  fetchTableMetadata(tableName: string): Promise<TableMetadata>;
315
+ /**
316
+ * @deprecated Will leave the public `client.ws` type in the next minor.
317
+ * Not part of the app-facing client: the admin UI's SQL console reaches it
318
+ * through `<Rebase>`, and it answers only a caller with `database:write`.
319
+ * App code has no supported SQL or branch path on the client; run SQL
320
+ * server-side (`isSQLAdmin(driver.admin)`), and use `client.admin` for
321
+ * users and roles.
322
+ */
256
323
  createBranch(name: string, options?: {
257
324
  source?: string;
258
325
  }): Promise<BranchInfo>;
326
+ /**
327
+ * @deprecated Will leave the public `client.ws` type in the next minor.
328
+ * Not part of the app-facing client: the admin UI's SQL console reaches it
329
+ * through `<Rebase>`, and it answers only a caller with `database:write`.
330
+ * App code has no supported SQL or branch path on the client; run SQL
331
+ * server-side (`isSQLAdmin(driver.admin)`), and use `client.admin` for
332
+ * users and roles.
333
+ */
259
334
  deleteBranch(name: string): Promise<void>;
260
335
  listBranches(): Promise<BranchInfo[]>;
261
336
  /**
262
- * Recursively compare two values for structural equality.
263
- * Handles primitives, null, undefined, Date, RegExp, arrays, and plain objects.
337
+ * Recursively compare two values a refetch can carry for structural
338
+ * equality: primitives, null, undefined, Date, RegExp, arrays and objects.
339
+ *
340
+ * A relation compares by the reference it holds, not by the row it happens
341
+ * to have loaded, so its `data` is left out on both sides. That used to be
342
+ * done by normalising each side into a copy first — two deep copies of
343
+ * every cached row on every frame, most of which then compared equal. It is
344
+ * done in place now, and an unchanged row costs no copy.
345
+ *
346
+ * `relationAware` is off for a relation's own fields: the copies never
347
+ * looked inside those either.
264
348
  */
265
349
  private deepEqual;
266
- private normalizeForComparison;
267
350
  /**
268
351
  * The address of a row, for matching it against another copy of itself.
269
352
  *
@@ -285,7 +368,7 @@ export declare class RebaseWebSocketClient {
285
368
  */
286
369
  private mergeRows;
287
370
  listenCollection<M extends Record<string, unknown>>(props: Omit<ListenCollectionProps<M>, "onUpdate" | "onError">, onUpdate: (rows: Record<string, unknown>[], meta?: CollectionUpdateMeta) => void, onError?: (error: Error) => void): () => void;
288
- listenOne<M extends Record<string, unknown>>(props: FetchOneProps<M>, onUpdate: (row: Record<string, unknown> | null) => void, onError?: (error: Error) => void): () => void;
371
+ listenOne<M extends Record<string, unknown>>(props: ListenOneTarget<M>, onUpdate: (row: Record<string, unknown> | null) => void, onError?: (error: Error) => void): () => void;
289
372
  /**
290
373
  * Send a `subscribe_collection` for an already-registered subscription and
291
374
  * arm its watchdog.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rebasepro/client",
3
- "version": "0.24.0",
3
+ "version": "0.24.1-canary.gcb918fc",
4
4
  "description": "HTTP SDK client for the Rebase custom backend",
5
5
  "keywords": [
6
6
  "rebase",
@@ -41,9 +41,9 @@
41
41
  "./package.json": "./package.json"
42
42
  },
43
43
  "dependencies": {
44
- "@rebasepro/common": "0.24.0",
45
- "@rebasepro/utils": "0.24.0",
46
- "@rebasepro/types": "0.24.0"
44
+ "@rebasepro/common": "0.24.1-canary.gcb918fc",
45
+ "@rebasepro/types": "0.24.1-canary.gcb918fc",
46
+ "@rebasepro/utils": "0.24.1-canary.gcb918fc"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@jest/globals": "^30.4.1",
@@ -1 +0,0 @@
1
- export { QueryBuilder, or, and, cond } from "@rebasepro/common";