yrby-client 0.4.2 → 0.5.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/README.md CHANGED
@@ -61,10 +61,24 @@ provider.onStatusChange(({ status }) => render(status)); // returns an unsubscri
61
61
  // provider.status -> the current status (same union as above)
62
62
  // provider.awareness -> the provider's Awareness instance (always a fresh one)
63
63
  // provider.synced -> caught up with the server
64
+ // provider.whenSynced -> Promise for the FIRST catch-up (see below)
64
65
  // provider.hasPending -> unacked local edits in flight
65
66
  // provider.destroy() -> tear down
66
67
  ```
67
68
 
69
+ Most rich-text bindings seed an empty document when they mount, so binding
70
+ before the server's state arrives makes each client insert its own
71
+ top-level node. Wait for the first sync before creating the editor:
72
+
73
+ ```js
74
+ provider.connect();
75
+ await provider.whenSynced; // resolves immediately if already synced
76
+ // now hand the doc to the editor binding
77
+ ```
78
+
79
+ It resolves once, on the first catch-up, and stays resolved across later
80
+ reconnects. Use `onStatusChange` to track the live connection.
81
+
68
82
  On `disconnect()` / `destroy()` — and on browser `pagehide` — the provider
69
83
  broadcasts a presence removal so peers drop your cursor immediately instead of
70
84
  waiting for the awareness timeout. `destroy()` is synchronous (the unsubscribe is
@@ -48,6 +48,24 @@ export declare class ActionCableProvider {
48
48
  constructor(doc: Doc, consumer: CableConsumer, channelName: string, channelParams?: object, opts?: ActionCableProviderOptions);
49
49
  /** True once the document has caught up with the server (received a SyncStep2). */
50
50
  get synced(): boolean;
51
+ /**
52
+ * Resolves once the document has first caught up with the server. Most
53
+ * editor bindings seed an empty document when they mount, so binding
54
+ * before the server's state arrives makes each client insert its own
55
+ * top-level node. Create the editor after this resolves:
56
+ *
57
+ * provider.connect();
58
+ * await provider.whenSynced;
59
+ * // now hand the doc to the editor binding
60
+ *
61
+ * Resolves immediately if the first catch-up has already happened, even
62
+ * while the transport is down (`synced` is false during a reconnect;
63
+ * whether the doc has ever synced does not change). It stays resolved
64
+ * across later reconnects; use `onStatusChange` to track the live
65
+ * connection. If the provider is destroyed before the first sync, the
66
+ * promise never settles.
67
+ */
68
+ get whenSynced(): Promise<void>;
51
69
  /** True while there are unacknowledged local document updates in flight. */
52
70
  get hasPending(): boolean;
53
71
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"actioncable_provider.d.ts","sourceRoot":"","sources":["../src/actioncable_provider.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,gBAAgB,EAAe,KAAK,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAEtG,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE/B;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,GAAG,cAAc,CAAC;AAEpF,kDAAkD;AAClD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,oFAAoF;AACpF,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IAC7B,wEAAwE;IACxE,OAAO,CAAC,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACjC,sEAAsE;IACtE,WAAW,CAAC,IAAI,IAAI,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE;QACb,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAAC;KACrE,CAAC;CACH;AAED,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAAC,uBAAuB,EAAE,gBAAgB,GAAG,SAAS,CAAC,CAAC;AAQrG,qBAAa,mBAAmB;;IAC9B,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;gBASjC,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,aAAa,EACvB,WAAW,EAAE,MAAM,EACnB,aAAa,GAAE,MAAW,EAC1B,IAAI,GAAE,0BAA+B;IAiBvC,mFAAmF;IACnF,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,4EAA4E;IAC5E,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAI3C,6DAA6D;IAC7D,IAAI,MAAM,IAAI,cAAc,CAE3B;IAED,oEAAoE;IACpE,cAAc,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI;IAKlE,OAAO,IAAI,IAAI;IAgDf,UAAU,IAAI,IAAI;IAmBlB,OAAO,IAAI,IAAI;CAqDhB"}
1
+ {"version":3,"file":"actioncable_provider.d.ts","sourceRoot":"","sources":["../src/actioncable_provider.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,gBAAgB,EAAe,KAAK,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAEtG,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE/B;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,GAAG,cAAc,CAAC;AAEpF,kDAAkD;AAClD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,oFAAoF;AACpF,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IAC7B,wEAAwE;IACxE,OAAO,CAAC,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACjC,sEAAsE;IACtE,WAAW,CAAC,IAAI,IAAI,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE;QACb,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAAC;KACrE,CAAC;CACH;AAED,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAAC,uBAAuB,EAAE,gBAAgB,GAAG,SAAS,CAAC,CAAC;AAQrG,qBAAa,mBAAmB;;IAC9B,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;gBAiBjC,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,aAAa,EACvB,WAAW,EAAE,MAAM,EACnB,aAAa,GAAE,MAAW,EAC1B,IAAI,GAAE,0BAA+B;IAiBvC,mFAAmF;IACnF,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,IAAI,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAW9B;IAED,4EAA4E;IAC5E,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAI3C,6DAA6D;IAC7D,IAAI,MAAM,IAAI,cAAc,CAE3B;IAED,oEAAoE;IACpE,cAAc,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI;IAKlE,OAAO,IAAI,IAAI;IAuDf,UAAU,IAAI,IAAI;IAmBlB,OAAO,IAAI,IAAI;CAyFhB"}
@@ -10,9 +10,10 @@
10
10
  //
11
11
  // The constructor does not auto-connect: wire up your editor binding first, then
12
12
  // call `connect()`. Watch the connection with `onStatusChange(({ status }) => ...)`
13
- // or the `status` getter. On `disconnect()`/`destroy()`, and on browser
14
- // `pagehide`, the provider broadcasts a presence removal so peers drop our cursor
15
- // right away instead of waiting for the awareness timeout.
13
+ // or the `status` getter. Editors that must not bind before the first sync
14
+ // can `await provider.whenSynced` after connect(). On `disconnect()`/`destroy()`,
15
+ // and on browser `pagehide`, the provider broadcasts a presence removal so peers
16
+ // drop our cursor right away instead of waiting for the awareness timeout.
16
17
  import { YProtocolSession, MessageType } from "./y_protocol_session.js";
17
18
  import { toBase64, fromBase64 } from "./base64.js";
18
19
  import { Awareness } from "y-protocols/awareness";
@@ -28,7 +29,15 @@ export class ActionCableProvider {
28
29
  #connected = false;
29
30
  #status = "disconnected";
30
31
  #statusListeners = new Set();
32
+ #whenSynced = null;
33
+ // `session.synced` resets on every transport drop (a reconnect
34
+ // re-handshakes). Whether the first catch-up has ever happened is tracked
35
+ // separately here, so `whenSynced` does not depend on when it is first
36
+ // read.
37
+ #everSynced = false;
31
38
  #onUnload = null;
39
+ #onRestore = null;
40
+ #stashedPresence = null;
32
41
  constructor(doc, consumer, channelName, channelParams = {}, opts = {}) {
33
42
  this.doc = doc;
34
43
  this.consumer = consumer;
@@ -47,6 +56,36 @@ export class ActionCableProvider {
47
56
  get synced() {
48
57
  return this.session.synced;
49
58
  }
59
+ /**
60
+ * Resolves once the document has first caught up with the server. Most
61
+ * editor bindings seed an empty document when they mount, so binding
62
+ * before the server's state arrives makes each client insert its own
63
+ * top-level node. Create the editor after this resolves:
64
+ *
65
+ * provider.connect();
66
+ * await provider.whenSynced;
67
+ * // now hand the doc to the editor binding
68
+ *
69
+ * Resolves immediately if the first catch-up has already happened, even
70
+ * while the transport is down (`synced` is false during a reconnect;
71
+ * whether the doc has ever synced does not change). It stays resolved
72
+ * across later reconnects; use `onStatusChange` to track the live
73
+ * connection. If the provider is destroyed before the first sync, the
74
+ * promise never settles.
75
+ */
76
+ get whenSynced() {
77
+ this.#whenSynced ??= this.#everSynced
78
+ ? Promise.resolve()
79
+ : new Promise((resolve) => {
80
+ const off = this.onStatusChange(({ status }) => {
81
+ if (status !== "synced")
82
+ return;
83
+ off();
84
+ resolve();
85
+ });
86
+ });
87
+ return this.#whenSynced;
88
+ }
50
89
  /** True while there are unacknowledged local document updates in flight. */
51
90
  get hasPending() {
52
91
  return this.session.hasPending;
@@ -119,6 +158,13 @@ export class ActionCableProvider {
119
158
  provider.session.onDisconnect(); // pause retransmits, clear remote presence
120
159
  provider.#refreshStatus(); // subscription still set -> "connecting" (retrying)
121
160
  },
161
+ rejected() {
162
+ // The channel refused the subscription (auth, missing doc). Surface
163
+ // it and tear down — otherwise the provider sits at "connecting"
164
+ // forever, silently queueing edits. The app decides what's next.
165
+ provider.#onError(new Error("subscription rejected by the server"), "rejected");
166
+ provider.disconnect();
167
+ },
122
168
  });
123
169
  this.#installUnloadHandler();
124
170
  this.#refreshStatus(); // -> "connecting"
@@ -160,24 +206,46 @@ export class ActionCableProvider {
160
206
  if (next === this.#status)
161
207
  return;
162
208
  this.#status = next;
209
+ if (next === "synced")
210
+ this.#everSynced = true;
163
211
  for (const listener of this.#statusListeners)
164
212
  listener({ status: next });
165
213
  }
166
- // Best-effort presence removal when the tab/page goes away (close, navigation,
167
- // bfcache). `pagehide` fires while the socket is still live and is bfcache-safe
168
- // (unlike `beforeunload`, which can block it). Sends are not guaranteed to
169
- // flush on unload, so the server-side awareness timeout remains the backstop.
214
+ // Presence teardown/restore around page lifecycle:
215
+ // - `pagehide`: remove local presence while the socket is still live so peers
216
+ // drop our cursor now (bfcache-safe; the awareness timeout is the backstop).
217
+ // - `pageshow` with `persisted`: the user came BACK (bfcache restore), so put
218
+ // their presence back — editors set awareness once at setup, so without
219
+ // this they'd rejoin as a ghost with no cursor.
170
220
  #installUnloadHandler() {
171
221
  if (typeof window === "undefined" || this.#onUnload)
172
222
  return;
173
- this.#onUnload = () => this.session.removeLocalAwareness();
223
+ this.#onUnload = () => {
224
+ this.#stashedPresence = this.awareness.getLocalState();
225
+ this.session.removeLocalAwareness();
226
+ };
227
+ this.#onRestore = (event) => {
228
+ if (!event.persisted || !this.#stashedPresence)
229
+ return;
230
+ if (this.awareness.getLocalState() === null) {
231
+ this.awareness.setLocalState(this.#stashedPresence);
232
+ }
233
+ this.#stashedPresence = null;
234
+ };
174
235
  window.addEventListener("pagehide", this.#onUnload);
236
+ window.addEventListener("pageshow", this.#onRestore);
175
237
  }
176
238
  #removeUnloadHandler() {
177
- if (typeof window === "undefined" || !this.#onUnload)
239
+ if (typeof window === "undefined")
178
240
  return;
179
- window.removeEventListener("pagehide", this.#onUnload);
180
- this.#onUnload = null;
241
+ if (this.#onUnload) {
242
+ window.removeEventListener("pagehide", this.#onUnload);
243
+ this.#onUnload = null;
244
+ }
245
+ if (this.#onRestore) {
246
+ window.removeEventListener("pageshow", this.#onRestore);
247
+ this.#onRestore = null;
248
+ }
181
249
  }
182
250
  // Send one raw protocol frame over the cable. Awareness frames are whispered
183
251
  // when AnyCable exposes `subscription.whisper`; otherwise they fall back to a
@@ -190,12 +258,28 @@ export class ActionCableProvider {
190
258
  return;
191
259
  const update = toBase64(frame);
192
260
  const isAwareness = frame[0] === MessageType.Awareness;
193
- if (isAwareness && typeof sub.whisper === "function") {
194
- sub.whisper({ awareness: update });
195
- return;
261
+ // Route transport failures (sync throws, or @anycable/web's rejected
262
+ // promises) to onError instead of letting them escape into update
263
+ // handlers. A failed send is recoverable: reliable frames stay queued
264
+ // until acked, and awareness is best-effort anyway.
265
+ try {
266
+ if (isAwareness && typeof sub.whisper === "function") {
267
+ this.#observe(sub.whisper({ awareness: update }));
268
+ return;
269
+ }
270
+ const payload = id === undefined ? { update } : { update, id };
271
+ this.#observe(sub.send(payload));
272
+ }
273
+ catch (error) {
274
+ this.#onError(error, "send");
275
+ }
276
+ }
277
+ // Attach a rejection handler when a transport returns a promise, so failures
278
+ // surface via onError instead of as unhandled rejections.
279
+ #observe(result) {
280
+ if (result instanceof Promise) {
281
+ result.catch((error) => this.#onError(error, "send"));
196
282
  }
197
- const payload = id === undefined ? { update } : { update, id };
198
- sub.send(payload);
199
283
  }
200
284
  }
201
285
  //# sourceMappingURL=actioncable_provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"actioncable_provider.js","sourceRoot":"","sources":["../src/actioncable_provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"actioncable_provider.js","sourceRoot":"","sources":["../src/actioncable_provider.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,kFAAkF;AAClF,kFAAkF;AAClF,qEAAqE;AACrE,gDAAgD;AAChD,EAAE;AACF,6EAA6E;AAC7E,gFAAgF;AAChF,qCAAqC;AACrC,EAAE;AACF,iFAAiF;AACjF,oFAAoF;AACpF,2EAA2E;AAC3E,kFAAkF;AAClF,iFAAiF;AACjF,2EAA2E;AAC3E,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAgC,MAAM,yBAAyB,CAAC;AACtG,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAkDlD,MAAM,OAAO,mBAAmB;IACrB,GAAG,CAAM;IACT,QAAQ,CAAgB;IACxB,WAAW,CAAS;IACpB,aAAa,CAAS;IACtB,SAAS,CAAY;IACrB,OAAO,CAAmB;IACnC,aAAa,GAA6B,IAAI,CAAC;IAC/C,QAAQ,CAA4C;IACpD,UAAU,GAAG,KAAK,CAAC;IACnB,OAAO,GAAmB,cAAc,CAAC;IACzC,gBAAgB,GAAG,IAAI,GAAG,EAAgC,CAAC;IAC3D,WAAW,GAAyB,IAAI,CAAC;IACzC,+DAA+D;IAC/D,0EAA0E;IAC1E,uEAAuE;IACvE,QAAQ;IACR,WAAW,GAAG,KAAK,CAAC;IACpB,SAAS,GAAwB,IAAI,CAAC;IACtC,UAAU,GAAkD,IAAI,CAAC;IACjE,gBAAgB,GAAmC,IAAI,CAAC;IAExD,YACE,GAAQ,EACR,QAAuB,EACvB,WAAmB,EACnB,gBAAwB,EAAE,EAC1B,OAAmC,EAAE;QAErC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,SAAS,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,OAAO,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;QAEhG,IAAI,CAAC,OAAO,GAAG,IAAI,gBAAgB,CAAC,GAAG,EAAE;YACvC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,OAAO,EAAE,IAAI,CAAC,QAAQ;YACtB,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;SAC3C,CAAC,CAAC;IACL,CAAC;IAED,mFAAmF;IACnF,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7B,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,IAAI,UAAU;QACZ,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW;YACnC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE;YACnB,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBACtB,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;oBAC7C,IAAI,MAAM,KAAK,QAAQ;wBAAE,OAAO;oBAChC,GAAG,EAAE,CAAC;oBACN,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACP,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,4EAA4E;IAC5E,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;IACjC,CAAC;IAED;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,MAAkB;QAClC,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,6DAA6D;IAC7D,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,oEAAoE;IACpE,cAAc,CAAC,QAAsC;QACnD,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACpC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC;IAED,OAAO;QACL,IAAI,IAAI,CAAC,aAAa;YAAE,OAAO;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CACrD,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,aAAa,EAAE,EACpD;YACE,QAAQ,CAAC,OAAqB;gBAC5B,0DAA0D;gBAC1D,IAAI,OAAO,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;oBACzC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;oBAClC,OAAO;gBACT,CAAC;gBACD,MAAM,gBAAgB,GAAG,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC;gBACtD,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;gBAChE,IAAI,OAAO,OAAO,KAAK,QAAQ;oBAAE,OAAO;gBACxC,oEAAoE;gBACpE,4DAA4D;gBAC5D,IAAI,KAAiB,CAAC;gBACtB,IAAI,CAAC;oBACH,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;gBAC9B,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;oBACrC,OAAO;gBACT,CAAC;gBACD,IAAI,gBAAgB,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,SAAS,EAAE,CAAC;oBACzE,QAAQ,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,kDAAkD,CAAC,EAAE,UAAU,CAAC,CAAC;oBAC7F,OAAO;gBACT,CAAC;gBACD,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC9C,IAAI,KAAK;oBAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,uCAAuC;gBACpF,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC,mDAAmD;YAChF,CAAC;YACD,SAAS;gBACP,QAAQ,CAAC,UAAU,GAAG,IAAI,CAAC;gBAC3B,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,sCAAsC;gBACpE,QAAQ,CAAC,cAAc,EAAE,CAAC;YAC5B,CAAC;YACD,YAAY;gBACV,QAAQ,CAAC,UAAU,GAAG,KAAK,CAAC;gBAC5B,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,2CAA2C;gBAC5E,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC,oDAAoD;YACjF,CAAC;YACD,QAAQ;gBACN,oEAAoE;gBACpE,iEAAiE;gBACjE,iEAAiE;gBACjE,QAAQ,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,qCAAqC,CAAC,EAAE,UAAU,CAAC,CAAC;gBAChF,QAAQ,CAAC,UAAU,EAAE,CAAC;YACxB,CAAC;SACF,CACF,CAAC;QACF,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,kBAAkB;IAC3C,CAAC;IAED,UAAU;QACR,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,OAAO;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC;QAC/B,0EAA0E;QAC1E,2EAA2E;QAC3E,iCAAiC;QACjC,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC;QACpC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QAC5B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,8EAA8E;QAC9E,8EAA8E;QAC9E,+EAA+E;QAC/E,qBAAqB;QACrB,cAAc,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,oBAAoB;IAC7C,CAAC;IAED,OAAO;QACL,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACvB,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,yBAAyB;QACnD,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;IAChC,CAAC;IAED,cAAc;QACZ,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,OAAO,cAAc,CAAC;QAC/C,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO,YAAY,CAAC;QAC1C,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;IACtD,CAAC;IAED,cAAc;QACZ,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACnC,IAAI,IAAI,KAAK,IAAI,CAAC,OAAO;YAAE,OAAO;QAClC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,IAAI,KAAK,QAAQ;YAAE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC/C,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,gBAAgB;YAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,mDAAmD;IACnD,8EAA8E;IAC9E,+EAA+E;IAC/E,8EAA8E;IAC9E,0EAA0E;IAC1E,kDAAkD;IAClD,qBAAqB;QACnB,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC5D,IAAI,CAAC,SAAS,GAAG,GAAG,EAAE;YACpB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC;YACvD,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC;QACtC,CAAC,CAAC;QACF,IAAI,CAAC,UAAU,GAAG,CAAC,KAA0B,EAAE,EAAE;YAC/C,IAAI,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,gBAAgB;gBAAE,OAAO;YACvD,IAAI,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC;gBAC5C,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACtD,CAAC;YACD,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC/B,CAAC,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACpD,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACvD,CAAC;IAED,oBAAoB;QAClB,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;QAC1C,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YACvD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;YACxD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,8EAA8E;IAC9E,8EAA8E;IAC9E,6EAA6E;IAC7E,+CAA+C;IAC/C,KAAK,CAAC,KAAiB,EAAE,EAAsB;QAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC;QAC/B,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,SAAS,CAAC;QACvD,qEAAqE;QACrE,kEAAkE;QAClE,sEAAsE;QACtE,oDAAoD;QACpD,IAAI,CAAC;YACH,IAAI,WAAW,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;gBACrD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;gBAClD,OAAO;YACT,CAAC;YACD,MAAM,OAAO,GAAG,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;YAC/D,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,0DAA0D;IAC1D,QAAQ,CAAC,MAAe;QACtB,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,91 @@
1
+ import { YProtocolSession, type YProtocolSessionOptions } from "./y_protocol_session.js";
2
+ import { Awareness } from "y-protocols/awareness";
3
+ import type { Doc } from "yjs";
4
+ /**
5
+ * Connection lifecycle, folded into one signal (no separate "sync" event):
6
+ * connecting (subscription created, transport not up yet), connected (transport
7
+ * up, exchanging sync steps; UI: "syncing"), synced (caught up), and disconnected
8
+ * (torn down via disconnect()/destroy()). A dropped transport that ActionCable
9
+ * will retry shows as "connecting", not "disconnected".
10
+ */
11
+ export type ProviderStatus = "connecting" | "connected" | "synced" | "disconnected";
12
+ /** Payload passed to onStatusChange listeners. */
13
+ export interface StatusEvent {
14
+ status: ProviderStatus;
15
+ }
16
+ /** The minimal slice of an ActionCable/AnyCable subscription this provider uses. */
17
+ export interface CableSubscription {
18
+ send(data: unknown): unknown;
19
+ /** AnyCable client-to-client broadcast; absent on plain ActionCable. */
20
+ whisper?(data: unknown): unknown;
21
+ /** Teardown. Present on both @rails/actioncable and @anycable/web. */
22
+ unsubscribe?(): void;
23
+ }
24
+ /**
25
+ * The minimal slice of an ActionCable/AnyCable consumer this provider uses.
26
+ *
27
+ * Deliberately loose so the consumers from both `@rails/actioncable` and
28
+ * `@anycable/web` are directly assignable -- no adapter or casts. `create` is
29
+ * widened to the channel/params shapes both libs accept, with an optional mixin
30
+ * (the handlers object). There's no `subscriptions.remove`: the provider tears
31
+ * down via `subscription.unsubscribe()` (universal), and @anycable has no such
32
+ * method anyway.
33
+ */
34
+ export interface CableConsumer {
35
+ subscriptions: {
36
+ create(channel: string | object, mixin?: object): CableSubscription;
37
+ };
38
+ }
39
+ export type ActionCableProviderOptions = Pick<YProtocolSessionOptions, "resendInterval" | "onError">;
40
+ export declare class ActionCableProvider {
41
+ #private;
42
+ readonly doc: Doc;
43
+ readonly consumer: CableConsumer;
44
+ readonly channelName: string;
45
+ readonly channelParams: object;
46
+ readonly awareness: Awareness;
47
+ readonly session: YProtocolSession;
48
+ constructor(doc: Doc, consumer: CableConsumer, channelName: string, channelParams?: object, opts?: ActionCableProviderOptions);
49
+ /** True once the document has caught up with the server (received a SyncStep2). */
50
+ get synced(): boolean;
51
+ /**
52
+ * Resolves once the document has first caught up with the server. Most
53
+ * editor bindings seed an empty document when they mount, so binding
54
+ * before the server's state arrives makes each client insert its own
55
+ * top-level node. Create the editor after this resolves:
56
+ *
57
+ * provider.connect();
58
+ * await provider.whenSynced;
59
+ * // now hand the doc to the editor binding
60
+ *
61
+ * Resolves immediately if the first catch-up has already happened, even
62
+ * while the transport is down (`synced` is false during a reconnect;
63
+ * whether the doc has ever synced does not change). It stays resolved
64
+ * across later reconnects; use `onStatusChange` to track the live
65
+ * connection. If the provider is destroyed before the first sync, the
66
+ * promise never settles.
67
+ */
68
+ get whenSynced(): Promise<void>;
69
+ /** True while there are unacknowledged local document updates in flight. */
70
+ get hasPending(): boolean;
71
+ /**
72
+ * Apply a bootstrap/restore update (initial HTTP state, a server snapshot, an
73
+ * import) without re-sending it to the server as a local edit. Call it once per
74
+ * chunk of already-durable state when seeding the doc, before `connect()`:
75
+ *
76
+ * provider.applyRemoteUpdate(fromBase64(initialState));
77
+ * priorUpdates.forEach((u) => provider.applyRemoteUpdate(fromBase64(u)));
78
+ * provider.connect();
79
+ *
80
+ * See {@link YProtocolSession.applyRemoteUpdate} for why a bare `Y.applyUpdate`
81
+ * would be re-broadcast as a pending change instead.
82
+ */
83
+ applyRemoteUpdate(update: Uint8Array): void;
84
+ /** Current connection status. See {@link ProviderStatus}. */
85
+ get status(): ProviderStatus;
86
+ /** Subscribe to status changes. Returns an unsubscribe function. */
87
+ onStatusChange(listener: (event: StatusEvent) => void): () => void;
88
+ connect(): void;
89
+ disconnect(): void;
90
+ destroy(): void;
91
+ }
@@ -13,9 +13,10 @@ exports.ActionCableProvider = void 0;
13
13
  //
14
14
  // The constructor does not auto-connect: wire up your editor binding first, then
15
15
  // call `connect()`. Watch the connection with `onStatusChange(({ status }) => ...)`
16
- // or the `status` getter. On `disconnect()`/`destroy()`, and on browser
17
- // `pagehide`, the provider broadcasts a presence removal so peers drop our cursor
18
- // right away instead of waiting for the awareness timeout.
16
+ // or the `status` getter. Editors that must not bind before the first sync
17
+ // can `await provider.whenSynced` after connect(). On `disconnect()`/`destroy()`,
18
+ // and on browser `pagehide`, the provider broadcasts a presence removal so peers
19
+ // drop our cursor right away instead of waiting for the awareness timeout.
19
20
  const y_protocol_session_js_1 = require("./y_protocol_session.js");
20
21
  const base64_js_1 = require("./base64.js");
21
22
  const awareness_1 = require("y-protocols/awareness");
@@ -31,7 +32,15 @@ class ActionCableProvider {
31
32
  #connected = false;
32
33
  #status = "disconnected";
33
34
  #statusListeners = new Set();
35
+ #whenSynced = null;
36
+ // `session.synced` resets on every transport drop (a reconnect
37
+ // re-handshakes). Whether the first catch-up has ever happened is tracked
38
+ // separately here, so `whenSynced` does not depend on when it is first
39
+ // read.
40
+ #everSynced = false;
34
41
  #onUnload = null;
42
+ #onRestore = null;
43
+ #stashedPresence = null;
35
44
  constructor(doc, consumer, channelName, channelParams = {}, opts = {}) {
36
45
  this.doc = doc;
37
46
  this.consumer = consumer;
@@ -50,6 +59,36 @@ class ActionCableProvider {
50
59
  get synced() {
51
60
  return this.session.synced;
52
61
  }
62
+ /**
63
+ * Resolves once the document has first caught up with the server. Most
64
+ * editor bindings seed an empty document when they mount, so binding
65
+ * before the server's state arrives makes each client insert its own
66
+ * top-level node. Create the editor after this resolves:
67
+ *
68
+ * provider.connect();
69
+ * await provider.whenSynced;
70
+ * // now hand the doc to the editor binding
71
+ *
72
+ * Resolves immediately if the first catch-up has already happened, even
73
+ * while the transport is down (`synced` is false during a reconnect;
74
+ * whether the doc has ever synced does not change). It stays resolved
75
+ * across later reconnects; use `onStatusChange` to track the live
76
+ * connection. If the provider is destroyed before the first sync, the
77
+ * promise never settles.
78
+ */
79
+ get whenSynced() {
80
+ this.#whenSynced ??= this.#everSynced
81
+ ? Promise.resolve()
82
+ : new Promise((resolve) => {
83
+ const off = this.onStatusChange(({ status }) => {
84
+ if (status !== "synced")
85
+ return;
86
+ off();
87
+ resolve();
88
+ });
89
+ });
90
+ return this.#whenSynced;
91
+ }
53
92
  /** True while there are unacknowledged local document updates in flight. */
54
93
  get hasPending() {
55
94
  return this.session.hasPending;
@@ -122,6 +161,13 @@ class ActionCableProvider {
122
161
  provider.session.onDisconnect(); // pause retransmits, clear remote presence
123
162
  provider.#refreshStatus(); // subscription still set -> "connecting" (retrying)
124
163
  },
164
+ rejected() {
165
+ // The channel refused the subscription (auth, missing doc). Surface
166
+ // it and tear down — otherwise the provider sits at "connecting"
167
+ // forever, silently queueing edits. The app decides what's next.
168
+ provider.#onError(new Error("subscription rejected by the server"), "rejected");
169
+ provider.disconnect();
170
+ },
125
171
  });
126
172
  this.#installUnloadHandler();
127
173
  this.#refreshStatus(); // -> "connecting"
@@ -163,24 +209,46 @@ class ActionCableProvider {
163
209
  if (next === this.#status)
164
210
  return;
165
211
  this.#status = next;
212
+ if (next === "synced")
213
+ this.#everSynced = true;
166
214
  for (const listener of this.#statusListeners)
167
215
  listener({ status: next });
168
216
  }
169
- // Best-effort presence removal when the tab/page goes away (close, navigation,
170
- // bfcache). `pagehide` fires while the socket is still live and is bfcache-safe
171
- // (unlike `beforeunload`, which can block it). Sends are not guaranteed to
172
- // flush on unload, so the server-side awareness timeout remains the backstop.
217
+ // Presence teardown/restore around page lifecycle:
218
+ // - `pagehide`: remove local presence while the socket is still live so peers
219
+ // drop our cursor now (bfcache-safe; the awareness timeout is the backstop).
220
+ // - `pageshow` with `persisted`: the user came BACK (bfcache restore), so put
221
+ // their presence back — editors set awareness once at setup, so without
222
+ // this they'd rejoin as a ghost with no cursor.
173
223
  #installUnloadHandler() {
174
224
  if (typeof window === "undefined" || this.#onUnload)
175
225
  return;
176
- this.#onUnload = () => this.session.removeLocalAwareness();
226
+ this.#onUnload = () => {
227
+ this.#stashedPresence = this.awareness.getLocalState();
228
+ this.session.removeLocalAwareness();
229
+ };
230
+ this.#onRestore = (event) => {
231
+ if (!event.persisted || !this.#stashedPresence)
232
+ return;
233
+ if (this.awareness.getLocalState() === null) {
234
+ this.awareness.setLocalState(this.#stashedPresence);
235
+ }
236
+ this.#stashedPresence = null;
237
+ };
177
238
  window.addEventListener("pagehide", this.#onUnload);
239
+ window.addEventListener("pageshow", this.#onRestore);
178
240
  }
179
241
  #removeUnloadHandler() {
180
- if (typeof window === "undefined" || !this.#onUnload)
242
+ if (typeof window === "undefined")
181
243
  return;
182
- window.removeEventListener("pagehide", this.#onUnload);
183
- this.#onUnload = null;
244
+ if (this.#onUnload) {
245
+ window.removeEventListener("pagehide", this.#onUnload);
246
+ this.#onUnload = null;
247
+ }
248
+ if (this.#onRestore) {
249
+ window.removeEventListener("pageshow", this.#onRestore);
250
+ this.#onRestore = null;
251
+ }
184
252
  }
185
253
  // Send one raw protocol frame over the cable. Awareness frames are whispered
186
254
  // when AnyCable exposes `subscription.whisper`; otherwise they fall back to a
@@ -193,12 +261,28 @@ class ActionCableProvider {
193
261
  return;
194
262
  const update = (0, base64_js_1.toBase64)(frame);
195
263
  const isAwareness = frame[0] === y_protocol_session_js_1.MessageType.Awareness;
196
- if (isAwareness && typeof sub.whisper === "function") {
197
- sub.whisper({ awareness: update });
198
- return;
264
+ // Route transport failures (sync throws, or @anycable/web's rejected
265
+ // promises) to onError instead of letting them escape into update
266
+ // handlers. A failed send is recoverable: reliable frames stay queued
267
+ // until acked, and awareness is best-effort anyway.
268
+ try {
269
+ if (isAwareness && typeof sub.whisper === "function") {
270
+ this.#observe(sub.whisper({ awareness: update }));
271
+ return;
272
+ }
273
+ const payload = id === undefined ? { update } : { update, id };
274
+ this.#observe(sub.send(payload));
275
+ }
276
+ catch (error) {
277
+ this.#onError(error, "send");
278
+ }
279
+ }
280
+ // Attach a rejection handler when a transport returns a promise, so failures
281
+ // surface via onError instead of as unhandled rejections.
282
+ #observe(result) {
283
+ if (result instanceof Promise) {
284
+ result.catch((error) => this.#onError(error, "send"));
199
285
  }
200
- const payload = id === undefined ? { update } : { update, id };
201
- sub.send(payload);
202
286
  }
203
287
  }
204
288
  exports.ActionCableProvider = ActionCableProvider;
@@ -0,0 +1,2 @@
1
+ export declare const toBase64: (bytes: Uint8Array) => string;
2
+ export declare const fromBase64: (str: string) => Uint8Array;
@@ -0,0 +1,7 @@
1
+ export { ReliableSync } from "./reliable_sync.js";
2
+ export type { ReliableSyncOptions, TimerHandle } from "./reliable_sync.js";
3
+ export { YProtocolSession, MessageType } from "./y_protocol_session.js";
4
+ export type { YProtocolSessionOptions } from "./y_protocol_session.js";
5
+ export { ActionCableProvider } from "./actioncable_provider.js";
6
+ export type { ActionCableProviderOptions, ProviderStatus, StatusEvent, CableConsumer, CableSubscription, } from "./actioncable_provider.js";
7
+ export { toBase64, fromBase64 } from "./base64.js";
@@ -0,0 +1,58 @@
1
+ /** An opaque timer handle (number in browsers, Timeout in Node). */
2
+ export type TimerHandle = unknown;
3
+ export interface ReliableSyncOptions {
4
+ /**
5
+ * Transmit one update. `update` is the raw merged update bytes; `id` is the
6
+ * cumulative sequence to ack against.
7
+ */
8
+ send: (update: Uint8Array, id: number) => void;
9
+ /** Merge an array of update byte-arrays into one (typically Y.mergeUpdates). */
10
+ merge: (updates: Uint8Array[]) => Uint8Array;
11
+ /** Milliseconds between retransmits of the unacked tail (default 1000). */
12
+ resendInterval?: number;
13
+ /** Injectable timer hooks (default to globals); handy for tests. */
14
+ setInterval?: (handler: () => void, ms: number) => TimerHandle;
15
+ clearInterval?: (handle: TimerHandle) => void;
16
+ }
17
+ interface Pending {
18
+ seq: number;
19
+ update: Uint8Array;
20
+ }
21
+ export declare class ReliableSync {
22
+ #private;
23
+ /** Unacked local updates, in order. */
24
+ pending: Pending[];
25
+ constructor(opts: ReliableSyncOptions);
26
+ /** True while there are unacknowledged local updates. */
27
+ get hasPending(): boolean;
28
+ /**
29
+ * Record a local document update. It is queued and the unacked tail is
30
+ * flushed; the update remains retained until the server acknowledges it.
31
+ */
32
+ enqueue(update: Uint8Array): void;
33
+ /**
34
+ * Send the whole unacked tail as one merged delta. The id is the highest seq
35
+ * in the batch, so a single { ack } cumulatively confirms everything up to it.
36
+ * No-op while disconnected (the tail is replayed on the next onConnect).
37
+ */
38
+ flush(): void;
39
+ /**
40
+ * Confirm delivery up to `id`: prune every queued update with seq <= id.
41
+ * Acks arrive over the wire, so validate before pruning. A malformed value
42
+ * (NaN/string/negative) or an impossible future id must not silently drop the
43
+ * queue; invalid acks are ignored.
44
+ */
45
+ onAck(id: number): void;
46
+ /** Transport (re)connected: replay the unacked tail and resume retransmits. */
47
+ onConnect(): void;
48
+ /** Transport dropped: keep the queue (for reconnect replay), pause the timer. */
49
+ onDisconnect(): void;
50
+ /**
51
+ * One retransmit tick. Exposed for deterministic testing; normally driven by
52
+ * the internal timer.
53
+ */
54
+ onTick(): void;
55
+ /** Stop timers and drop references. Call when the provider is destroyed. */
56
+ destroy(): void;
57
+ }
58
+ export {};
@@ -0,0 +1,75 @@
1
+ import { Doc } from "yjs";
2
+ import { type Awareness } from "y-protocols/awareness";
3
+ import { type TimerHandle } from "./reliable_sync.js";
4
+ export declare const MessageType: {
5
+ readonly Sync: 0;
6
+ readonly Awareness: 1;
7
+ };
8
+ export interface YProtocolSessionOptions {
9
+ /**
10
+ * Transmit one raw protocol frame. `id` is set only for reliable document
11
+ * updates (tag it onto your envelope so the server can ack). Awareness frames
12
+ * are identifiable by their first byte (`MessageType.Awareness`) if a transport
13
+ * needs to route them separately.
14
+ */
15
+ send: (frame: Uint8Array, id: number | undefined) => void;
16
+ /** Optional awareness/presence. When omitted, awareness frames are ignored. */
17
+ awareness?: Awareness | null;
18
+ /** Forwarded to ReliableSync. */
19
+ resendInterval?: number;
20
+ /**
21
+ * Called when an incoming frame can't be decoded/applied (malformed bytes,
22
+ * truncated message, unexpected structure). The frame is dropped and the
23
+ * session keeps running. `context` names where it happened (e.g. "receive").
24
+ * Defaults to a `console.warn`.
25
+ */
26
+ onError?: (error: unknown, context: string) => void;
27
+ /** Injectable timer hooks (forwarded to ReliableSync); handy for tests. */
28
+ setInterval?: (handler: () => void, ms: number) => TimerHandle;
29
+ clearInterval?: (handle: TimerHandle) => void;
30
+ }
31
+ export declare class YProtocolSession {
32
+ #private;
33
+ readonly doc: Doc;
34
+ readonly awareness: Awareness | null;
35
+ constructor(doc: Doc, opts: YProtocolSessionOptions);
36
+ /** True once we've received the server's SyncStep2 (the document is caught up). */
37
+ get synced(): boolean;
38
+ /** True while there are unacknowledged local document updates in flight. */
39
+ get hasPending(): boolean;
40
+ /** Transport connected: send the opening handshake and replay the unacked tail. */
41
+ onConnect(): void;
42
+ /** Transport dropped: pause retransmits (queue kept) and clear remote presence. */
43
+ onDisconnect(): void;
44
+ /**
45
+ * Broadcast that our local presence is gone (sets local state to null, which
46
+ * emits a removal awareness frame through `send`). Call this while the
47
+ * transport is still live so peers drop our cursor immediately instead of
48
+ * waiting for the awareness timeout. A no-op when there's no local state.
49
+ */
50
+ removeLocalAwareness(): void;
51
+ /** A reliable-delivery `{ ack: id }` envelope arrived. */
52
+ ack(id: number): void;
53
+ /**
54
+ * Apply an update without treating it as a local edit, so it isn't queued for
55
+ * re-delivery to the server. Use it for bootstrap/restore: initial state loaded
56
+ * over HTTP, a server snapshot, an import. These are bytes the server already
57
+ * has.
58
+ *
59
+ * The session re-sends any doc update whose origin isn't itself (that's how a
60
+ * keystroke becomes an outbound frame), so a bare `Y.applyUpdate(doc, update)`
61
+ * would look like a local edit and get echoed back on the next connect. Going
62
+ * through here applies under the session's own origin, which the outbound
63
+ * filter skips. Safe to call before `onConnect()`: the state folds into the
64
+ * SyncStep1 handshake instead of being re-sent.
65
+ */
66
+ applyRemoteUpdate(update: Uint8Array): void;
67
+ /**
68
+ * Decode and apply one incoming binary protocol frame (document sync or
69
+ * awareness). Returns a reply frame to transmit (e.g. SyncStep2 answering a
70
+ * SyncStep1), or null if there's nothing to send.
71
+ */
72
+ receive(frame: Uint8Array): Uint8Array | null;
73
+ /** Detach doc/awareness listeners and stop retransmits. */
74
+ destroy(): void;
75
+ }
@@ -235,7 +235,25 @@ class YProtocolSession {
235
235
  break;
236
236
  }
237
237
  case exports.MessageType.Awareness:
238
- decoding.readVarUint8Array(decoder);
238
+ // Validate the payload's CONTENTS, not just the envelope.
239
+ // applyAwarenessUpdate mutates state entry by entry and only notifies
240
+ // listeners at the end — a bad entry mid-payload would leave earlier
241
+ // entries applied with no event fired. Dry-running every entry here
242
+ // makes the real apply infallible (and catches trailing garbage
243
+ // inside the blob).
244
+ {
245
+ const payload = decoding.readVarUint8Array(decoder);
246
+ const inner = decoding.createDecoder(payload);
247
+ const count = decoding.readVarUint(inner);
248
+ for (let i = 0; i < count; i++) {
249
+ decoding.readVarUint(inner); // clientID
250
+ decoding.readVarUint(inner); // clock
251
+ JSON.parse(decoding.readVarString(inner)); // state (null on removal)
252
+ }
253
+ if (decoding.hasContent(inner)) {
254
+ throw new Error("awareness payload has trailing bytes");
255
+ }
256
+ }
239
257
  break;
240
258
  default:
241
259
  return null; // a y-protocols type yrby doesn't speak: ignore
@@ -1 +1 @@
1
- {"version":3,"file":"y_protocol_session.d.ts","sourceRoot":"","sources":["../src/y_protocol_session.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,GAAG,EAA6B,MAAM,KAAK,CAAC;AAIrD,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAIpE,eAAO,MAAM,WAAW;;;CAAqC,CAAC;AAE9D,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,IAAI,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC1D,+EAA+E;IAC/E,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7B,iCAAiC;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,2EAA2E;IAC3E,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,WAAW,CAAC;IAC/D,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;CAC/C;AAID,qBAAa,gBAAgB;;IAC3B,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;gBASzB,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,uBAAuB;IA6CnD,mFAAmF;IACnF,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,4EAA4E;IAC5E,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,mFAAmF;IACnF,SAAS,IAAI,IAAI;IAQjB,mFAAmF;IACnF,YAAY,IAAI,IAAI;IASpB;;;;;OAKG;IACH,oBAAoB,IAAI,IAAI;IAM5B,0DAA0D;IAC1D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIrB;;;;;;;;;;;;OAYG;IACH,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAI3C;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI;IA8B7C,2DAA2D;IAC3D,OAAO,IAAI,IAAI;CAwDhB"}
1
+ {"version":3,"file":"y_protocol_session.d.ts","sourceRoot":"","sources":["../src/y_protocol_session.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,GAAG,EAA6B,MAAM,KAAK,CAAC;AAIrD,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAIpE,eAAO,MAAM,WAAW;;;CAAqC,CAAC;AAE9D,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,IAAI,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC1D,+EAA+E;IAC/E,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7B,iCAAiC;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,2EAA2E;IAC3E,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,WAAW,CAAC;IAC/D,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;CAC/C;AAID,qBAAa,gBAAgB;;IAC3B,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;gBASzB,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,uBAAuB;IA6CnD,mFAAmF;IACnF,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,4EAA4E;IAC5E,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,mFAAmF;IACnF,SAAS,IAAI,IAAI;IAQjB,mFAAmF;IACnF,YAAY,IAAI,IAAI;IASpB;;;;;OAKG;IACH,oBAAoB,IAAI,IAAI;IAM5B,0DAA0D;IAC1D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIrB;;;;;;;;;;;;OAYG;IACH,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAI3C;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI;IA8B7C,2DAA2D;IAC3D,OAAO,IAAI,IAAI;CA0EhB"}
@@ -199,7 +199,25 @@ export class YProtocolSession {
199
199
  break;
200
200
  }
201
201
  case MessageType.Awareness:
202
- decoding.readVarUint8Array(decoder);
202
+ // Validate the payload's CONTENTS, not just the envelope.
203
+ // applyAwarenessUpdate mutates state entry by entry and only notifies
204
+ // listeners at the end — a bad entry mid-payload would leave earlier
205
+ // entries applied with no event fired. Dry-running every entry here
206
+ // makes the real apply infallible (and catches trailing garbage
207
+ // inside the blob).
208
+ {
209
+ const payload = decoding.readVarUint8Array(decoder);
210
+ const inner = decoding.createDecoder(payload);
211
+ const count = decoding.readVarUint(inner);
212
+ for (let i = 0; i < count; i++) {
213
+ decoding.readVarUint(inner); // clientID
214
+ decoding.readVarUint(inner); // clock
215
+ JSON.parse(decoding.readVarString(inner)); // state (null on removal)
216
+ }
217
+ if (decoding.hasContent(inner)) {
218
+ throw new Error("awareness payload has trailing bytes");
219
+ }
220
+ }
203
221
  break;
204
222
  default:
205
223
  return null; // a y-protocols type yrby doesn't speak: ignore
@@ -1 +1 @@
1
- {"version":3,"file":"y_protocol_session.js","sourceRoot":"","sources":["../src/y_protocol_session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"y_protocol_session.js","sourceRoot":"","sources":["../src/y_protocol_session.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yrby-client",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "JavaScript client for the yrby y-websocket protocol: a ready-made ActionCable/AnyCable provider, a transport-agnostic protocol session (sync steps, encode/decode, awareness), and a reliable-delivery core (ack-tracked queue, sync-since-last-ack, retransmit + reconnect replay). Written in TypeScript with bundled types; ESM + CommonJS, usable from plain JS.",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -8,19 +8,34 @@
8
8
  "types": "./dist/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js",
13
- "require": "./dist/cjs/index.js"
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/cjs/index.d.ts",
17
+ "default": "./dist/cjs/index.js"
18
+ }
14
19
  },
15
20
  "./reliable": {
16
- "types": "./dist/reliable_sync.d.ts",
17
- "import": "./dist/reliable_sync.js",
18
- "require": "./dist/cjs/reliable_sync.js"
21
+ "import": {
22
+ "types": "./dist/reliable_sync.d.ts",
23
+ "default": "./dist/reliable_sync.js"
24
+ },
25
+ "require": {
26
+ "types": "./dist/cjs/reliable_sync.d.ts",
27
+ "default": "./dist/cjs/reliable_sync.js"
28
+ }
19
29
  },
20
30
  "./base64": {
21
- "types": "./dist/base64.d.ts",
22
- "import": "./dist/base64.js",
23
- "require": "./dist/cjs/base64.js"
31
+ "import": {
32
+ "types": "./dist/base64.d.ts",
33
+ "default": "./dist/base64.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/cjs/base64.d.ts",
37
+ "default": "./dist/cjs/base64.js"
38
+ }
24
39
  }
25
40
  },
26
41
  "files": [