@rebasepro/client 0.25.0 → 0.26.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.
@@ -88,6 +88,9 @@ export interface PendingMutation {
88
88
  *
89
89
  * An `update` or `delete` carries only the key: its queued request is the
90
90
  * one it sent, since nothing is merged into an op that has `sent`.
91
+ *
92
+ * A queued create or update is marked too, before its first replay goes
93
+ * out, for the same reason: from then on the server may hold it.
91
94
  */
92
95
  sent?: {
93
96
  idempotencyKey: string;
@@ -97,6 +100,13 @@ export interface PendingMutation {
97
100
  id?: string | number;
98
101
  /** `createMany`: the conflict target the batch was sent with. */
99
102
  onConflict?: readonly string[];
103
+ /**
104
+ * A `create` replayed folded into a `replayBatchSize` run: that run's
105
+ * key. While the run is still whole in the queue it is sent again as
106
+ * that same request; otherwise each member replays alone, under its
107
+ * own key.
108
+ */
109
+ run?: string;
100
110
  };
101
111
  queuedAt: number;
102
112
  /**
package/dist/offline.d.ts CHANGED
@@ -100,7 +100,8 @@ export interface OfflineConfig {
100
100
  * A row last seen in a `find()` or `listen()` list has no version, and an
101
101
  * edit made on top of another queued write to the same row has none
102
102
  * either; those replay without a precondition. A caller's own `ifMatch` is
103
- * kept on a queued edit too.
103
+ * kept on a queued edit or delete too — without this option as well, when
104
+ * a 412 over it is a refusal like any other.
104
105
  *
105
106
  * The queue waits while this runs, so a prompt can ask the user. Without
106
107
  * it — the default — replay sends no precondition and the last writer
@@ -379,6 +380,22 @@ export declare class OfflineManager {
379
380
  private ticket;
380
381
  /** The ticket of whoever the held scope turns out to be. */
381
382
  private nextTicket;
383
+ private currentTicket;
384
+ /**
385
+ * Whether a write may go to the server now. Not while the scope is the last
386
+ * user's, unconfirmed: it would go out with no credentials, as nobody. It
387
+ * queues for its author instead, as it does offline.
388
+ */
389
+ private sendsWrites;
390
+ private readonly reachedUnconfirmedListeners;
391
+ /**
392
+ * `listener` runs when a request made while the scope is unconfirmed
393
+ * reached the server: the connection is back, so the session can be asked
394
+ * about. The client wires it to the same confirmation the status listener
395
+ * runs — the status may never have said the connection was gone.
396
+ */
397
+ onReachedUnconfirmed(listener: () => void): () => void;
398
+ private reachedUnconfirmed;
382
399
  /** Whether an operation's user is still the signed-in one. */
383
400
  private isCurrent;
384
401
  /**
@@ -587,6 +604,14 @@ export declare class OfflineManager {
587
604
  */
588
605
  private replayRun;
589
606
  private replay;
607
+ /**
608
+ * Record a queued create as sent, with the request about to go out, and
609
+ * persist it — before the request, so a lost answer cannot leave it
610
+ * unmarked. One already marked (sent online before it was queued, or by
611
+ * an earlier replay) keeps what it holds: that is the request the server
612
+ * may have stored.
613
+ */
614
+ private markCreateSent;
590
615
  /**
591
616
  * Send a queued write under its key.
592
617
  *
@@ -259,6 +259,14 @@ export declare class RebaseRealtimeChannel {
259
259
  * A refusal therefore arrives on {@link onError}, not as a rejection here.
260
260
  */
261
261
  broadcast(event: string, payload: unknown): Promise<void>;
262
+ /**
263
+ * The socket ids this channel has broadcast from — the current one and the
264
+ * ones before a reconnect. A message in history from any of them is this
265
+ * client's own, and a sender is never sent its own messages: replayed after
266
+ * a reconnect whose `broadcast_ack` was lost, it was applied twice.
267
+ */
268
+ private readonly ownSenderIds;
269
+ private rememberOwnSender;
262
270
  /**
263
271
  * Observe refusals about this channel.
264
272
  *
@@ -16,6 +16,11 @@ export interface RebaseWebSocketConfig {
16
16
  * `RebaseClientConfig.impersonate`. Sent with every `AUTHENTICATE`.
17
17
  */
18
18
  impersonate?: string;
19
+ /**
20
+ * Log the connection's progress — opened, signed in, closed, redialling —
21
+ * with `console.debug`. Off by default. See `CreateRebaseClientOptions.debug`.
22
+ */
23
+ debug?: boolean;
19
24
  }
20
25
  export declare class RebaseWebSocketClient {
21
26
  private websocketUrl;
@@ -149,6 +154,19 @@ export declare class RebaseWebSocketClient {
149
154
  onUnauthorized?: () => Promise<boolean>;
150
155
  private refreshInProgress;
151
156
  private readonly impersonate?;
157
+ private readonly debug;
158
+ /**
159
+ * Connection chatter: the socket opened, signed in, closed, is redialling.
160
+ *
161
+ * Silent unless asked for, with the `debug` option or
162
+ * {@link debugSwitchedOn}. It used to go to `console.debug` in every
163
+ * browser: a public page printed "Connected to PostgreSQL backend" and
164
+ * "WebSocket auto-authenticated" to each visitor's console, naming the
165
+ * backend on every load. In Node, where `console.debug` is `console.log`,
166
+ * it opened a script's stdout ahead of what the script prints. Warnings and
167
+ * errors are not chatter and are always written.
168
+ */
169
+ private connectionDebug;
152
170
  constructor(config: RebaseWebSocketConfig);
153
171
  /**
154
172
  * Open the socket if it is not open (or opening) already.
@@ -173,6 +191,22 @@ export declare class RebaseWebSocketClient {
173
191
  private removeNetworkListeners;
174
192
  private onlineListener;
175
193
  private visibilityListener;
194
+ /** The session this socket's server refused, and why. Cleared when a socket opens. */
195
+ private refusedSession;
196
+ /**
197
+ * Whether `error` is the server refusing the session `token` signs in as —
198
+ * revoked, its account gone or disabled, a token that does not verify. Said
199
+ * once per socket and token, as a warning that names the code.
200
+ */
201
+ private noteSessionRefused;
202
+ /** Whether the current run of ceiling refusals has been said in the console. */
203
+ private socketCeilingWarned;
204
+ /**
205
+ * The server refused this socket for its per-user ceiling. Said once per
206
+ * run of refusals, as a warning, and reported to every registration at
207
+ * once as an outage — a refusal is not a blip that the next dial fixes.
208
+ */
209
+ private noteSocketCeiling;
176
210
  /**
177
211
  * Authenticate the WebSocket connection
178
212
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rebasepro/client",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
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.25.0",
45
- "@rebasepro/utils": "0.25.0",
46
- "@rebasepro/types": "0.25.0"
44
+ "@rebasepro/common": "0.26.0",
45
+ "@rebasepro/utils": "0.26.0",
46
+ "@rebasepro/types": "0.26.0"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@jest/globals": "^30.4.1",