y-partyserver 2.1.4 → 2.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.
@@ -6,16 +6,12 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") {
10
- for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
- key = keys[i];
12
- if (!__hasOwnProp.call(to, key) && key !== except) {
13
- __defProp(to, key, {
14
- get: ((k) => from[k]).bind(null, key),
15
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
- });
17
- }
18
- }
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
19
15
  }
20
16
  return to;
21
17
  };
@@ -23,12 +19,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
19
  value: mod,
24
20
  enumerable: true
25
21
  }) : target, mod));
26
-
27
22
  //#endregion
28
-
29
- Object.defineProperty(exports, '__toESM', {
30
- enumerable: true,
31
- get: function () {
32
- return __toESM;
33
- }
34
- });
23
+ Object.defineProperty(exports, "__toESM", {
24
+ enumerable: true,
25
+ get: function() {
26
+ return __toESM;
27
+ }
28
+ });
@@ -2,29 +2,28 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_chunk = require("../chunk-C0xms8kb.cjs");
5
+ const require_chunk = require("../chunk-CKQMccvm.cjs");
6
6
  let lib0_decoding = require("lib0/decoding");
7
- lib0_decoding = require_chunk.__toESM(lib0_decoding);
7
+ lib0_decoding = require_chunk.__toESM(lib0_decoding, 1);
8
8
  let lib0_encoding = require("lib0/encoding");
9
- lib0_encoding = require_chunk.__toESM(lib0_encoding);
9
+ lib0_encoding = require_chunk.__toESM(lib0_encoding, 1);
10
10
  let y_protocols_awareness = require("y-protocols/awareness");
11
- y_protocols_awareness = require_chunk.__toESM(y_protocols_awareness);
11
+ y_protocols_awareness = require_chunk.__toESM(y_protocols_awareness, 1);
12
12
  let y_protocols_sync = require("y-protocols/sync");
13
- y_protocols_sync = require_chunk.__toESM(y_protocols_sync);
13
+ y_protocols_sync = require_chunk.__toESM(y_protocols_sync, 1);
14
14
  let yjs = require("yjs");
15
15
  let lib0_broadcastchannel = require("lib0/broadcastchannel");
16
- lib0_broadcastchannel = require_chunk.__toESM(lib0_broadcastchannel);
16
+ lib0_broadcastchannel = require_chunk.__toESM(lib0_broadcastchannel, 1);
17
17
  let lib0_math = require("lib0/math");
18
- lib0_math = require_chunk.__toESM(lib0_math);
18
+ lib0_math = require_chunk.__toESM(lib0_math, 1);
19
19
  let lib0_observable = require("lib0/observable");
20
20
  let lib0_time = require("lib0/time");
21
- lib0_time = require_chunk.__toESM(lib0_time);
21
+ lib0_time = require_chunk.__toESM(lib0_time, 1);
22
22
  let lib0_url = require("lib0/url");
23
- lib0_url = require_chunk.__toESM(lib0_url);
23
+ lib0_url = require_chunk.__toESM(lib0_url, 1);
24
24
  let nanoid = require("nanoid");
25
25
  let y_protocols_auth = require("y-protocols/auth");
26
- y_protocols_auth = require_chunk.__toESM(y_protocols_auth);
27
-
26
+ y_protocols_auth = require_chunk.__toESM(y_protocols_auth, 1);
28
27
  //#region src/provider/index.ts
29
28
  const messageSync = 0;
30
29
  const messageQueryAwareness = 3;
@@ -32,14 +31,8 @@ const messageAwareness = 1;
32
31
  const messageAuth = 2;
33
32
  const DEFAULT_DISABLE_BC = typeof window === "undefined";
34
33
  const messageHandlers = [];
35
- messageHandlers[messageSync] = (
36
- encoder,
37
- decoder,
38
- provider,
39
- emitSynced,
40
- _messageType
41
- ) => {
42
- lib0_encoding.writeVarUint(encoder, messageSync);
34
+ messageHandlers[0] = (encoder, decoder, provider, emitSynced, _messageType) => {
35
+ lib0_encoding.writeVarUint(encoder, 0);
43
36
  const syncMessageType = y_protocols_sync.readSyncMessage(
44
37
  decoder,
45
38
  encoder,
@@ -53,14 +46,14 @@ messageHandlers[messageSync] = (
53
46
  )
54
47
  provider.synced = true;
55
48
  };
56
- messageHandlers[messageQueryAwareness] = (
49
+ messageHandlers[3] = (
57
50
  encoder,
58
51
  _decoder,
59
52
  provider,
60
53
  _emitSynced,
61
54
  _messageType
62
55
  ) => {
63
- lib0_encoding.writeVarUint(encoder, messageAwareness);
56
+ lib0_encoding.writeVarUint(encoder, 1);
64
57
  lib0_encoding.writeVarUint8Array(
65
58
  encoder,
66
59
  y_protocols_awareness.encodeAwarenessUpdate(
@@ -69,7 +62,7 @@ messageHandlers[messageQueryAwareness] = (
69
62
  )
70
63
  );
71
64
  };
72
- messageHandlers[messageAwareness] = (
65
+ messageHandlers[1] = (
73
66
  _encoder,
74
67
  decoder,
75
68
  provider,
@@ -82,7 +75,7 @@ messageHandlers[messageAwareness] = (
82
75
  provider
83
76
  );
84
77
  };
85
- messageHandlers[messageAuth] = (
78
+ messageHandlers[2] = (
86
79
  _encoder,
87
80
  decoder,
88
81
  provider,
@@ -173,13 +166,13 @@ function setupWS(provider) {
173
166
  provider.wsUnsuccessfulReconnects = 0;
174
167
  provider.emit("status", [{ status: "connected" }]);
175
168
  const encoder = lib0_encoding.createEncoder();
176
- lib0_encoding.writeVarUint(encoder, messageSync);
169
+ lib0_encoding.writeVarUint(encoder, 0);
177
170
  y_protocols_sync.writeSyncStep1(encoder, provider.doc);
178
171
  websocket.send(lib0_encoding.toUint8Array(encoder));
179
172
  if (provider.awareness.getLocalState() !== null) {
180
173
  provider.awareness.setLocalState(provider.awareness.getLocalState());
181
174
  const encoderAwarenessState = lib0_encoding.createEncoder();
182
- lib0_encoding.writeVarUint(encoderAwarenessState, messageAwareness);
175
+ lib0_encoding.writeVarUint(encoderAwarenessState, 1);
183
176
  lib0_encoding.writeVarUint8Array(
184
177
  encoderAwarenessState,
185
178
  y_protocols_awareness.encodeAwarenessUpdate(provider.awareness, [
@@ -278,7 +271,7 @@ var WebsocketProvider = class extends lib0_observable.Observable {
278
271
  this._resyncInterval = setInterval(() => {
279
272
  if (this.ws && this.ws.readyState === WebSocket.OPEN) {
280
273
  const encoder = lib0_encoding.createEncoder();
281
- lib0_encoding.writeVarUint(encoder, messageSync);
274
+ lib0_encoding.writeVarUint(encoder, 0);
282
275
  y_protocols_sync.writeSyncStep1(encoder, doc);
283
276
  this.ws.send(lib0_encoding.toUint8Array(encoder));
284
277
  }
@@ -300,7 +293,7 @@ var WebsocketProvider = class extends lib0_observable.Observable {
300
293
  this._updateHandler = (update, origin) => {
301
294
  if (origin !== this) {
302
295
  const encoder = lib0_encoding.createEncoder();
303
- lib0_encoding.writeVarUint(encoder, messageSync);
296
+ lib0_encoding.writeVarUint(encoder, 0);
304
297
  y_protocols_sync.writeUpdate(encoder, update);
305
298
  broadcastMessage(this, lib0_encoding.toUint8Array(encoder));
306
299
  }
@@ -309,7 +302,7 @@ var WebsocketProvider = class extends lib0_observable.Observable {
309
302
  this._awarenessUpdateHandler = ({ added, updated, removed }, _origin) => {
310
303
  const changedClients = added.concat(updated).concat(removed);
311
304
  const encoder = lib0_encoding.createEncoder();
312
- lib0_encoding.writeVarUint(encoder, messageAwareness);
305
+ lib0_encoding.writeVarUint(encoder, 1);
313
306
  lib0_encoding.writeVarUint8Array(
314
307
  encoder,
315
308
  y_protocols_awareness.encodeAwarenessUpdate(awareness, changedClients)
@@ -365,7 +358,7 @@ var WebsocketProvider = class extends lib0_observable.Observable {
365
358
  this.bcconnected = true;
366
359
  }
367
360
  const encoderSync = lib0_encoding.createEncoder();
368
- lib0_encoding.writeVarUint(encoderSync, messageSync);
361
+ lib0_encoding.writeVarUint(encoderSync, 0);
369
362
  y_protocols_sync.writeSyncStep1(encoderSync, this.doc);
370
363
  lib0_broadcastchannel.publish(
371
364
  this.bcChannel,
@@ -373,7 +366,7 @@ var WebsocketProvider = class extends lib0_observable.Observable {
373
366
  this
374
367
  );
375
368
  const encoderState = lib0_encoding.createEncoder();
376
- lib0_encoding.writeVarUint(encoderState, messageSync);
369
+ lib0_encoding.writeVarUint(encoderState, 0);
377
370
  y_protocols_sync.writeSyncStep2(encoderState, this.doc);
378
371
  lib0_broadcastchannel.publish(
379
372
  this.bcChannel,
@@ -381,14 +374,14 @@ var WebsocketProvider = class extends lib0_observable.Observable {
381
374
  this
382
375
  );
383
376
  const encoderAwarenessQuery = lib0_encoding.createEncoder();
384
- lib0_encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
377
+ lib0_encoding.writeVarUint(encoderAwarenessQuery, 3);
385
378
  lib0_broadcastchannel.publish(
386
379
  this.bcChannel,
387
380
  lib0_encoding.toUint8Array(encoderAwarenessQuery),
388
381
  this
389
382
  );
390
383
  const encoderAwarenessState = lib0_encoding.createEncoder();
391
- lib0_encoding.writeVarUint(encoderAwarenessState, messageAwareness);
384
+ lib0_encoding.writeVarUint(encoderAwarenessState, 1);
392
385
  lib0_encoding.writeVarUint8Array(
393
386
  encoderAwarenessState,
394
387
  y_protocols_awareness.encodeAwarenessUpdate(this.awareness, [
@@ -403,7 +396,7 @@ var WebsocketProvider = class extends lib0_observable.Observable {
403
396
  }
404
397
  disconnectBc() {
405
398
  const encoder = lib0_encoding.createEncoder();
406
- lib0_encoding.writeVarUint(encoder, messageAwareness);
399
+ lib0_encoding.writeVarUint(encoder, 1);
407
400
  lib0_encoding.writeVarUint8Array(
408
401
  encoder,
409
402
  y_protocols_awareness.encodeAwarenessUpdate(
@@ -502,7 +495,6 @@ var YProvider = class extends WebsocketProvider {
502
495
  this.ws?.send(`__YPS:${message}`);
503
496
  }
504
497
  };
505
-
506
498
  //#endregion
507
499
  exports.WebsocketProvider = WebsocketProvider;
508
500
  exports.default = YProvider;
@@ -510,4 +502,5 @@ exports.messageAuth = messageAuth;
510
502
  exports.messageAwareness = messageAwareness;
511
503
  exports.messageQueryAwareness = messageQueryAwareness;
512
504
  exports.messageSync = messageSync;
505
+
513
506
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["syncProtocol","awarenessProtocol","decoding","encoding","time","math","Observable","url","YDoc","#params","#resolveParams"],"sources":["../../src/provider/index.ts"],"sourcesContent":["import * as bc from \"lib0/broadcastchannel\";\nimport * as decoding from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport * as math from \"lib0/math\";\nimport { Observable } from \"lib0/observable\";\nimport * as time from \"lib0/time\";\nimport * as url from \"lib0/url\";\nimport { nanoid } from \"nanoid\";\nimport * as authProtocol from \"y-protocols/auth\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport { Doc as YDoc } from \"yjs\";\n\nexport const messageSync = 0;\nexport const messageQueryAwareness = 3;\nexport const messageAwareness = 1;\nexport const messageAuth = 2;\n\n// Disable BroadcastChannel by default in Cloudflare Workers / Node\nconst DEFAULT_DISABLE_BC = typeof window === \"undefined\";\n\nconst messageHandlers: Array<\n (\n encoder: encoding.Encoder,\n decoder: decoding.Decoder,\n provider: WebsocketProvider,\n emitSynced: boolean,\n messageType: number\n ) => void\n> = [];\n\nmessageHandlers[messageSync] = (\n encoder,\n decoder,\n provider,\n emitSynced,\n _messageType\n) => {\n encoding.writeVarUint(encoder, messageSync);\n const syncMessageType = syncProtocol.readSyncMessage(\n decoder,\n encoder,\n provider.doc,\n provider\n );\n if (\n emitSynced &&\n syncMessageType === syncProtocol.messageYjsSyncStep2 &&\n !provider.synced\n ) {\n provider.synced = true;\n }\n};\n\nmessageHandlers[messageQueryAwareness] = (\n encoder,\n _decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n provider.awareness,\n Array.from(provider.awareness.getStates().keys())\n )\n );\n};\n\nmessageHandlers[messageAwareness] = (\n _encoder,\n decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n awarenessProtocol.applyAwarenessUpdate(\n provider.awareness,\n decoding.readVarUint8Array(decoder),\n provider\n );\n};\n\nmessageHandlers[messageAuth] = (\n _encoder,\n decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n authProtocol.readAuthMessage(decoder, provider.doc, (_ydoc, reason) =>\n permissionDeniedHandler(provider, reason)\n );\n};\n\nfunction permissionDeniedHandler(provider: WebsocketProvider, reason: string) {\n console.warn(`Permission denied to access ${provider.url}.\\n${reason}`);\n}\n\nfunction readMessage(\n provider: WebsocketProvider,\n buf: Uint8Array,\n emitSynced: boolean\n): encoding.Encoder {\n const decoder = decoding.createDecoder(buf);\n const encoder = encoding.createEncoder();\n const messageType = decoding.readVarUint(decoder);\n const messageHandler = provider.messageHandlers[messageType];\n if (/** @type {any} */ messageHandler) {\n messageHandler(encoder, decoder, provider, emitSynced, messageType);\n } else {\n console.error(\"Unable to compute message\");\n }\n return encoder;\n}\n\nfunction setupWS(provider: WebsocketProvider) {\n if (provider.shouldConnect && provider.ws === null) {\n if (!provider._WS) {\n throw new Error(\n \"No WebSocket implementation available, did you forget to pass options.WebSocketPolyfill?\"\n );\n }\n const websocket = new provider._WS(provider.url);\n websocket.binaryType = \"arraybuffer\";\n provider.ws = websocket;\n provider.wsconnecting = true;\n provider.wsconnected = false;\n provider.synced = false;\n\n websocket.addEventListener(\"message\", (event) => {\n if (typeof event.data === \"string\") {\n // Handle custom messages with __YPS: prefix\n if (event.data.startsWith(\"__YPS:\")) {\n const customMessage = event.data.slice(6); // Remove __YPS: prefix\n provider.emit(\"custom-message\", [customMessage]);\n }\n return;\n }\n provider.wsLastMessageReceived = time.getUnixTime();\n const encoder = readMessage(provider, new Uint8Array(event.data), true);\n if (encoding.length(encoder) > 1) {\n websocket.send(encoding.toUint8Array(encoder));\n }\n });\n websocket.addEventListener(\"error\", (event) => {\n provider.emit(\"connection-error\", [event, provider]);\n });\n websocket.addEventListener(\"close\", (event) => {\n provider.emit(\"connection-close\", [event, provider]);\n provider.ws = null;\n provider.wsconnecting = false;\n if (provider.wsconnected) {\n provider.wsconnected = false;\n provider.synced = false;\n // update awareness (all users except local left)\n const removedClients = Array.from(\n provider.awareness.getStates().keys()\n ).filter((client) => client !== provider.doc.clientID);\n awarenessProtocol.removeAwarenessStates(\n provider.awareness,\n removedClients,\n provider\n );\n // Clear stale meta for remote clients so their awareness\n // updates are accepted on reconnect (clock check starts fresh)\n for (const clientID of removedClients) {\n provider.awareness.meta.delete(clientID);\n }\n provider.emit(\"status\", [\n {\n status: \"disconnected\"\n }\n ]);\n } else {\n provider.wsUnsuccessfulReconnects++;\n }\n // Start with no reconnect timeout and increase timeout by\n // using exponential backoff starting with 100ms\n setTimeout(\n () => {\n if (provider.shouldConnect) {\n Promise.resolve(provider._reconnectWS()).catch((err) => {\n console.error(\"Reconnection failed\", err);\n });\n }\n },\n math.min(\n math.pow(2, provider.wsUnsuccessfulReconnects) * 100,\n provider.maxBackoffTime\n )\n );\n });\n websocket.addEventListener(\"open\", () => {\n provider.wsLastMessageReceived = time.getUnixTime();\n provider.wsconnecting = false;\n provider.wsconnected = true;\n provider.wsUnsuccessfulReconnects = 0;\n provider.emit(\"status\", [\n {\n status: \"connected\"\n }\n ]);\n // always send sync step 1 when connected\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, provider.doc);\n websocket.send(encoding.toUint8Array(encoder));\n // broadcast local awareness state\n if (provider.awareness.getLocalState() !== null) {\n // Re-set local state to bump the awareness clock, ensuring\n // remote clients accept the update even if they have stale meta\n provider.awareness.setLocalState(provider.awareness.getLocalState());\n const encoderAwarenessState = encoding.createEncoder();\n encoding.writeVarUint(encoderAwarenessState, messageAwareness);\n encoding.writeVarUint8Array(\n encoderAwarenessState,\n awarenessProtocol.encodeAwarenessUpdate(provider.awareness, [\n provider.doc.clientID\n ])\n );\n websocket.send(encoding.toUint8Array(encoderAwarenessState));\n }\n });\n provider.emit(\"status\", [\n {\n status: \"connecting\"\n }\n ]);\n }\n}\n\nfunction broadcastMessage(provider: WebsocketProvider, buf: Uint8Array) {\n const ws = provider.ws;\n if (provider.wsconnected && ws && ws.readyState === ws.OPEN) {\n ws.send(buf);\n }\n if (provider.bcconnected) {\n bc.publish(provider.bcChannel, buf, provider);\n }\n}\n\ntype AwarenessUpdate = {\n added: number[];\n updated: number[];\n removed: number[];\n};\n\nconst DefaultWebSocket = typeof WebSocket === \"undefined\" ? null : WebSocket;\n\n/**\n * Websocket Provider for Yjs. Creates a websocket connection to sync the shared document.\n * The document name is attached to the provided url. I.e. the following example\n * creates a websocket connection to http://localhost:1234/my-document-name\n *\n * @example\n * import * as Y from 'yjs'\n * import { WebsocketProvider } from 'y-websocket'\n * const doc = new Y.Doc()\n * const provider = new WebsocketProvider('http://localhost:1234', 'my-document-name', doc)\n *\n * @extends {Observable<string>}\n */\nexport class WebsocketProvider extends Observable<string> {\n maxBackoffTime: number;\n bcChannel: string;\n url: string;\n roomname: string;\n doc: YDoc;\n _WS: typeof WebSocket;\n awareness: awarenessProtocol.Awareness;\n wsconnected: boolean;\n wsconnecting: boolean;\n bcconnected: boolean;\n disableBc: boolean;\n wsUnsuccessfulReconnects: number;\n messageHandlers: typeof messageHandlers;\n _synced: boolean;\n ws: WebSocket | null;\n wsLastMessageReceived: number;\n shouldConnect: boolean; // Whether to connect to other peers or not\n _resyncInterval: ReturnType<typeof setInterval> | number;\n _bcSubscriber: (message: Uint8Array, origin: unknown) => void;\n _updateHandler: (update: Uint8Array, origin: unknown) => void;\n _awarenessUpdateHandler: (update: AwarenessUpdate, origin: unknown) => void;\n _unloadHandler: () => void;\n\n constructor(\n serverUrl: string,\n roomname: string,\n doc: YDoc,\n {\n connect = true,\n awareness = new awarenessProtocol.Awareness(doc),\n params = {},\n isPrefixedUrl = false,\n WebSocketPolyfill = DefaultWebSocket, // Optionally provide a WebSocket polyfill\n resyncInterval = -1, // Request server state every `resyncInterval` milliseconds\n maxBackoffTime = 2500, // Maximum amount of time to wait before trying to reconnect (we try to reconnect using exponential backoff)\n disableBc = DEFAULT_DISABLE_BC // Disable cross-tab BroadcastChannel communication\n }: {\n connect?: boolean;\n awareness?: awarenessProtocol.Awareness;\n params?: { [s: string]: string };\n isPrefixedUrl?: boolean;\n WebSocketPolyfill?: typeof WebSocket | null;\n resyncInterval?: number;\n maxBackoffTime?: number;\n disableBc?: boolean;\n } = {}\n ) {\n super();\n // ensure that url is always ends with /\n while (serverUrl[serverUrl.length - 1] === \"/\") {\n serverUrl = serverUrl.slice(0, serverUrl.length - 1);\n }\n const encodedParams = url.encodeQueryParams(params);\n this.maxBackoffTime = maxBackoffTime;\n this.bcChannel = `${serverUrl}/${roomname}`;\n this.url = isPrefixedUrl\n ? serverUrl\n : `${serverUrl}/${roomname}${encodedParams.length === 0 ? \"\" : `?${encodedParams}`}`;\n this.roomname = roomname;\n this.doc = doc;\n this._WS = WebSocketPolyfill!;\n this.awareness = awareness;\n this.wsconnected = false;\n this.wsconnecting = false;\n this.bcconnected = false;\n this.disableBc = disableBc;\n this.wsUnsuccessfulReconnects = 0;\n this.messageHandlers = messageHandlers.slice();\n\n this._synced = false;\n\n this.ws = null;\n this.wsLastMessageReceived = 0;\n\n this.shouldConnect = connect;\n\n this._resyncInterval = 0;\n if (resyncInterval > 0) {\n this._resyncInterval = /** @type {any} */ setInterval(() => {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n // resend sync step 1\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, doc);\n this.ws.send(encoding.toUint8Array(encoder));\n }\n }, resyncInterval);\n }\n\n this._bcSubscriber = (data: Uint8Array, origin: unknown) => {\n if (origin !== this) {\n const encoder = readMessage(this, new Uint8Array(data), false);\n if (encoding.length(encoder) > 1) {\n bc.publish(this.bcChannel, encoding.toUint8Array(encoder), this);\n }\n }\n };\n /**\n * Listens to Yjs updates and sends them to remote peers (ws and broadcastchannel)\n */\n this._updateHandler = (update: Uint8Array, origin: unknown) => {\n if (origin !== this) {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeUpdate(encoder, update);\n broadcastMessage(this, encoding.toUint8Array(encoder));\n }\n };\n this.doc.on(\"update\", this._updateHandler);\n\n this._awarenessUpdateHandler = (\n { added, updated, removed }: AwarenessUpdate,\n _origin: unknown\n ) => {\n const changedClients = added.concat(updated).concat(removed);\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(awareness, changedClients)\n );\n broadcastMessage(this, encoding.toUint8Array(encoder));\n };\n this._unloadHandler = () => {\n awarenessProtocol.removeAwarenessStates(\n this.awareness,\n [doc.clientID],\n \"window unload\"\n );\n };\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"unload\", this._unloadHandler);\n } else if (\n typeof process !== \"undefined\" &&\n typeof process.on === \"function\"\n ) {\n process.on(\"exit\", this._unloadHandler);\n }\n // Listen on 'change' (not 'update') so that clock-only awareness\n // renewals (the 15-second heartbeat) do NOT produce network traffic.\n // Only actual state changes (cursor moved, name changed, etc.) are sent.\n // This allows Durable Objects to hibernate when sessions are idle.\n awareness.on(\"change\", this._awarenessUpdateHandler);\n\n // Disable the awareness protocol's built-in check interval.\n // It renews the local clock every 15s (causing wire traffic that defeats\n // DO hibernation) and removes remote peers after 30s of inactivity.\n // We handle peer cleanup via WebSocket close events instead.\n clearInterval(\n (\n awareness as unknown as {\n _checkInterval: ReturnType<typeof setInterval>;\n }\n )._checkInterval\n );\n if (connect) {\n this.connect();\n }\n }\n\n /**\n * @type {boolean}\n */\n get synced() {\n return this._synced;\n }\n\n set synced(state) {\n if (this._synced !== state) {\n this._synced = state;\n this.emit(\"synced\", [state]);\n this.emit(\"sync\", [state]);\n }\n }\n\n destroy() {\n if (this._resyncInterval !== 0) {\n clearInterval(this._resyncInterval);\n }\n this.disconnect();\n if (typeof window !== \"undefined\") {\n window.removeEventListener(\"unload\", this._unloadHandler);\n } else if (\n typeof process !== \"undefined\" &&\n typeof process.off === \"function\"\n ) {\n process.off(\"exit\", this._unloadHandler);\n }\n this.awareness.off(\"change\", this._awarenessUpdateHandler);\n this.doc.off(\"update\", this._updateHandler);\n super.destroy();\n }\n\n connectBc() {\n if (this.disableBc) {\n return;\n }\n if (!this.bcconnected) {\n bc.subscribe(this.bcChannel, this._bcSubscriber);\n this.bcconnected = true;\n }\n // send sync step1 to bc\n // write sync step 1\n const encoderSync = encoding.createEncoder();\n encoding.writeVarUint(encoderSync, messageSync);\n syncProtocol.writeSyncStep1(encoderSync, this.doc);\n bc.publish(this.bcChannel, encoding.toUint8Array(encoderSync), this);\n // broadcast local state\n const encoderState = encoding.createEncoder();\n encoding.writeVarUint(encoderState, messageSync);\n syncProtocol.writeSyncStep2(encoderState, this.doc);\n bc.publish(this.bcChannel, encoding.toUint8Array(encoderState), this);\n // write queryAwareness\n const encoderAwarenessQuery = encoding.createEncoder();\n encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);\n bc.publish(\n this.bcChannel,\n encoding.toUint8Array(encoderAwarenessQuery),\n this\n );\n // broadcast local awareness state\n const encoderAwarenessState = encoding.createEncoder();\n encoding.writeVarUint(encoderAwarenessState, messageAwareness);\n encoding.writeVarUint8Array(\n encoderAwarenessState,\n awarenessProtocol.encodeAwarenessUpdate(this.awareness, [\n this.doc.clientID\n ])\n );\n bc.publish(\n this.bcChannel,\n encoding.toUint8Array(encoderAwarenessState),\n this\n );\n }\n\n disconnectBc() {\n // broadcast message with local awareness state set to null (indicating disconnect)\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.awareness,\n [this.doc.clientID],\n new Map()\n )\n );\n broadcastMessage(this, encoding.toUint8Array(encoder));\n if (this.bcconnected) {\n bc.unsubscribe(this.bcChannel, this._bcSubscriber);\n this.bcconnected = false;\n }\n }\n\n disconnect() {\n this.shouldConnect = false;\n this.disconnectBc();\n if (this.ws !== null) {\n this.ws.close();\n }\n }\n\n /**\n * Called by the close handler to re-establish the WebSocket.\n * Subclasses (e.g. YProvider) override this to refresh dynamic\n * params before reconnecting.\n */\n _reconnectWS() {\n setupWS(this);\n }\n\n connect() {\n this.shouldConnect = true;\n if (!this.wsconnected && this.ws === null) {\n setupWS(this);\n this.connectBc();\n }\n }\n}\n\nfunction assertType(value: unknown, label: string, type: string) {\n if (typeof value !== type) {\n throw new Error(\n `Invalid \"${label}\" parameter provided to YProvider. Expected: ${type}, received: ${value as string}`\n );\n }\n}\n\ntype Params = Record<string, string | null | undefined>;\ntype ParamsProvider = Params | (() => Params | Promise<Params>);\ntype BaseProviderOptions = ConstructorParameters<typeof WebsocketProvider>[3];\n\ntype YProviderOptions = Omit<NonNullable<BaseProviderOptions>, \"params\"> & {\n connectionId?: string;\n party?: string;\n prefix?: string;\n params?: ParamsProvider;\n protocol?: \"ws\" | \"wss\";\n};\n\nexport default class YProvider extends WebsocketProvider {\n id: string;\n #params?: ParamsProvider;\n\n constructor(\n host: string,\n room: string,\n doc?: YDoc,\n options: YProviderOptions = {}\n ) {\n assertType(host, \"host\", \"string\");\n assertType(room, \"room\", \"string\");\n\n // strip the protocol from the beginning of `host` if any\n host = host.replace(/^(http|https|ws|wss):\\/\\//, \"\");\n\n // strip trailing slash from host if any\n if (host.endsWith(\"/\")) {\n host = host.slice(0, -1);\n }\n\n const serverUrl = `${\n options.protocol ||\n (host.startsWith(\"localhost:\") ||\n host.startsWith(\"127.0.0.1:\") ||\n host.startsWith(\"192.168.\") ||\n host.startsWith(\"10.\") ||\n (host.startsWith(\"172.\") &&\n host.split(\".\")[1] >= \"16\" &&\n host.split(\".\")[1] <= \"31\")\n ? \"ws\"\n : \"wss\")\n }://${host}${options.prefix || `/parties/${options.party || \"main\"}`}`;\n\n // use provided id, or generate a random one\n const id = options.connectionId ?? nanoid(10);\n\n // don't pass params to WebsocketProvider, we override them in connect()\n const { params, connect = true, ...rest } = options;\n\n // don't connect until we've updated the url parameters\n const baseOptions = {\n ...rest,\n isPrefixedUrl: !!options.prefix,\n connect: false\n };\n\n super(serverUrl, room, doc ?? new YDoc(), baseOptions);\n\n this.id = id;\n this.#params = params;\n\n if (connect) {\n void this.connect();\n }\n }\n\n async #resolveParams() {\n const nextParams =\n typeof this.#params === \"function\" ? await this.#params() : this.#params;\n const urlParams = new URLSearchParams([[\"_pk\", this.id]]);\n if (nextParams) {\n for (const [key, value] of Object.entries(nextParams)) {\n if (value !== null && value !== undefined) {\n urlParams.append(key, value);\n }\n }\n }\n const nextUrl = new URL(this.url);\n nextUrl.search = urlParams.toString();\n this.url = nextUrl.toString();\n }\n\n async connect() {\n try {\n await this.#resolveParams();\n super.connect();\n } catch (err) {\n console.error(\"Failed to open connecton to PartyServer\", err);\n throw err;\n }\n }\n\n async _reconnectWS() {\n try {\n await this.#resolveParams();\n } catch (err) {\n console.error(\n \"Failed to refresh params, reconnecting with stale params\",\n err\n );\n }\n super._reconnectWS();\n }\n\n sendMessage(message: string) {\n this.ws?.send(`__YPS:${message}`);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["syncProtocol","awarenessProtocol","decoding","encoding","time","math","Observable","url","YDoc","#params","#resolveParams"],"sources":["../../src/provider/index.ts"],"sourcesContent":["import * as bc from \"lib0/broadcastchannel\";\nimport * as decoding from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport * as math from \"lib0/math\";\nimport { Observable } from \"lib0/observable\";\nimport * as time from \"lib0/time\";\nimport * as url from \"lib0/url\";\nimport { nanoid } from \"nanoid\";\nimport * as authProtocol from \"y-protocols/auth\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport { Doc as YDoc } from \"yjs\";\n\nexport const messageSync = 0;\nexport const messageQueryAwareness = 3;\nexport const messageAwareness = 1;\nexport const messageAuth = 2;\n\n// Disable BroadcastChannel by default in Cloudflare Workers / Node\nconst DEFAULT_DISABLE_BC = typeof window === \"undefined\";\n\nconst messageHandlers: Array<\n (\n encoder: encoding.Encoder,\n decoder: decoding.Decoder,\n provider: WebsocketProvider,\n emitSynced: boolean,\n messageType: number\n ) => void\n> = [];\n\nmessageHandlers[messageSync] = (\n encoder,\n decoder,\n provider,\n emitSynced,\n _messageType\n) => {\n encoding.writeVarUint(encoder, messageSync);\n const syncMessageType = syncProtocol.readSyncMessage(\n decoder,\n encoder,\n provider.doc,\n provider\n );\n if (\n emitSynced &&\n syncMessageType === syncProtocol.messageYjsSyncStep2 &&\n !provider.synced\n ) {\n provider.synced = true;\n }\n};\n\nmessageHandlers[messageQueryAwareness] = (\n encoder,\n _decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n provider.awareness,\n Array.from(provider.awareness.getStates().keys())\n )\n );\n};\n\nmessageHandlers[messageAwareness] = (\n _encoder,\n decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n awarenessProtocol.applyAwarenessUpdate(\n provider.awareness,\n decoding.readVarUint8Array(decoder),\n provider\n );\n};\n\nmessageHandlers[messageAuth] = (\n _encoder,\n decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n authProtocol.readAuthMessage(decoder, provider.doc, (_ydoc, reason) =>\n permissionDeniedHandler(provider, reason)\n );\n};\n\nfunction permissionDeniedHandler(provider: WebsocketProvider, reason: string) {\n console.warn(`Permission denied to access ${provider.url}.\\n${reason}`);\n}\n\nfunction readMessage(\n provider: WebsocketProvider,\n buf: Uint8Array,\n emitSynced: boolean\n): encoding.Encoder {\n const decoder = decoding.createDecoder(buf);\n const encoder = encoding.createEncoder();\n const messageType = decoding.readVarUint(decoder);\n const messageHandler = provider.messageHandlers[messageType];\n if (/** @type {any} */ messageHandler) {\n messageHandler(encoder, decoder, provider, emitSynced, messageType);\n } else {\n console.error(\"Unable to compute message\");\n }\n return encoder;\n}\n\nfunction setupWS(provider: WebsocketProvider) {\n if (provider.shouldConnect && provider.ws === null) {\n if (!provider._WS) {\n throw new Error(\n \"No WebSocket implementation available, did you forget to pass options.WebSocketPolyfill?\"\n );\n }\n const websocket = new provider._WS(provider.url);\n websocket.binaryType = \"arraybuffer\";\n provider.ws = websocket;\n provider.wsconnecting = true;\n provider.wsconnected = false;\n provider.synced = false;\n\n websocket.addEventListener(\"message\", (event) => {\n if (typeof event.data === \"string\") {\n // Handle custom messages with __YPS: prefix\n if (event.data.startsWith(\"__YPS:\")) {\n const customMessage = event.data.slice(6); // Remove __YPS: prefix\n provider.emit(\"custom-message\", [customMessage]);\n }\n return;\n }\n provider.wsLastMessageReceived = time.getUnixTime();\n const encoder = readMessage(provider, new Uint8Array(event.data), true);\n if (encoding.length(encoder) > 1) {\n websocket.send(encoding.toUint8Array(encoder));\n }\n });\n websocket.addEventListener(\"error\", (event) => {\n provider.emit(\"connection-error\", [event, provider]);\n });\n websocket.addEventListener(\"close\", (event) => {\n provider.emit(\"connection-close\", [event, provider]);\n provider.ws = null;\n provider.wsconnecting = false;\n if (provider.wsconnected) {\n provider.wsconnected = false;\n provider.synced = false;\n // update awareness (all users except local left)\n const removedClients = Array.from(\n provider.awareness.getStates().keys()\n ).filter((client) => client !== provider.doc.clientID);\n awarenessProtocol.removeAwarenessStates(\n provider.awareness,\n removedClients,\n provider\n );\n // Clear stale meta for remote clients so their awareness\n // updates are accepted on reconnect (clock check starts fresh)\n for (const clientID of removedClients) {\n provider.awareness.meta.delete(clientID);\n }\n provider.emit(\"status\", [\n {\n status: \"disconnected\"\n }\n ]);\n } else {\n provider.wsUnsuccessfulReconnects++;\n }\n // Start with no reconnect timeout and increase timeout by\n // using exponential backoff starting with 100ms\n setTimeout(\n () => {\n if (provider.shouldConnect) {\n Promise.resolve(provider._reconnectWS()).catch((err) => {\n console.error(\"Reconnection failed\", err);\n });\n }\n },\n math.min(\n math.pow(2, provider.wsUnsuccessfulReconnects) * 100,\n provider.maxBackoffTime\n )\n );\n });\n websocket.addEventListener(\"open\", () => {\n provider.wsLastMessageReceived = time.getUnixTime();\n provider.wsconnecting = false;\n provider.wsconnected = true;\n provider.wsUnsuccessfulReconnects = 0;\n provider.emit(\"status\", [\n {\n status: \"connected\"\n }\n ]);\n // always send sync step 1 when connected\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, provider.doc);\n websocket.send(encoding.toUint8Array(encoder));\n // broadcast local awareness state\n if (provider.awareness.getLocalState() !== null) {\n // Re-set local state to bump the awareness clock, ensuring\n // remote clients accept the update even if they have stale meta\n provider.awareness.setLocalState(provider.awareness.getLocalState());\n const encoderAwarenessState = encoding.createEncoder();\n encoding.writeVarUint(encoderAwarenessState, messageAwareness);\n encoding.writeVarUint8Array(\n encoderAwarenessState,\n awarenessProtocol.encodeAwarenessUpdate(provider.awareness, [\n provider.doc.clientID\n ])\n );\n websocket.send(encoding.toUint8Array(encoderAwarenessState));\n }\n });\n provider.emit(\"status\", [\n {\n status: \"connecting\"\n }\n ]);\n }\n}\n\nfunction broadcastMessage(provider: WebsocketProvider, buf: Uint8Array) {\n const ws = provider.ws;\n if (provider.wsconnected && ws && ws.readyState === ws.OPEN) {\n ws.send(buf);\n }\n if (provider.bcconnected) {\n bc.publish(provider.bcChannel, buf, provider);\n }\n}\n\ntype AwarenessUpdate = {\n added: number[];\n updated: number[];\n removed: number[];\n};\n\nconst DefaultWebSocket = typeof WebSocket === \"undefined\" ? null : WebSocket;\n\n/**\n * Websocket Provider for Yjs. Creates a websocket connection to sync the shared document.\n * The document name is attached to the provided url. I.e. the following example\n * creates a websocket connection to http://localhost:1234/my-document-name\n *\n * @example\n * import * as Y from 'yjs'\n * import { WebsocketProvider } from 'y-websocket'\n * const doc = new Y.Doc()\n * const provider = new WebsocketProvider('http://localhost:1234', 'my-document-name', doc)\n *\n * @extends {Observable<string>}\n */\nexport class WebsocketProvider extends Observable<string> {\n maxBackoffTime: number;\n bcChannel: string;\n url: string;\n roomname: string;\n doc: YDoc;\n _WS: typeof WebSocket;\n awareness: awarenessProtocol.Awareness;\n wsconnected: boolean;\n wsconnecting: boolean;\n bcconnected: boolean;\n disableBc: boolean;\n wsUnsuccessfulReconnects: number;\n messageHandlers: typeof messageHandlers;\n _synced: boolean;\n ws: WebSocket | null;\n wsLastMessageReceived: number;\n shouldConnect: boolean; // Whether to connect to other peers or not\n _resyncInterval: ReturnType<typeof setInterval> | number;\n _bcSubscriber: (message: Uint8Array, origin: unknown) => void;\n _updateHandler: (update: Uint8Array, origin: unknown) => void;\n _awarenessUpdateHandler: (update: AwarenessUpdate, origin: unknown) => void;\n _unloadHandler: () => void;\n\n constructor(\n serverUrl: string,\n roomname: string,\n doc: YDoc,\n {\n connect = true,\n awareness = new awarenessProtocol.Awareness(doc),\n params = {},\n isPrefixedUrl = false,\n WebSocketPolyfill = DefaultWebSocket, // Optionally provide a WebSocket polyfill\n resyncInterval = -1, // Request server state every `resyncInterval` milliseconds\n maxBackoffTime = 2500, // Maximum amount of time to wait before trying to reconnect (we try to reconnect using exponential backoff)\n disableBc = DEFAULT_DISABLE_BC // Disable cross-tab BroadcastChannel communication\n }: {\n connect?: boolean;\n awareness?: awarenessProtocol.Awareness;\n params?: { [s: string]: string };\n isPrefixedUrl?: boolean;\n WebSocketPolyfill?: typeof WebSocket | null;\n resyncInterval?: number;\n maxBackoffTime?: number;\n disableBc?: boolean;\n } = {}\n ) {\n super();\n // ensure that url is always ends with /\n while (serverUrl[serverUrl.length - 1] === \"/\") {\n serverUrl = serverUrl.slice(0, serverUrl.length - 1);\n }\n const encodedParams = url.encodeQueryParams(params);\n this.maxBackoffTime = maxBackoffTime;\n this.bcChannel = `${serverUrl}/${roomname}`;\n this.url = isPrefixedUrl\n ? serverUrl\n : `${serverUrl}/${roomname}${encodedParams.length === 0 ? \"\" : `?${encodedParams}`}`;\n this.roomname = roomname;\n this.doc = doc;\n this._WS = WebSocketPolyfill!;\n this.awareness = awareness;\n this.wsconnected = false;\n this.wsconnecting = false;\n this.bcconnected = false;\n this.disableBc = disableBc;\n this.wsUnsuccessfulReconnects = 0;\n this.messageHandlers = messageHandlers.slice();\n\n this._synced = false;\n\n this.ws = null;\n this.wsLastMessageReceived = 0;\n\n this.shouldConnect = connect;\n\n this._resyncInterval = 0;\n if (resyncInterval > 0) {\n this._resyncInterval = /** @type {any} */ setInterval(() => {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n // resend sync step 1\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, doc);\n this.ws.send(encoding.toUint8Array(encoder));\n }\n }, resyncInterval);\n }\n\n this._bcSubscriber = (data: Uint8Array, origin: unknown) => {\n if (origin !== this) {\n const encoder = readMessage(this, new Uint8Array(data), false);\n if (encoding.length(encoder) > 1) {\n bc.publish(this.bcChannel, encoding.toUint8Array(encoder), this);\n }\n }\n };\n /**\n * Listens to Yjs updates and sends them to remote peers (ws and broadcastchannel)\n */\n this._updateHandler = (update: Uint8Array, origin: unknown) => {\n if (origin !== this) {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeUpdate(encoder, update);\n broadcastMessage(this, encoding.toUint8Array(encoder));\n }\n };\n this.doc.on(\"update\", this._updateHandler);\n\n this._awarenessUpdateHandler = (\n { added, updated, removed }: AwarenessUpdate,\n _origin: unknown\n ) => {\n const changedClients = added.concat(updated).concat(removed);\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(awareness, changedClients)\n );\n broadcastMessage(this, encoding.toUint8Array(encoder));\n };\n this._unloadHandler = () => {\n awarenessProtocol.removeAwarenessStates(\n this.awareness,\n [doc.clientID],\n \"window unload\"\n );\n };\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"unload\", this._unloadHandler);\n } else if (\n typeof process !== \"undefined\" &&\n typeof process.on === \"function\"\n ) {\n process.on(\"exit\", this._unloadHandler);\n }\n // Listen on 'change' (not 'update') so that clock-only awareness\n // renewals (the 15-second heartbeat) do NOT produce network traffic.\n // Only actual state changes (cursor moved, name changed, etc.) are sent.\n // This allows Durable Objects to hibernate when sessions are idle.\n awareness.on(\"change\", this._awarenessUpdateHandler);\n\n // Disable the awareness protocol's built-in check interval.\n // It renews the local clock every 15s (causing wire traffic that defeats\n // DO hibernation) and removes remote peers after 30s of inactivity.\n // We handle peer cleanup via WebSocket close events instead.\n clearInterval(\n (\n awareness as unknown as {\n _checkInterval: ReturnType<typeof setInterval>;\n }\n )._checkInterval\n );\n if (connect) {\n this.connect();\n }\n }\n\n /**\n * @type {boolean}\n */\n get synced() {\n return this._synced;\n }\n\n set synced(state) {\n if (this._synced !== state) {\n this._synced = state;\n this.emit(\"synced\", [state]);\n this.emit(\"sync\", [state]);\n }\n }\n\n destroy() {\n if (this._resyncInterval !== 0) {\n clearInterval(this._resyncInterval);\n }\n this.disconnect();\n if (typeof window !== \"undefined\") {\n window.removeEventListener(\"unload\", this._unloadHandler);\n } else if (\n typeof process !== \"undefined\" &&\n typeof process.off === \"function\"\n ) {\n process.off(\"exit\", this._unloadHandler);\n }\n this.awareness.off(\"change\", this._awarenessUpdateHandler);\n this.doc.off(\"update\", this._updateHandler);\n super.destroy();\n }\n\n connectBc() {\n if (this.disableBc) {\n return;\n }\n if (!this.bcconnected) {\n bc.subscribe(this.bcChannel, this._bcSubscriber);\n this.bcconnected = true;\n }\n // send sync step1 to bc\n // write sync step 1\n const encoderSync = encoding.createEncoder();\n encoding.writeVarUint(encoderSync, messageSync);\n syncProtocol.writeSyncStep1(encoderSync, this.doc);\n bc.publish(this.bcChannel, encoding.toUint8Array(encoderSync), this);\n // broadcast local state\n const encoderState = encoding.createEncoder();\n encoding.writeVarUint(encoderState, messageSync);\n syncProtocol.writeSyncStep2(encoderState, this.doc);\n bc.publish(this.bcChannel, encoding.toUint8Array(encoderState), this);\n // write queryAwareness\n const encoderAwarenessQuery = encoding.createEncoder();\n encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);\n bc.publish(\n this.bcChannel,\n encoding.toUint8Array(encoderAwarenessQuery),\n this\n );\n // broadcast local awareness state\n const encoderAwarenessState = encoding.createEncoder();\n encoding.writeVarUint(encoderAwarenessState, messageAwareness);\n encoding.writeVarUint8Array(\n encoderAwarenessState,\n awarenessProtocol.encodeAwarenessUpdate(this.awareness, [\n this.doc.clientID\n ])\n );\n bc.publish(\n this.bcChannel,\n encoding.toUint8Array(encoderAwarenessState),\n this\n );\n }\n\n disconnectBc() {\n // broadcast message with local awareness state set to null (indicating disconnect)\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.awareness,\n [this.doc.clientID],\n new Map()\n )\n );\n broadcastMessage(this, encoding.toUint8Array(encoder));\n if (this.bcconnected) {\n bc.unsubscribe(this.bcChannel, this._bcSubscriber);\n this.bcconnected = false;\n }\n }\n\n disconnect() {\n this.shouldConnect = false;\n this.disconnectBc();\n if (this.ws !== null) {\n this.ws.close();\n }\n }\n\n /**\n * Called by the close handler to re-establish the WebSocket.\n * Subclasses (e.g. YProvider) override this to refresh dynamic\n * params before reconnecting.\n */\n _reconnectWS() {\n setupWS(this);\n }\n\n connect() {\n this.shouldConnect = true;\n if (!this.wsconnected && this.ws === null) {\n setupWS(this);\n this.connectBc();\n }\n }\n}\n\nfunction assertType(value: unknown, label: string, type: string) {\n if (typeof value !== type) {\n throw new Error(\n `Invalid \"${label}\" parameter provided to YProvider. Expected: ${type}, received: ${value as string}`\n );\n }\n}\n\ntype Params = Record<string, string | null | undefined>;\ntype ParamsProvider = Params | (() => Params | Promise<Params>);\ntype BaseProviderOptions = ConstructorParameters<typeof WebsocketProvider>[3];\n\ntype YProviderOptions = Omit<NonNullable<BaseProviderOptions>, \"params\"> & {\n connectionId?: string;\n party?: string;\n prefix?: string;\n params?: ParamsProvider;\n protocol?: \"ws\" | \"wss\";\n};\n\nexport default class YProvider extends WebsocketProvider {\n id: string;\n #params?: ParamsProvider;\n\n constructor(\n host: string,\n room: string,\n doc?: YDoc,\n options: YProviderOptions = {}\n ) {\n assertType(host, \"host\", \"string\");\n assertType(room, \"room\", \"string\");\n\n // strip the protocol from the beginning of `host` if any\n host = host.replace(/^(http|https|ws|wss):\\/\\//, \"\");\n\n // strip trailing slash from host if any\n if (host.endsWith(\"/\")) {\n host = host.slice(0, -1);\n }\n\n const serverUrl = `${\n options.protocol ||\n (host.startsWith(\"localhost:\") ||\n host.startsWith(\"127.0.0.1:\") ||\n host.startsWith(\"192.168.\") ||\n host.startsWith(\"10.\") ||\n (host.startsWith(\"172.\") &&\n host.split(\".\")[1] >= \"16\" &&\n host.split(\".\")[1] <= \"31\")\n ? \"ws\"\n : \"wss\")\n }://${host}${options.prefix || `/parties/${options.party || \"main\"}`}`;\n\n // use provided id, or generate a random one\n const id = options.connectionId ?? nanoid(10);\n\n // don't pass params to WebsocketProvider, we override them in connect()\n const { params, connect = true, ...rest } = options;\n\n // don't connect until we've updated the url parameters\n const baseOptions = {\n ...rest,\n isPrefixedUrl: !!options.prefix,\n connect: false\n };\n\n super(serverUrl, room, doc ?? new YDoc(), baseOptions);\n\n this.id = id;\n this.#params = params;\n\n if (connect) {\n void this.connect();\n }\n }\n\n async #resolveParams() {\n const nextParams =\n typeof this.#params === \"function\" ? await this.#params() : this.#params;\n const urlParams = new URLSearchParams([[\"_pk\", this.id]]);\n if (nextParams) {\n for (const [key, value] of Object.entries(nextParams)) {\n if (value !== null && value !== undefined) {\n urlParams.append(key, value);\n }\n }\n }\n const nextUrl = new URL(this.url);\n nextUrl.search = urlParams.toString();\n this.url = nextUrl.toString();\n }\n\n async connect() {\n try {\n await this.#resolveParams();\n super.connect();\n } catch (err) {\n console.error(\"Failed to open connecton to PartyServer\", err);\n throw err;\n }\n }\n\n async _reconnectWS() {\n try {\n await this.#resolveParams();\n } catch (err) {\n console.error(\n \"Failed to refresh params, reconnecting with stale params\",\n err\n );\n }\n super._reconnectWS();\n }\n\n sendMessage(message: string) {\n this.ws?.send(`__YPS:${message}`);\n }\n}\n"],"mappings":"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"}
@@ -10,7 +10,6 @@ import * as time from "lib0/time";
10
10
  import * as url from "lib0/url";
11
11
  import { nanoid } from "nanoid";
12
12
  import * as authProtocol from "y-protocols/auth";
13
-
14
13
  //#region src/provider/index.ts
15
14
  const messageSync = 0;
16
15
  const messageQueryAwareness = 3;
@@ -18,14 +17,8 @@ const messageAwareness = 1;
18
17
  const messageAuth = 2;
19
18
  const DEFAULT_DISABLE_BC = typeof window === "undefined";
20
19
  const messageHandlers = [];
21
- messageHandlers[messageSync] = (
22
- encoder,
23
- decoder,
24
- provider,
25
- emitSynced,
26
- _messageType
27
- ) => {
28
- encoding.writeVarUint(encoder, messageSync);
20
+ messageHandlers[0] = (encoder, decoder, provider, emitSynced, _messageType) => {
21
+ encoding.writeVarUint(encoder, 0);
29
22
  const syncMessageType = syncProtocol.readSyncMessage(
30
23
  decoder,
31
24
  encoder,
@@ -39,14 +32,14 @@ messageHandlers[messageSync] = (
39
32
  )
40
33
  provider.synced = true;
41
34
  };
42
- messageHandlers[messageQueryAwareness] = (
35
+ messageHandlers[3] = (
43
36
  encoder,
44
37
  _decoder,
45
38
  provider,
46
39
  _emitSynced,
47
40
  _messageType
48
41
  ) => {
49
- encoding.writeVarUint(encoder, messageAwareness);
42
+ encoding.writeVarUint(encoder, 1);
50
43
  encoding.writeVarUint8Array(
51
44
  encoder,
52
45
  awarenessProtocol.encodeAwarenessUpdate(
@@ -55,7 +48,7 @@ messageHandlers[messageQueryAwareness] = (
55
48
  )
56
49
  );
57
50
  };
58
- messageHandlers[messageAwareness] = (
51
+ messageHandlers[1] = (
59
52
  _encoder,
60
53
  decoder,
61
54
  provider,
@@ -68,7 +61,7 @@ messageHandlers[messageAwareness] = (
68
61
  provider
69
62
  );
70
63
  };
71
- messageHandlers[messageAuth] = (
64
+ messageHandlers[2] = (
72
65
  _encoder,
73
66
  decoder,
74
67
  provider,
@@ -159,13 +152,13 @@ function setupWS(provider) {
159
152
  provider.wsUnsuccessfulReconnects = 0;
160
153
  provider.emit("status", [{ status: "connected" }]);
161
154
  const encoder = encoding.createEncoder();
162
- encoding.writeVarUint(encoder, messageSync);
155
+ encoding.writeVarUint(encoder, 0);
163
156
  syncProtocol.writeSyncStep1(encoder, provider.doc);
164
157
  websocket.send(encoding.toUint8Array(encoder));
165
158
  if (provider.awareness.getLocalState() !== null) {
166
159
  provider.awareness.setLocalState(provider.awareness.getLocalState());
167
160
  const encoderAwarenessState = encoding.createEncoder();
168
- encoding.writeVarUint(encoderAwarenessState, messageAwareness);
161
+ encoding.writeVarUint(encoderAwarenessState, 1);
169
162
  encoding.writeVarUint8Array(
170
163
  encoderAwarenessState,
171
164
  awarenessProtocol.encodeAwarenessUpdate(provider.awareness, [
@@ -263,7 +256,7 @@ var WebsocketProvider = class extends Observable {
263
256
  this._resyncInterval = setInterval(() => {
264
257
  if (this.ws && this.ws.readyState === WebSocket.OPEN) {
265
258
  const encoder = encoding.createEncoder();
266
- encoding.writeVarUint(encoder, messageSync);
259
+ encoding.writeVarUint(encoder, 0);
267
260
  syncProtocol.writeSyncStep1(encoder, doc);
268
261
  this.ws.send(encoding.toUint8Array(encoder));
269
262
  }
@@ -281,7 +274,7 @@ var WebsocketProvider = class extends Observable {
281
274
  this._updateHandler = (update, origin) => {
282
275
  if (origin !== this) {
283
276
  const encoder = encoding.createEncoder();
284
- encoding.writeVarUint(encoder, messageSync);
277
+ encoding.writeVarUint(encoder, 0);
285
278
  syncProtocol.writeUpdate(encoder, update);
286
279
  broadcastMessage(this, encoding.toUint8Array(encoder));
287
280
  }
@@ -290,7 +283,7 @@ var WebsocketProvider = class extends Observable {
290
283
  this._awarenessUpdateHandler = ({ added, updated, removed }, _origin) => {
291
284
  const changedClients = added.concat(updated).concat(removed);
292
285
  const encoder = encoding.createEncoder();
293
- encoding.writeVarUint(encoder, messageAwareness);
286
+ encoding.writeVarUint(encoder, 1);
294
287
  encoding.writeVarUint8Array(
295
288
  encoder,
296
289
  awarenessProtocol.encodeAwarenessUpdate(awareness, changedClients)
@@ -346,22 +339,22 @@ var WebsocketProvider = class extends Observable {
346
339
  this.bcconnected = true;
347
340
  }
348
341
  const encoderSync = encoding.createEncoder();
349
- encoding.writeVarUint(encoderSync, messageSync);
342
+ encoding.writeVarUint(encoderSync, 0);
350
343
  syncProtocol.writeSyncStep1(encoderSync, this.doc);
351
344
  bc.publish(this.bcChannel, encoding.toUint8Array(encoderSync), this);
352
345
  const encoderState = encoding.createEncoder();
353
- encoding.writeVarUint(encoderState, messageSync);
346
+ encoding.writeVarUint(encoderState, 0);
354
347
  syncProtocol.writeSyncStep2(encoderState, this.doc);
355
348
  bc.publish(this.bcChannel, encoding.toUint8Array(encoderState), this);
356
349
  const encoderAwarenessQuery = encoding.createEncoder();
357
- encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
350
+ encoding.writeVarUint(encoderAwarenessQuery, 3);
358
351
  bc.publish(
359
352
  this.bcChannel,
360
353
  encoding.toUint8Array(encoderAwarenessQuery),
361
354
  this
362
355
  );
363
356
  const encoderAwarenessState = encoding.createEncoder();
364
- encoding.writeVarUint(encoderAwarenessState, messageAwareness);
357
+ encoding.writeVarUint(encoderAwarenessState, 1);
365
358
  encoding.writeVarUint8Array(
366
359
  encoderAwarenessState,
367
360
  awarenessProtocol.encodeAwarenessUpdate(this.awareness, [
@@ -376,7 +369,7 @@ var WebsocketProvider = class extends Observable {
376
369
  }
377
370
  disconnectBc() {
378
371
  const encoder = encoding.createEncoder();
379
- encoding.writeVarUint(encoder, messageAwareness);
372
+ encoding.writeVarUint(encoder, 1);
380
373
  encoding.writeVarUint8Array(
381
374
  encoder,
382
375
  awarenessProtocol.encodeAwarenessUpdate(
@@ -475,7 +468,6 @@ var YProvider = class extends WebsocketProvider {
475
468
  this.ws?.send(`__YPS:${message}`);
476
469
  }
477
470
  };
478
-
479
471
  //#endregion
480
472
  export {
481
473
  WebsocketProvider,
@@ -485,4 +477,5 @@ export {
485
477
  messageQueryAwareness,
486
478
  messageSync
487
479
  };
480
+
488
481
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["YDoc","#params","#resolveParams"],"sources":["../../src/provider/index.ts"],"sourcesContent":["import * as bc from \"lib0/broadcastchannel\";\nimport * as decoding from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport * as math from \"lib0/math\";\nimport { Observable } from \"lib0/observable\";\nimport * as time from \"lib0/time\";\nimport * as url from \"lib0/url\";\nimport { nanoid } from \"nanoid\";\nimport * as authProtocol from \"y-protocols/auth\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport { Doc as YDoc } from \"yjs\";\n\nexport const messageSync = 0;\nexport const messageQueryAwareness = 3;\nexport const messageAwareness = 1;\nexport const messageAuth = 2;\n\n// Disable BroadcastChannel by default in Cloudflare Workers / Node\nconst DEFAULT_DISABLE_BC = typeof window === \"undefined\";\n\nconst messageHandlers: Array<\n (\n encoder: encoding.Encoder,\n decoder: decoding.Decoder,\n provider: WebsocketProvider,\n emitSynced: boolean,\n messageType: number\n ) => void\n> = [];\n\nmessageHandlers[messageSync] = (\n encoder,\n decoder,\n provider,\n emitSynced,\n _messageType\n) => {\n encoding.writeVarUint(encoder, messageSync);\n const syncMessageType = syncProtocol.readSyncMessage(\n decoder,\n encoder,\n provider.doc,\n provider\n );\n if (\n emitSynced &&\n syncMessageType === syncProtocol.messageYjsSyncStep2 &&\n !provider.synced\n ) {\n provider.synced = true;\n }\n};\n\nmessageHandlers[messageQueryAwareness] = (\n encoder,\n _decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n provider.awareness,\n Array.from(provider.awareness.getStates().keys())\n )\n );\n};\n\nmessageHandlers[messageAwareness] = (\n _encoder,\n decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n awarenessProtocol.applyAwarenessUpdate(\n provider.awareness,\n decoding.readVarUint8Array(decoder),\n provider\n );\n};\n\nmessageHandlers[messageAuth] = (\n _encoder,\n decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n authProtocol.readAuthMessage(decoder, provider.doc, (_ydoc, reason) =>\n permissionDeniedHandler(provider, reason)\n );\n};\n\nfunction permissionDeniedHandler(provider: WebsocketProvider, reason: string) {\n console.warn(`Permission denied to access ${provider.url}.\\n${reason}`);\n}\n\nfunction readMessage(\n provider: WebsocketProvider,\n buf: Uint8Array,\n emitSynced: boolean\n): encoding.Encoder {\n const decoder = decoding.createDecoder(buf);\n const encoder = encoding.createEncoder();\n const messageType = decoding.readVarUint(decoder);\n const messageHandler = provider.messageHandlers[messageType];\n if (/** @type {any} */ messageHandler) {\n messageHandler(encoder, decoder, provider, emitSynced, messageType);\n } else {\n console.error(\"Unable to compute message\");\n }\n return encoder;\n}\n\nfunction setupWS(provider: WebsocketProvider) {\n if (provider.shouldConnect && provider.ws === null) {\n if (!provider._WS) {\n throw new Error(\n \"No WebSocket implementation available, did you forget to pass options.WebSocketPolyfill?\"\n );\n }\n const websocket = new provider._WS(provider.url);\n websocket.binaryType = \"arraybuffer\";\n provider.ws = websocket;\n provider.wsconnecting = true;\n provider.wsconnected = false;\n provider.synced = false;\n\n websocket.addEventListener(\"message\", (event) => {\n if (typeof event.data === \"string\") {\n // Handle custom messages with __YPS: prefix\n if (event.data.startsWith(\"__YPS:\")) {\n const customMessage = event.data.slice(6); // Remove __YPS: prefix\n provider.emit(\"custom-message\", [customMessage]);\n }\n return;\n }\n provider.wsLastMessageReceived = time.getUnixTime();\n const encoder = readMessage(provider, new Uint8Array(event.data), true);\n if (encoding.length(encoder) > 1) {\n websocket.send(encoding.toUint8Array(encoder));\n }\n });\n websocket.addEventListener(\"error\", (event) => {\n provider.emit(\"connection-error\", [event, provider]);\n });\n websocket.addEventListener(\"close\", (event) => {\n provider.emit(\"connection-close\", [event, provider]);\n provider.ws = null;\n provider.wsconnecting = false;\n if (provider.wsconnected) {\n provider.wsconnected = false;\n provider.synced = false;\n // update awareness (all users except local left)\n const removedClients = Array.from(\n provider.awareness.getStates().keys()\n ).filter((client) => client !== provider.doc.clientID);\n awarenessProtocol.removeAwarenessStates(\n provider.awareness,\n removedClients,\n provider\n );\n // Clear stale meta for remote clients so their awareness\n // updates are accepted on reconnect (clock check starts fresh)\n for (const clientID of removedClients) {\n provider.awareness.meta.delete(clientID);\n }\n provider.emit(\"status\", [\n {\n status: \"disconnected\"\n }\n ]);\n } else {\n provider.wsUnsuccessfulReconnects++;\n }\n // Start with no reconnect timeout and increase timeout by\n // using exponential backoff starting with 100ms\n setTimeout(\n () => {\n if (provider.shouldConnect) {\n Promise.resolve(provider._reconnectWS()).catch((err) => {\n console.error(\"Reconnection failed\", err);\n });\n }\n },\n math.min(\n math.pow(2, provider.wsUnsuccessfulReconnects) * 100,\n provider.maxBackoffTime\n )\n );\n });\n websocket.addEventListener(\"open\", () => {\n provider.wsLastMessageReceived = time.getUnixTime();\n provider.wsconnecting = false;\n provider.wsconnected = true;\n provider.wsUnsuccessfulReconnects = 0;\n provider.emit(\"status\", [\n {\n status: \"connected\"\n }\n ]);\n // always send sync step 1 when connected\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, provider.doc);\n websocket.send(encoding.toUint8Array(encoder));\n // broadcast local awareness state\n if (provider.awareness.getLocalState() !== null) {\n // Re-set local state to bump the awareness clock, ensuring\n // remote clients accept the update even if they have stale meta\n provider.awareness.setLocalState(provider.awareness.getLocalState());\n const encoderAwarenessState = encoding.createEncoder();\n encoding.writeVarUint(encoderAwarenessState, messageAwareness);\n encoding.writeVarUint8Array(\n encoderAwarenessState,\n awarenessProtocol.encodeAwarenessUpdate(provider.awareness, [\n provider.doc.clientID\n ])\n );\n websocket.send(encoding.toUint8Array(encoderAwarenessState));\n }\n });\n provider.emit(\"status\", [\n {\n status: \"connecting\"\n }\n ]);\n }\n}\n\nfunction broadcastMessage(provider: WebsocketProvider, buf: Uint8Array) {\n const ws = provider.ws;\n if (provider.wsconnected && ws && ws.readyState === ws.OPEN) {\n ws.send(buf);\n }\n if (provider.bcconnected) {\n bc.publish(provider.bcChannel, buf, provider);\n }\n}\n\ntype AwarenessUpdate = {\n added: number[];\n updated: number[];\n removed: number[];\n};\n\nconst DefaultWebSocket = typeof WebSocket === \"undefined\" ? null : WebSocket;\n\n/**\n * Websocket Provider for Yjs. Creates a websocket connection to sync the shared document.\n * The document name is attached to the provided url. I.e. the following example\n * creates a websocket connection to http://localhost:1234/my-document-name\n *\n * @example\n * import * as Y from 'yjs'\n * import { WebsocketProvider } from 'y-websocket'\n * const doc = new Y.Doc()\n * const provider = new WebsocketProvider('http://localhost:1234', 'my-document-name', doc)\n *\n * @extends {Observable<string>}\n */\nexport class WebsocketProvider extends Observable<string> {\n maxBackoffTime: number;\n bcChannel: string;\n url: string;\n roomname: string;\n doc: YDoc;\n _WS: typeof WebSocket;\n awareness: awarenessProtocol.Awareness;\n wsconnected: boolean;\n wsconnecting: boolean;\n bcconnected: boolean;\n disableBc: boolean;\n wsUnsuccessfulReconnects: number;\n messageHandlers: typeof messageHandlers;\n _synced: boolean;\n ws: WebSocket | null;\n wsLastMessageReceived: number;\n shouldConnect: boolean; // Whether to connect to other peers or not\n _resyncInterval: ReturnType<typeof setInterval> | number;\n _bcSubscriber: (message: Uint8Array, origin: unknown) => void;\n _updateHandler: (update: Uint8Array, origin: unknown) => void;\n _awarenessUpdateHandler: (update: AwarenessUpdate, origin: unknown) => void;\n _unloadHandler: () => void;\n\n constructor(\n serverUrl: string,\n roomname: string,\n doc: YDoc,\n {\n connect = true,\n awareness = new awarenessProtocol.Awareness(doc),\n params = {},\n isPrefixedUrl = false,\n WebSocketPolyfill = DefaultWebSocket, // Optionally provide a WebSocket polyfill\n resyncInterval = -1, // Request server state every `resyncInterval` milliseconds\n maxBackoffTime = 2500, // Maximum amount of time to wait before trying to reconnect (we try to reconnect using exponential backoff)\n disableBc = DEFAULT_DISABLE_BC // Disable cross-tab BroadcastChannel communication\n }: {\n connect?: boolean;\n awareness?: awarenessProtocol.Awareness;\n params?: { [s: string]: string };\n isPrefixedUrl?: boolean;\n WebSocketPolyfill?: typeof WebSocket | null;\n resyncInterval?: number;\n maxBackoffTime?: number;\n disableBc?: boolean;\n } = {}\n ) {\n super();\n // ensure that url is always ends with /\n while (serverUrl[serverUrl.length - 1] === \"/\") {\n serverUrl = serverUrl.slice(0, serverUrl.length - 1);\n }\n const encodedParams = url.encodeQueryParams(params);\n this.maxBackoffTime = maxBackoffTime;\n this.bcChannel = `${serverUrl}/${roomname}`;\n this.url = isPrefixedUrl\n ? serverUrl\n : `${serverUrl}/${roomname}${encodedParams.length === 0 ? \"\" : `?${encodedParams}`}`;\n this.roomname = roomname;\n this.doc = doc;\n this._WS = WebSocketPolyfill!;\n this.awareness = awareness;\n this.wsconnected = false;\n this.wsconnecting = false;\n this.bcconnected = false;\n this.disableBc = disableBc;\n this.wsUnsuccessfulReconnects = 0;\n this.messageHandlers = messageHandlers.slice();\n\n this._synced = false;\n\n this.ws = null;\n this.wsLastMessageReceived = 0;\n\n this.shouldConnect = connect;\n\n this._resyncInterval = 0;\n if (resyncInterval > 0) {\n this._resyncInterval = /** @type {any} */ setInterval(() => {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n // resend sync step 1\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, doc);\n this.ws.send(encoding.toUint8Array(encoder));\n }\n }, resyncInterval);\n }\n\n this._bcSubscriber = (data: Uint8Array, origin: unknown) => {\n if (origin !== this) {\n const encoder = readMessage(this, new Uint8Array(data), false);\n if (encoding.length(encoder) > 1) {\n bc.publish(this.bcChannel, encoding.toUint8Array(encoder), this);\n }\n }\n };\n /**\n * Listens to Yjs updates and sends them to remote peers (ws and broadcastchannel)\n */\n this._updateHandler = (update: Uint8Array, origin: unknown) => {\n if (origin !== this) {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeUpdate(encoder, update);\n broadcastMessage(this, encoding.toUint8Array(encoder));\n }\n };\n this.doc.on(\"update\", this._updateHandler);\n\n this._awarenessUpdateHandler = (\n { added, updated, removed }: AwarenessUpdate,\n _origin: unknown\n ) => {\n const changedClients = added.concat(updated).concat(removed);\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(awareness, changedClients)\n );\n broadcastMessage(this, encoding.toUint8Array(encoder));\n };\n this._unloadHandler = () => {\n awarenessProtocol.removeAwarenessStates(\n this.awareness,\n [doc.clientID],\n \"window unload\"\n );\n };\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"unload\", this._unloadHandler);\n } else if (\n typeof process !== \"undefined\" &&\n typeof process.on === \"function\"\n ) {\n process.on(\"exit\", this._unloadHandler);\n }\n // Listen on 'change' (not 'update') so that clock-only awareness\n // renewals (the 15-second heartbeat) do NOT produce network traffic.\n // Only actual state changes (cursor moved, name changed, etc.) are sent.\n // This allows Durable Objects to hibernate when sessions are idle.\n awareness.on(\"change\", this._awarenessUpdateHandler);\n\n // Disable the awareness protocol's built-in check interval.\n // It renews the local clock every 15s (causing wire traffic that defeats\n // DO hibernation) and removes remote peers after 30s of inactivity.\n // We handle peer cleanup via WebSocket close events instead.\n clearInterval(\n (\n awareness as unknown as {\n _checkInterval: ReturnType<typeof setInterval>;\n }\n )._checkInterval\n );\n if (connect) {\n this.connect();\n }\n }\n\n /**\n * @type {boolean}\n */\n get synced() {\n return this._synced;\n }\n\n set synced(state) {\n if (this._synced !== state) {\n this._synced = state;\n this.emit(\"synced\", [state]);\n this.emit(\"sync\", [state]);\n }\n }\n\n destroy() {\n if (this._resyncInterval !== 0) {\n clearInterval(this._resyncInterval);\n }\n this.disconnect();\n if (typeof window !== \"undefined\") {\n window.removeEventListener(\"unload\", this._unloadHandler);\n } else if (\n typeof process !== \"undefined\" &&\n typeof process.off === \"function\"\n ) {\n process.off(\"exit\", this._unloadHandler);\n }\n this.awareness.off(\"change\", this._awarenessUpdateHandler);\n this.doc.off(\"update\", this._updateHandler);\n super.destroy();\n }\n\n connectBc() {\n if (this.disableBc) {\n return;\n }\n if (!this.bcconnected) {\n bc.subscribe(this.bcChannel, this._bcSubscriber);\n this.bcconnected = true;\n }\n // send sync step1 to bc\n // write sync step 1\n const encoderSync = encoding.createEncoder();\n encoding.writeVarUint(encoderSync, messageSync);\n syncProtocol.writeSyncStep1(encoderSync, this.doc);\n bc.publish(this.bcChannel, encoding.toUint8Array(encoderSync), this);\n // broadcast local state\n const encoderState = encoding.createEncoder();\n encoding.writeVarUint(encoderState, messageSync);\n syncProtocol.writeSyncStep2(encoderState, this.doc);\n bc.publish(this.bcChannel, encoding.toUint8Array(encoderState), this);\n // write queryAwareness\n const encoderAwarenessQuery = encoding.createEncoder();\n encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);\n bc.publish(\n this.bcChannel,\n encoding.toUint8Array(encoderAwarenessQuery),\n this\n );\n // broadcast local awareness state\n const encoderAwarenessState = encoding.createEncoder();\n encoding.writeVarUint(encoderAwarenessState, messageAwareness);\n encoding.writeVarUint8Array(\n encoderAwarenessState,\n awarenessProtocol.encodeAwarenessUpdate(this.awareness, [\n this.doc.clientID\n ])\n );\n bc.publish(\n this.bcChannel,\n encoding.toUint8Array(encoderAwarenessState),\n this\n );\n }\n\n disconnectBc() {\n // broadcast message with local awareness state set to null (indicating disconnect)\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.awareness,\n [this.doc.clientID],\n new Map()\n )\n );\n broadcastMessage(this, encoding.toUint8Array(encoder));\n if (this.bcconnected) {\n bc.unsubscribe(this.bcChannel, this._bcSubscriber);\n this.bcconnected = false;\n }\n }\n\n disconnect() {\n this.shouldConnect = false;\n this.disconnectBc();\n if (this.ws !== null) {\n this.ws.close();\n }\n }\n\n /**\n * Called by the close handler to re-establish the WebSocket.\n * Subclasses (e.g. YProvider) override this to refresh dynamic\n * params before reconnecting.\n */\n _reconnectWS() {\n setupWS(this);\n }\n\n connect() {\n this.shouldConnect = true;\n if (!this.wsconnected && this.ws === null) {\n setupWS(this);\n this.connectBc();\n }\n }\n}\n\nfunction assertType(value: unknown, label: string, type: string) {\n if (typeof value !== type) {\n throw new Error(\n `Invalid \"${label}\" parameter provided to YProvider. Expected: ${type}, received: ${value as string}`\n );\n }\n}\n\ntype Params = Record<string, string | null | undefined>;\ntype ParamsProvider = Params | (() => Params | Promise<Params>);\ntype BaseProviderOptions = ConstructorParameters<typeof WebsocketProvider>[3];\n\ntype YProviderOptions = Omit<NonNullable<BaseProviderOptions>, \"params\"> & {\n connectionId?: string;\n party?: string;\n prefix?: string;\n params?: ParamsProvider;\n protocol?: \"ws\" | \"wss\";\n};\n\nexport default class YProvider extends WebsocketProvider {\n id: string;\n #params?: ParamsProvider;\n\n constructor(\n host: string,\n room: string,\n doc?: YDoc,\n options: YProviderOptions = {}\n ) {\n assertType(host, \"host\", \"string\");\n assertType(room, \"room\", \"string\");\n\n // strip the protocol from the beginning of `host` if any\n host = host.replace(/^(http|https|ws|wss):\\/\\//, \"\");\n\n // strip trailing slash from host if any\n if (host.endsWith(\"/\")) {\n host = host.slice(0, -1);\n }\n\n const serverUrl = `${\n options.protocol ||\n (host.startsWith(\"localhost:\") ||\n host.startsWith(\"127.0.0.1:\") ||\n host.startsWith(\"192.168.\") ||\n host.startsWith(\"10.\") ||\n (host.startsWith(\"172.\") &&\n host.split(\".\")[1] >= \"16\" &&\n host.split(\".\")[1] <= \"31\")\n ? \"ws\"\n : \"wss\")\n }://${host}${options.prefix || `/parties/${options.party || \"main\"}`}`;\n\n // use provided id, or generate a random one\n const id = options.connectionId ?? nanoid(10);\n\n // don't pass params to WebsocketProvider, we override them in connect()\n const { params, connect = true, ...rest } = options;\n\n // don't connect until we've updated the url parameters\n const baseOptions = {\n ...rest,\n isPrefixedUrl: !!options.prefix,\n connect: false\n };\n\n super(serverUrl, room, doc ?? new YDoc(), baseOptions);\n\n this.id = id;\n this.#params = params;\n\n if (connect) {\n void this.connect();\n }\n }\n\n async #resolveParams() {\n const nextParams =\n typeof this.#params === \"function\" ? await this.#params() : this.#params;\n const urlParams = new URLSearchParams([[\"_pk\", this.id]]);\n if (nextParams) {\n for (const [key, value] of Object.entries(nextParams)) {\n if (value !== null && value !== undefined) {\n urlParams.append(key, value);\n }\n }\n }\n const nextUrl = new URL(this.url);\n nextUrl.search = urlParams.toString();\n this.url = nextUrl.toString();\n }\n\n async connect() {\n try {\n await this.#resolveParams();\n super.connect();\n } catch (err) {\n console.error(\"Failed to open connecton to PartyServer\", err);\n throw err;\n }\n }\n\n async _reconnectWS() {\n try {\n await this.#resolveParams();\n } catch (err) {\n console.error(\n \"Failed to refresh params, reconnecting with stale params\",\n err\n );\n }\n super._reconnectWS();\n }\n\n sendMessage(message: string) {\n this.ws?.send(`__YPS:${message}`);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["YDoc","#params","#resolveParams"],"sources":["../../src/provider/index.ts"],"sourcesContent":["import * as bc from \"lib0/broadcastchannel\";\nimport * as decoding from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport * as math from \"lib0/math\";\nimport { Observable } from \"lib0/observable\";\nimport * as time from \"lib0/time\";\nimport * as url from \"lib0/url\";\nimport { nanoid } from \"nanoid\";\nimport * as authProtocol from \"y-protocols/auth\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport { Doc as YDoc } from \"yjs\";\n\nexport const messageSync = 0;\nexport const messageQueryAwareness = 3;\nexport const messageAwareness = 1;\nexport const messageAuth = 2;\n\n// Disable BroadcastChannel by default in Cloudflare Workers / Node\nconst DEFAULT_DISABLE_BC = typeof window === \"undefined\";\n\nconst messageHandlers: Array<\n (\n encoder: encoding.Encoder,\n decoder: decoding.Decoder,\n provider: WebsocketProvider,\n emitSynced: boolean,\n messageType: number\n ) => void\n> = [];\n\nmessageHandlers[messageSync] = (\n encoder,\n decoder,\n provider,\n emitSynced,\n _messageType\n) => {\n encoding.writeVarUint(encoder, messageSync);\n const syncMessageType = syncProtocol.readSyncMessage(\n decoder,\n encoder,\n provider.doc,\n provider\n );\n if (\n emitSynced &&\n syncMessageType === syncProtocol.messageYjsSyncStep2 &&\n !provider.synced\n ) {\n provider.synced = true;\n }\n};\n\nmessageHandlers[messageQueryAwareness] = (\n encoder,\n _decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n provider.awareness,\n Array.from(provider.awareness.getStates().keys())\n )\n );\n};\n\nmessageHandlers[messageAwareness] = (\n _encoder,\n decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n awarenessProtocol.applyAwarenessUpdate(\n provider.awareness,\n decoding.readVarUint8Array(decoder),\n provider\n );\n};\n\nmessageHandlers[messageAuth] = (\n _encoder,\n decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n authProtocol.readAuthMessage(decoder, provider.doc, (_ydoc, reason) =>\n permissionDeniedHandler(provider, reason)\n );\n};\n\nfunction permissionDeniedHandler(provider: WebsocketProvider, reason: string) {\n console.warn(`Permission denied to access ${provider.url}.\\n${reason}`);\n}\n\nfunction readMessage(\n provider: WebsocketProvider,\n buf: Uint8Array,\n emitSynced: boolean\n): encoding.Encoder {\n const decoder = decoding.createDecoder(buf);\n const encoder = encoding.createEncoder();\n const messageType = decoding.readVarUint(decoder);\n const messageHandler = provider.messageHandlers[messageType];\n if (/** @type {any} */ messageHandler) {\n messageHandler(encoder, decoder, provider, emitSynced, messageType);\n } else {\n console.error(\"Unable to compute message\");\n }\n return encoder;\n}\n\nfunction setupWS(provider: WebsocketProvider) {\n if (provider.shouldConnect && provider.ws === null) {\n if (!provider._WS) {\n throw new Error(\n \"No WebSocket implementation available, did you forget to pass options.WebSocketPolyfill?\"\n );\n }\n const websocket = new provider._WS(provider.url);\n websocket.binaryType = \"arraybuffer\";\n provider.ws = websocket;\n provider.wsconnecting = true;\n provider.wsconnected = false;\n provider.synced = false;\n\n websocket.addEventListener(\"message\", (event) => {\n if (typeof event.data === \"string\") {\n // Handle custom messages with __YPS: prefix\n if (event.data.startsWith(\"__YPS:\")) {\n const customMessage = event.data.slice(6); // Remove __YPS: prefix\n provider.emit(\"custom-message\", [customMessage]);\n }\n return;\n }\n provider.wsLastMessageReceived = time.getUnixTime();\n const encoder = readMessage(provider, new Uint8Array(event.data), true);\n if (encoding.length(encoder) > 1) {\n websocket.send(encoding.toUint8Array(encoder));\n }\n });\n websocket.addEventListener(\"error\", (event) => {\n provider.emit(\"connection-error\", [event, provider]);\n });\n websocket.addEventListener(\"close\", (event) => {\n provider.emit(\"connection-close\", [event, provider]);\n provider.ws = null;\n provider.wsconnecting = false;\n if (provider.wsconnected) {\n provider.wsconnected = false;\n provider.synced = false;\n // update awareness (all users except local left)\n const removedClients = Array.from(\n provider.awareness.getStates().keys()\n ).filter((client) => client !== provider.doc.clientID);\n awarenessProtocol.removeAwarenessStates(\n provider.awareness,\n removedClients,\n provider\n );\n // Clear stale meta for remote clients so their awareness\n // updates are accepted on reconnect (clock check starts fresh)\n for (const clientID of removedClients) {\n provider.awareness.meta.delete(clientID);\n }\n provider.emit(\"status\", [\n {\n status: \"disconnected\"\n }\n ]);\n } else {\n provider.wsUnsuccessfulReconnects++;\n }\n // Start with no reconnect timeout and increase timeout by\n // using exponential backoff starting with 100ms\n setTimeout(\n () => {\n if (provider.shouldConnect) {\n Promise.resolve(provider._reconnectWS()).catch((err) => {\n console.error(\"Reconnection failed\", err);\n });\n }\n },\n math.min(\n math.pow(2, provider.wsUnsuccessfulReconnects) * 100,\n provider.maxBackoffTime\n )\n );\n });\n websocket.addEventListener(\"open\", () => {\n provider.wsLastMessageReceived = time.getUnixTime();\n provider.wsconnecting = false;\n provider.wsconnected = true;\n provider.wsUnsuccessfulReconnects = 0;\n provider.emit(\"status\", [\n {\n status: \"connected\"\n }\n ]);\n // always send sync step 1 when connected\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, provider.doc);\n websocket.send(encoding.toUint8Array(encoder));\n // broadcast local awareness state\n if (provider.awareness.getLocalState() !== null) {\n // Re-set local state to bump the awareness clock, ensuring\n // remote clients accept the update even if they have stale meta\n provider.awareness.setLocalState(provider.awareness.getLocalState());\n const encoderAwarenessState = encoding.createEncoder();\n encoding.writeVarUint(encoderAwarenessState, messageAwareness);\n encoding.writeVarUint8Array(\n encoderAwarenessState,\n awarenessProtocol.encodeAwarenessUpdate(provider.awareness, [\n provider.doc.clientID\n ])\n );\n websocket.send(encoding.toUint8Array(encoderAwarenessState));\n }\n });\n provider.emit(\"status\", [\n {\n status: \"connecting\"\n }\n ]);\n }\n}\n\nfunction broadcastMessage(provider: WebsocketProvider, buf: Uint8Array) {\n const ws = provider.ws;\n if (provider.wsconnected && ws && ws.readyState === ws.OPEN) {\n ws.send(buf);\n }\n if (provider.bcconnected) {\n bc.publish(provider.bcChannel, buf, provider);\n }\n}\n\ntype AwarenessUpdate = {\n added: number[];\n updated: number[];\n removed: number[];\n};\n\nconst DefaultWebSocket = typeof WebSocket === \"undefined\" ? null : WebSocket;\n\n/**\n * Websocket Provider for Yjs. Creates a websocket connection to sync the shared document.\n * The document name is attached to the provided url. I.e. the following example\n * creates a websocket connection to http://localhost:1234/my-document-name\n *\n * @example\n * import * as Y from 'yjs'\n * import { WebsocketProvider } from 'y-websocket'\n * const doc = new Y.Doc()\n * const provider = new WebsocketProvider('http://localhost:1234', 'my-document-name', doc)\n *\n * @extends {Observable<string>}\n */\nexport class WebsocketProvider extends Observable<string> {\n maxBackoffTime: number;\n bcChannel: string;\n url: string;\n roomname: string;\n doc: YDoc;\n _WS: typeof WebSocket;\n awareness: awarenessProtocol.Awareness;\n wsconnected: boolean;\n wsconnecting: boolean;\n bcconnected: boolean;\n disableBc: boolean;\n wsUnsuccessfulReconnects: number;\n messageHandlers: typeof messageHandlers;\n _synced: boolean;\n ws: WebSocket | null;\n wsLastMessageReceived: number;\n shouldConnect: boolean; // Whether to connect to other peers or not\n _resyncInterval: ReturnType<typeof setInterval> | number;\n _bcSubscriber: (message: Uint8Array, origin: unknown) => void;\n _updateHandler: (update: Uint8Array, origin: unknown) => void;\n _awarenessUpdateHandler: (update: AwarenessUpdate, origin: unknown) => void;\n _unloadHandler: () => void;\n\n constructor(\n serverUrl: string,\n roomname: string,\n doc: YDoc,\n {\n connect = true,\n awareness = new awarenessProtocol.Awareness(doc),\n params = {},\n isPrefixedUrl = false,\n WebSocketPolyfill = DefaultWebSocket, // Optionally provide a WebSocket polyfill\n resyncInterval = -1, // Request server state every `resyncInterval` milliseconds\n maxBackoffTime = 2500, // Maximum amount of time to wait before trying to reconnect (we try to reconnect using exponential backoff)\n disableBc = DEFAULT_DISABLE_BC // Disable cross-tab BroadcastChannel communication\n }: {\n connect?: boolean;\n awareness?: awarenessProtocol.Awareness;\n params?: { [s: string]: string };\n isPrefixedUrl?: boolean;\n WebSocketPolyfill?: typeof WebSocket | null;\n resyncInterval?: number;\n maxBackoffTime?: number;\n disableBc?: boolean;\n } = {}\n ) {\n super();\n // ensure that url is always ends with /\n while (serverUrl[serverUrl.length - 1] === \"/\") {\n serverUrl = serverUrl.slice(0, serverUrl.length - 1);\n }\n const encodedParams = url.encodeQueryParams(params);\n this.maxBackoffTime = maxBackoffTime;\n this.bcChannel = `${serverUrl}/${roomname}`;\n this.url = isPrefixedUrl\n ? serverUrl\n : `${serverUrl}/${roomname}${encodedParams.length === 0 ? \"\" : `?${encodedParams}`}`;\n this.roomname = roomname;\n this.doc = doc;\n this._WS = WebSocketPolyfill!;\n this.awareness = awareness;\n this.wsconnected = false;\n this.wsconnecting = false;\n this.bcconnected = false;\n this.disableBc = disableBc;\n this.wsUnsuccessfulReconnects = 0;\n this.messageHandlers = messageHandlers.slice();\n\n this._synced = false;\n\n this.ws = null;\n this.wsLastMessageReceived = 0;\n\n this.shouldConnect = connect;\n\n this._resyncInterval = 0;\n if (resyncInterval > 0) {\n this._resyncInterval = /** @type {any} */ setInterval(() => {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n // resend sync step 1\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, doc);\n this.ws.send(encoding.toUint8Array(encoder));\n }\n }, resyncInterval);\n }\n\n this._bcSubscriber = (data: Uint8Array, origin: unknown) => {\n if (origin !== this) {\n const encoder = readMessage(this, new Uint8Array(data), false);\n if (encoding.length(encoder) > 1) {\n bc.publish(this.bcChannel, encoding.toUint8Array(encoder), this);\n }\n }\n };\n /**\n * Listens to Yjs updates and sends them to remote peers (ws and broadcastchannel)\n */\n this._updateHandler = (update: Uint8Array, origin: unknown) => {\n if (origin !== this) {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeUpdate(encoder, update);\n broadcastMessage(this, encoding.toUint8Array(encoder));\n }\n };\n this.doc.on(\"update\", this._updateHandler);\n\n this._awarenessUpdateHandler = (\n { added, updated, removed }: AwarenessUpdate,\n _origin: unknown\n ) => {\n const changedClients = added.concat(updated).concat(removed);\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(awareness, changedClients)\n );\n broadcastMessage(this, encoding.toUint8Array(encoder));\n };\n this._unloadHandler = () => {\n awarenessProtocol.removeAwarenessStates(\n this.awareness,\n [doc.clientID],\n \"window unload\"\n );\n };\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"unload\", this._unloadHandler);\n } else if (\n typeof process !== \"undefined\" &&\n typeof process.on === \"function\"\n ) {\n process.on(\"exit\", this._unloadHandler);\n }\n // Listen on 'change' (not 'update') so that clock-only awareness\n // renewals (the 15-second heartbeat) do NOT produce network traffic.\n // Only actual state changes (cursor moved, name changed, etc.) are sent.\n // This allows Durable Objects to hibernate when sessions are idle.\n awareness.on(\"change\", this._awarenessUpdateHandler);\n\n // Disable the awareness protocol's built-in check interval.\n // It renews the local clock every 15s (causing wire traffic that defeats\n // DO hibernation) and removes remote peers after 30s of inactivity.\n // We handle peer cleanup via WebSocket close events instead.\n clearInterval(\n (\n awareness as unknown as {\n _checkInterval: ReturnType<typeof setInterval>;\n }\n )._checkInterval\n );\n if (connect) {\n this.connect();\n }\n }\n\n /**\n * @type {boolean}\n */\n get synced() {\n return this._synced;\n }\n\n set synced(state) {\n if (this._synced !== state) {\n this._synced = state;\n this.emit(\"synced\", [state]);\n this.emit(\"sync\", [state]);\n }\n }\n\n destroy() {\n if (this._resyncInterval !== 0) {\n clearInterval(this._resyncInterval);\n }\n this.disconnect();\n if (typeof window !== \"undefined\") {\n window.removeEventListener(\"unload\", this._unloadHandler);\n } else if (\n typeof process !== \"undefined\" &&\n typeof process.off === \"function\"\n ) {\n process.off(\"exit\", this._unloadHandler);\n }\n this.awareness.off(\"change\", this._awarenessUpdateHandler);\n this.doc.off(\"update\", this._updateHandler);\n super.destroy();\n }\n\n connectBc() {\n if (this.disableBc) {\n return;\n }\n if (!this.bcconnected) {\n bc.subscribe(this.bcChannel, this._bcSubscriber);\n this.bcconnected = true;\n }\n // send sync step1 to bc\n // write sync step 1\n const encoderSync = encoding.createEncoder();\n encoding.writeVarUint(encoderSync, messageSync);\n syncProtocol.writeSyncStep1(encoderSync, this.doc);\n bc.publish(this.bcChannel, encoding.toUint8Array(encoderSync), this);\n // broadcast local state\n const encoderState = encoding.createEncoder();\n encoding.writeVarUint(encoderState, messageSync);\n syncProtocol.writeSyncStep2(encoderState, this.doc);\n bc.publish(this.bcChannel, encoding.toUint8Array(encoderState), this);\n // write queryAwareness\n const encoderAwarenessQuery = encoding.createEncoder();\n encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);\n bc.publish(\n this.bcChannel,\n encoding.toUint8Array(encoderAwarenessQuery),\n this\n );\n // broadcast local awareness state\n const encoderAwarenessState = encoding.createEncoder();\n encoding.writeVarUint(encoderAwarenessState, messageAwareness);\n encoding.writeVarUint8Array(\n encoderAwarenessState,\n awarenessProtocol.encodeAwarenessUpdate(this.awareness, [\n this.doc.clientID\n ])\n );\n bc.publish(\n this.bcChannel,\n encoding.toUint8Array(encoderAwarenessState),\n this\n );\n }\n\n disconnectBc() {\n // broadcast message with local awareness state set to null (indicating disconnect)\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.awareness,\n [this.doc.clientID],\n new Map()\n )\n );\n broadcastMessage(this, encoding.toUint8Array(encoder));\n if (this.bcconnected) {\n bc.unsubscribe(this.bcChannel, this._bcSubscriber);\n this.bcconnected = false;\n }\n }\n\n disconnect() {\n this.shouldConnect = false;\n this.disconnectBc();\n if (this.ws !== null) {\n this.ws.close();\n }\n }\n\n /**\n * Called by the close handler to re-establish the WebSocket.\n * Subclasses (e.g. YProvider) override this to refresh dynamic\n * params before reconnecting.\n */\n _reconnectWS() {\n setupWS(this);\n }\n\n connect() {\n this.shouldConnect = true;\n if (!this.wsconnected && this.ws === null) {\n setupWS(this);\n this.connectBc();\n }\n }\n}\n\nfunction assertType(value: unknown, label: string, type: string) {\n if (typeof value !== type) {\n throw new Error(\n `Invalid \"${label}\" parameter provided to YProvider. Expected: ${type}, received: ${value as string}`\n );\n }\n}\n\ntype Params = Record<string, string | null | undefined>;\ntype ParamsProvider = Params | (() => Params | Promise<Params>);\ntype BaseProviderOptions = ConstructorParameters<typeof WebsocketProvider>[3];\n\ntype YProviderOptions = Omit<NonNullable<BaseProviderOptions>, \"params\"> & {\n connectionId?: string;\n party?: string;\n prefix?: string;\n params?: ParamsProvider;\n protocol?: \"ws\" | \"wss\";\n};\n\nexport default class YProvider extends WebsocketProvider {\n id: string;\n #params?: ParamsProvider;\n\n constructor(\n host: string,\n room: string,\n doc?: YDoc,\n options: YProviderOptions = {}\n ) {\n assertType(host, \"host\", \"string\");\n assertType(room, \"room\", \"string\");\n\n // strip the protocol from the beginning of `host` if any\n host = host.replace(/^(http|https|ws|wss):\\/\\//, \"\");\n\n // strip trailing slash from host if any\n if (host.endsWith(\"/\")) {\n host = host.slice(0, -1);\n }\n\n const serverUrl = `${\n options.protocol ||\n (host.startsWith(\"localhost:\") ||\n host.startsWith(\"127.0.0.1:\") ||\n host.startsWith(\"192.168.\") ||\n host.startsWith(\"10.\") ||\n (host.startsWith(\"172.\") &&\n host.split(\".\")[1] >= \"16\" &&\n host.split(\".\")[1] <= \"31\")\n ? \"ws\"\n : \"wss\")\n }://${host}${options.prefix || `/parties/${options.party || \"main\"}`}`;\n\n // use provided id, or generate a random one\n const id = options.connectionId ?? nanoid(10);\n\n // don't pass params to WebsocketProvider, we override them in connect()\n const { params, connect = true, ...rest } = options;\n\n // don't connect until we've updated the url parameters\n const baseOptions = {\n ...rest,\n isPrefixedUrl: !!options.prefix,\n connect: false\n };\n\n super(serverUrl, room, doc ?? new YDoc(), baseOptions);\n\n this.id = id;\n this.#params = params;\n\n if (connect) {\n void this.connect();\n }\n }\n\n async #resolveParams() {\n const nextParams =\n typeof this.#params === \"function\" ? await this.#params() : this.#params;\n const urlParams = new URLSearchParams([[\"_pk\", this.id]]);\n if (nextParams) {\n for (const [key, value] of Object.entries(nextParams)) {\n if (value !== null && value !== undefined) {\n urlParams.append(key, value);\n }\n }\n }\n const nextUrl = new URL(this.url);\n nextUrl.search = urlParams.toString();\n this.url = nextUrl.toString();\n }\n\n async connect() {\n try {\n await this.#resolveParams();\n super.connect();\n } catch (err) {\n console.error(\"Failed to open connecton to PartyServer\", err);\n throw err;\n }\n }\n\n async _reconnectWS() {\n try {\n await this.#resolveParams();\n } catch (err) {\n console.error(\n \"Failed to refresh params, reconnecting with stale params\",\n err\n );\n }\n super._reconnectWS();\n }\n\n sendMessage(message: string) {\n this.ws?.send(`__YPS:${message}`);\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,6 @@
1
- const require_chunk = require("../chunk-C0xms8kb.cjs");
1
+ require("../chunk-CKQMccvm.cjs");
2
2
  const require_provider_index = require("./index.cjs");
3
3
  let react = require("react");
4
-
5
4
  //#region src/provider/react.tsx
6
5
  function useYProvider(yProviderOptions) {
7
6
  const { host, room, party, doc, options, prefix } = yProviderOptions;
@@ -28,7 +27,7 @@ function useYProvider(yProviderOptions) {
28
27
  }, [provider]);
29
28
  return provider;
30
29
  }
31
-
32
30
  //#endregion
33
31
  module.exports = useYProvider;
32
+
34
33
  //# sourceMappingURL=react.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"react.cjs","names":["YProvider"],"sources":["../../src/provider/react.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nimport YProvider from \"./index\";\n\nimport type * as Y from \"yjs\";\n\ntype UseYProviderOptions = {\n host?: string | undefined;\n room: string;\n party?: string;\n doc?: Y.Doc;\n prefix?: string;\n options?: ConstructorParameters<typeof YProvider>[3];\n};\n\nexport default function useYProvider(yProviderOptions: UseYProviderOptions) {\n const { host, room, party, doc, options, prefix } = yProviderOptions;\n const [provider] = useState<YProvider>(\n () =>\n new YProvider(\n host ||\n (typeof window !== \"undefined\"\n ? window.location.host\n : \"dummy-domain.com\"),\n room,\n doc,\n {\n connect: false,\n party,\n prefix,\n ...options\n }\n )\n );\n\n useEffect(() => {\n void provider.connect();\n return () => provider.disconnect();\n }, [provider]);\n return provider;\n}\n"],"mappings":";;;;;AAeA,SAAwB,aAAa,kBAAuC;CAC1E,MAAM,EAAE,MAAM,MAAM,OAAO,KAAK,SAAS,WAAW;CACpD,MAAM,CAAC,sCAEH,IAAIA,+BACF,SACG,OAAO,WAAW,cACf,OAAO,SAAS,OAChB,qBACN,MACA,KACA;EACE,SAAS;EACT;EACA;EACA,GAAG;EACJ,CACF,CACJ;AAED,4BAAgB;AACd,EAAK,SAAS,SAAS;AACvB,eAAa,SAAS,YAAY;IACjC,CAAC,SAAS,CAAC;AACd,QAAO"}
1
+ {"version":3,"file":"react.cjs","names":["YProvider"],"sources":["../../src/provider/react.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nimport YProvider from \"./index\";\n\nimport type * as Y from \"yjs\";\n\ntype UseYProviderOptions = {\n host?: string | undefined;\n room: string;\n party?: string;\n doc?: Y.Doc;\n prefix?: string;\n options?: ConstructorParameters<typeof YProvider>[3];\n};\n\nexport default function useYProvider(yProviderOptions: UseYProviderOptions) {\n const { host, room, party, doc, options, prefix } = yProviderOptions;\n const [provider] = useState<YProvider>(\n () =>\n new YProvider(\n host ||\n (typeof window !== \"undefined\"\n ? window.location.host\n : \"dummy-domain.com\"),\n room,\n doc,\n {\n connect: false,\n party,\n prefix,\n ...options\n }\n )\n );\n\n useEffect(() => {\n void provider.connect();\n return () => provider.disconnect();\n }, [provider]);\n return provider;\n}\n"],"mappings":";;;;AAeA,SAAwB,aAAa,kBAAuC;CAC1E,MAAM,EAAE,MAAM,MAAM,OAAO,KAAK,SAAS,WAAW;CACpD,MAAM,CAAC,aAAA,GAAA,MAAA,gBAEH,IAAIA,uBAAAA,QACF,SACG,OAAO,WAAW,cACf,OAAO,SAAS,OAChB,qBACN,MACA,KACA;EACE,SAAS;EACT;EACA;EACA,GAAG;EACJ,CACF,CACJ;AAED,EAAA,GAAA,MAAA,iBAAgB;AACT,WAAS,SAAS;AACvB,eAAa,SAAS,YAAY;IACjC,CAAC,SAAS,CAAC;AACd,QAAO"}
@@ -1,6 +1,5 @@
1
1
  import YProvider from "./index.js";
2
2
  import { useEffect, useState } from "react";
3
-
4
3
  //#region src/provider/react.tsx
5
4
  function useYProvider(yProviderOptions) {
6
5
  const { host, room, party, doc, options, prefix } = yProviderOptions;
@@ -27,7 +26,7 @@ function useYProvider(yProviderOptions) {
27
26
  }, [provider]);
28
27
  return provider;
29
28
  }
30
-
31
29
  //#endregion
32
30
  export { useYProvider as default };
31
+
33
32
  //# sourceMappingURL=react.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","names":[],"sources":["../../src/provider/react.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nimport YProvider from \"./index\";\n\nimport type * as Y from \"yjs\";\n\ntype UseYProviderOptions = {\n host?: string | undefined;\n room: string;\n party?: string;\n doc?: Y.Doc;\n prefix?: string;\n options?: ConstructorParameters<typeof YProvider>[3];\n};\n\nexport default function useYProvider(yProviderOptions: UseYProviderOptions) {\n const { host, room, party, doc, options, prefix } = yProviderOptions;\n const [provider] = useState<YProvider>(\n () =>\n new YProvider(\n host ||\n (typeof window !== \"undefined\"\n ? window.location.host\n : \"dummy-domain.com\"),\n room,\n doc,\n {\n connect: false,\n party,\n prefix,\n ...options\n }\n )\n );\n\n useEffect(() => {\n void provider.connect();\n return () => provider.disconnect();\n }, [provider]);\n return provider;\n}\n"],"mappings":";;;;AAeA,SAAwB,aAAa,kBAAuC;CAC1E,MAAM,EAAE,MAAM,MAAM,OAAO,KAAK,SAAS,WAAW;CACpD,MAAM,CAAC,YAAY,eAEf,IAAI,UACF,SACG,OAAO,WAAW,cACf,OAAO,SAAS,OAChB,qBACN,MACA,KACA;EACE,SAAS;EACT;EACA;EACA,GAAG;EACJ,CACF,CACJ;AAED,iBAAgB;AACd,EAAK,SAAS,SAAS;AACvB,eAAa,SAAS,YAAY;IACjC,CAAC,SAAS,CAAC;AACd,QAAO"}
1
+ {"version":3,"file":"react.js","names":[],"sources":["../../src/provider/react.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nimport YProvider from \"./index\";\n\nimport type * as Y from \"yjs\";\n\ntype UseYProviderOptions = {\n host?: string | undefined;\n room: string;\n party?: string;\n doc?: Y.Doc;\n prefix?: string;\n options?: ConstructorParameters<typeof YProvider>[3];\n};\n\nexport default function useYProvider(yProviderOptions: UseYProviderOptions) {\n const { host, room, party, doc, options, prefix } = yProviderOptions;\n const [provider] = useState<YProvider>(\n () =>\n new YProvider(\n host ||\n (typeof window !== \"undefined\"\n ? window.location.host\n : \"dummy-domain.com\"),\n room,\n doc,\n {\n connect: false,\n party,\n prefix,\n ...options\n }\n )\n );\n\n useEffect(() => {\n void provider.connect();\n return () => provider.disconnect();\n }, [provider]);\n return provider;\n}\n"],"mappings":";;;AAeA,SAAwB,aAAa,kBAAuC;CAC1E,MAAM,EAAE,MAAM,MAAM,OAAO,KAAK,SAAS,WAAW;CACpD,MAAM,CAAC,YAAY,eAEf,IAAI,UACF,SACG,OAAO,WAAW,cACf,OAAO,SAAS,OAChB,qBACN,MACA,KACA;EACE,SAAS;EACT;EACA;EACA,GAAG;EACJ,CACF,CACJ;AAED,iBAAgB;AACT,WAAS,SAAS;AACvB,eAAa,SAAS,YAAY;IACjC,CAAC,SAAS,CAAC;AACd,QAAO"}
@@ -1,18 +1,17 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_chunk = require("../chunk-C0xms8kb.cjs");
2
+ const require_chunk = require("../chunk-CKQMccvm.cjs");
3
3
  let lib0_decoding = require("lib0/decoding");
4
- lib0_decoding = require_chunk.__toESM(lib0_decoding);
4
+ lib0_decoding = require_chunk.__toESM(lib0_decoding, 1);
5
5
  let lib0_encoding = require("lib0/encoding");
6
- lib0_encoding = require_chunk.__toESM(lib0_encoding);
6
+ lib0_encoding = require_chunk.__toESM(lib0_encoding, 1);
7
7
  let lodash_debounce = require("lodash.debounce");
8
- lodash_debounce = require_chunk.__toESM(lodash_debounce);
8
+ lodash_debounce = require_chunk.__toESM(lodash_debounce, 1);
9
9
  let partyserver = require("partyserver");
10
10
  let y_protocols_awareness = require("y-protocols/awareness");
11
- y_protocols_awareness = require_chunk.__toESM(y_protocols_awareness);
11
+ y_protocols_awareness = require_chunk.__toESM(y_protocols_awareness, 1);
12
12
  let y_protocols_sync = require("y-protocols/sync");
13
- y_protocols_sync = require_chunk.__toESM(y_protocols_sync);
13
+ y_protocols_sync = require_chunk.__toESM(y_protocols_sync, 1);
14
14
  let yjs = require("yjs");
15
-
16
15
  //#region src/server/index.ts
17
16
  const snapshotOrigin = Symbol("snapshot-origin");
18
17
  const wsReadyStateConnecting = 0;
@@ -359,8 +358,8 @@ function withYjs(Base) {
359
358
  return YjsMixin;
360
359
  }
361
360
  const YServer = withYjs(partyserver.Server);
362
-
363
361
  //#endregion
364
362
  exports.YServer = YServer;
365
363
  exports.withYjs = withYjs;
364
+
366
365
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["YDoc","awarenessProtocol","decoding","syncProtocol","UndoManager","XmlText","XmlElement","XmlFragment","encoding","Server"],"sources":["../../src/server/index.ts"],"sourcesContent":["import * as decoding from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport debounce from \"lodash.debounce\";\nimport type { Connection, ConnectionContext, WSMessage } from \"partyserver\";\nimport { Server } from \"partyserver\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport {\n applyUpdate,\n Doc as YDoc,\n encodeStateAsUpdate,\n encodeStateVector,\n UndoManager,\n XmlText,\n XmlElement,\n XmlFragment\n} from \"yjs\";\n\nconst snapshotOrigin = Symbol(\"snapshot-origin\");\ntype YjsRootType =\n | \"Text\"\n | \"Map\"\n | \"Array\"\n | \"XmlText\"\n | \"XmlElement\"\n | \"XmlFragment\";\n\nconst wsReadyStateConnecting = 0;\nconst wsReadyStateOpen = 1;\n// oxlint-disable-next-line no-unused-vars\nconst wsReadyStateClosing = 2;\n// oxlint-disable-next-line no-unused-vars\nconst wsReadyStateClosed = 3;\n\nconst messageSync = 0;\nconst messageAwareness = 1;\n// oxlint-disable-next-line no-unused-vars\nconst messageAuth = 2;\n\n/**\n * Internal key used in connection.setState() to track which awareness\n * client IDs are controlled by each connection. This survives hibernation\n * because connection state is persisted to WebSocket attachments.\n */\nconst AWARENESS_IDS_KEY = \"__ypsAwarenessIds\";\n\ntype YServerConnectionState = {\n [AWARENESS_IDS_KEY]?: number[];\n [key: string]: unknown;\n};\n\nfunction getAwarenessIds(conn: Connection): number[] {\n try {\n const state = conn.state as YServerConnectionState | null;\n return state?.[AWARENESS_IDS_KEY] ?? [];\n } catch {\n return [];\n }\n}\n\nfunction setAwarenessIds(conn: Connection, ids: number[]): void {\n try {\n conn.setState((prev: YServerConnectionState | null) => ({\n ...prev,\n [AWARENESS_IDS_KEY]: ids\n }));\n } catch {\n // ignore — may fail if connection is already closed\n }\n}\n\nclass WSSharedDoc extends YDoc {\n awareness: awarenessProtocol.Awareness;\n\n constructor() {\n super({ gc: true });\n this.awareness = new awarenessProtocol.Awareness(this);\n this.awareness.setLocalState(null);\n\n // Disable the awareness protocol's built-in check interval.\n // It renews the local clock every 15s and removes peers after 30s,\n // but we handle peer cleanup via onClose instead. Clearing it here\n // prevents it from defeating Durable Object hibernation.\n clearInterval(\n (\n this.awareness as unknown as {\n _checkInterval: ReturnType<typeof setInterval>;\n }\n )._checkInterval\n );\n }\n}\n\nconst CALLBACK_DEFAULTS = {\n debounceWait: 2000,\n debounceMaxWait: 10000,\n timeout: 5000\n};\n\nfunction readSyncMessage(\n decoder: decoding.Decoder,\n encoder: encoding.Encoder,\n doc: YDoc,\n transactionOrigin: Connection,\n readOnly = false\n) {\n const messageType = decoding.readVarUint(decoder);\n switch (messageType) {\n case syncProtocol.messageYjsSyncStep1:\n syncProtocol.readSyncStep1(decoder, encoder, doc);\n break;\n case syncProtocol.messageYjsSyncStep2:\n if (!readOnly)\n syncProtocol.readSyncStep2(decoder, doc, transactionOrigin);\n break;\n case syncProtocol.messageYjsUpdate:\n if (!readOnly) syncProtocol.readUpdate(decoder, doc, transactionOrigin);\n break;\n default:\n throw new Error(\"Unknown message type\");\n }\n return messageType;\n}\n\nfunction send(conn: Connection, m: Uint8Array): void {\n if (\n conn.readyState !== undefined &&\n conn.readyState !== wsReadyStateConnecting &&\n conn.readyState !== wsReadyStateOpen\n ) {\n return;\n }\n try {\n conn.send(m);\n } catch {\n // connection is broken, ignore\n }\n}\n\nexport interface CallbackOptions {\n debounceWait?: number;\n debounceMaxWait?: number;\n timeout?: number;\n}\n\ntype ServerClass = new (...args: any[]) => Server;\n\nexport interface YjsInstance {\n readonly document: WSSharedDoc;\n onLoad(): Promise<YDoc | void>;\n onSave(): Promise<void>;\n unstable_replaceDocument(\n snapshotUpdate: Uint8Array,\n getMetadata?: (key: string) => YjsRootType\n ): void;\n isReadOnly(connection: Connection): boolean;\n onCustomMessage(connection: Connection, message: string): void;\n sendCustomMessage(connection: Connection, message: string): void;\n broadcastCustomMessage(message: string, excludeConnection?: Connection): void;\n handleMessage(connection: Connection, message: WSMessage): void;\n}\n\nexport interface YjsStatic {\n callbackOptions: CallbackOptions;\n}\n\nexport function withYjs<TBase extends ServerClass>(\n Base: TBase\n): TBase & YjsStatic & (new (...args: any[]) => YjsInstance) {\n class YjsMixin extends Base {\n static callbackOptions: CallbackOptions = {};\n\n readonly document: WSSharedDoc = new WSSharedDoc();\n\n async onLoad(): Promise<YDoc | void> {\n // to be implemented by the user\n return;\n }\n\n async onSave(): Promise<void> {\n // to be implemented by the user\n }\n\n /**\n * Replaces the document with a different state using Yjs UndoManager key remapping.\n *\n * @param snapshotUpdate - The snapshot update to replace the document with.\n * @param getMetadata (optional) - A function that returns the type of the root for a given key.\n */\n unstable_replaceDocument(\n snapshotUpdate: Uint8Array,\n getMetadata: (key: string) => YjsRootType = () => \"Map\"\n ): void {\n try {\n const doc = this.document;\n const snapshotDoc = new YDoc();\n applyUpdate(snapshotDoc, snapshotUpdate, snapshotOrigin);\n\n const currentStateVector = encodeStateVector(doc);\n const snapshotStateVector = encodeStateVector(snapshotDoc);\n\n const changesSinceSnapshotUpdate = encodeStateAsUpdate(\n doc,\n snapshotStateVector\n );\n\n const undoManager = new UndoManager(\n [...snapshotDoc.share.keys()].map((key) => {\n const type = getMetadata(key);\n if (type === \"Text\") {\n return snapshotDoc.getText(key);\n } else if (type === \"Map\") {\n return snapshotDoc.getMap(key);\n } else if (type === \"Array\") {\n return snapshotDoc.getArray(key);\n } else if (type === \"XmlText\") {\n return snapshotDoc.get(key, XmlText);\n } else if (type === \"XmlElement\") {\n return snapshotDoc.get(key, XmlElement);\n } else if (type === \"XmlFragment\") {\n return snapshotDoc.get(key, XmlFragment);\n }\n throw new Error(`Unknown root type: ${type} for key: ${key}`);\n }),\n {\n trackedOrigins: new Set([snapshotOrigin])\n }\n );\n\n applyUpdate(snapshotDoc, changesSinceSnapshotUpdate, snapshotOrigin);\n undoManager.undo();\n\n const documentChangesSinceSnapshotUpdate = encodeStateAsUpdate(\n snapshotDoc,\n currentStateVector\n );\n\n applyUpdate(this.document, documentChangesSinceSnapshotUpdate);\n } catch (error) {\n throw new Error(\n `Failed to replace document: ${error instanceof Error ? error.message : \"Unknown error\"}`\n );\n }\n }\n\n async onStart(): Promise<void> {\n const src = await this.onLoad();\n if (src != null) {\n const state = encodeStateAsUpdate(src);\n applyUpdate(this.document, state);\n }\n\n // Broadcast doc updates to all connections.\n // Uses this.getConnections() which works for both hibernate and non-hibernate\n // modes and survives DO hibernation (unlike an in-memory Map).\n this.document.on(\"update\", (update: Uint8Array) => {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeUpdate(encoder, update);\n const message = encoding.toUint8Array(encoder);\n for (const conn of this.getConnections()) {\n send(conn, message);\n }\n });\n\n // Track which awareness clientIDs each connection controls.\n // Stored in connection.setState() so it survives hibernation.\n // When conn is null (internal changes like removeAwarenessStates on close),\n // broadcast the update to remaining connections.\n // When conn is non-null (client message), handleMessage broadcasts directly.\n this.document.awareness.on(\n \"update\",\n (\n {\n added,\n updated,\n removed\n }: {\n added: Array<number>;\n updated: Array<number>;\n removed: Array<number>;\n },\n conn: Connection | null\n ) => {\n if (conn !== null) {\n // Track which clientIDs this connection controls\n try {\n const currentIds = new Set(getAwarenessIds(conn));\n for (const clientID of added) currentIds.add(clientID);\n for (const clientID of removed) currentIds.delete(clientID);\n setAwarenessIds(conn, [...currentIds]);\n } catch (_e) {\n // ignore — best-effort tracking\n }\n } else {\n // Internal awareness change (e.g. removeAwarenessStates on close)\n // — broadcast to all remaining connections\n const changedClients = added.concat(updated, removed);\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.document.awareness,\n changedClients\n )\n );\n const buff = encoding.toUint8Array(encoder);\n for (const c of this.getConnections()) {\n send(c, buff);\n }\n }\n }\n );\n\n // Debounced persistence handler\n const ctor = this.constructor as typeof YjsMixin;\n this.document.on(\n \"update\",\n debounce(\n (_update: Uint8Array, _origin: Connection, _doc: YDoc) => {\n try {\n this.onSave().catch((err) => {\n console.error(\"failed to persist:\", err);\n });\n } catch (err) {\n console.error(\"failed to persist:\", err);\n }\n },\n ctor.callbackOptions.debounceWait || CALLBACK_DEFAULTS.debounceWait,\n {\n maxWait:\n ctor.callbackOptions.debounceMaxWait ||\n CALLBACK_DEFAULTS.debounceMaxWait\n }\n )\n );\n\n // After hibernation wake-up, the doc is empty but existing connections\n // survive. Re-sync by sending sync step 1 to all connections — they'll\n // respond with sync step 2 containing their full state.\n // On first start there are no connections, so this is a no-op.\n const syncEncoder = encoding.createEncoder();\n encoding.writeVarUint(syncEncoder, messageSync);\n syncProtocol.writeSyncStep1(syncEncoder, this.document);\n const syncMessage = encoding.toUint8Array(syncEncoder);\n for (const conn of this.getConnections()) {\n send(conn, syncMessage);\n }\n }\n\n // oxlint-disable-next-line no-unused-vars\n isReadOnly(connection: Connection): boolean {\n // to be implemented by the user\n return false;\n }\n\n /**\n * Handle custom string messages from the client.\n * Override this method to implement custom message handling.\n * @param connection - The connection that sent the message\n * @param message - The custom message string (without the __YPS: prefix)\n */\n // oxlint-disable-next-line no-unused-vars\n onCustomMessage(connection: Connection, message: string): void {\n // to be implemented by the user\n console.warn(\n `Received custom message but onCustomMessage is not implemented in ${this.constructor.name}:`,\n message\n );\n }\n\n /**\n * Send a custom string message to a specific connection.\n * @param connection - The connection to send the message to\n * @param message - The custom message string to send\n */\n sendCustomMessage(connection: Connection, message: string): void {\n if (\n connection.readyState !== undefined &&\n connection.readyState !== wsReadyStateConnecting &&\n connection.readyState !== wsReadyStateOpen\n ) {\n return;\n }\n try {\n connection.send(`__YPS:${message}`);\n } catch (e) {\n console.warn(\"Failed to send custom message\", e);\n }\n }\n\n /**\n * Broadcast a custom string message to all connected clients.\n * @param message - The custom message string to broadcast\n * @param excludeConnection - Optional connection to exclude from the broadcast\n */\n broadcastCustomMessage(\n message: string,\n excludeConnection?: Connection\n ): void {\n const formattedMessage = `__YPS:${message}`;\n for (const conn of this.getConnections()) {\n if (excludeConnection && conn === excludeConnection) {\n continue;\n }\n if (\n conn.readyState !== undefined &&\n conn.readyState !== wsReadyStateConnecting &&\n conn.readyState !== wsReadyStateOpen\n ) {\n continue;\n }\n try {\n conn.send(formattedMessage);\n } catch (e) {\n console.warn(\"Failed to broadcast custom message\", e);\n }\n }\n }\n\n handleMessage(connection: Connection, message: WSMessage) {\n if (typeof message === \"string\") {\n // Handle custom messages with __YPS: prefix\n if (message.startsWith(\"__YPS:\")) {\n const customMessage = message.slice(6); // Remove __YPS: prefix\n this.onCustomMessage(connection, customMessage);\n return;\n }\n console.warn(\n `Received non-prefixed string message. Custom messages should be sent using sendMessage() on the provider.`\n );\n return;\n }\n try {\n const encoder = encoding.createEncoder();\n // Convert ArrayBuffer to Uint8Array if needed (ArrayBufferView like Uint8Array can be used directly)\n const uint8Array =\n message instanceof Uint8Array\n ? message\n : message instanceof ArrayBuffer\n ? new Uint8Array(message)\n : new Uint8Array(\n message.buffer,\n message.byteOffset,\n message.byteLength\n );\n const decoder = decoding.createDecoder(uint8Array);\n const messageType = decoding.readVarUint(decoder);\n switch (messageType) {\n case messageSync:\n encoding.writeVarUint(encoder, messageSync);\n readSyncMessage(\n decoder,\n encoder,\n this.document,\n connection,\n this.isReadOnly(connection)\n );\n\n // If the `encoder` only contains the type of reply message and no\n // message, there is no need to send the message. When `encoder` only\n // contains the type of reply, its length is 1.\n if (encoding.length(encoder) > 1) {\n send(connection, encoding.toUint8Array(encoder));\n }\n break;\n case messageAwareness: {\n const awarenessData = decoding.readVarUint8Array(decoder);\n awarenessProtocol.applyAwarenessUpdate(\n this.document.awareness,\n awarenessData,\n connection\n );\n // Forward raw awareness bytes to all connections\n const awarenessEncoder = encoding.createEncoder();\n encoding.writeVarUint(awarenessEncoder, messageAwareness);\n encoding.writeVarUint8Array(awarenessEncoder, awarenessData);\n const awarenessBuff = encoding.toUint8Array(awarenessEncoder);\n for (const c of this.getConnections()) {\n send(c, awarenessBuff);\n }\n break;\n }\n }\n } catch (err) {\n console.error(err);\n // @ts-expect-error - TODO: fix this\n this.document.emit(\"error\", [err]);\n }\n }\n\n onMessage(conn: Connection, message: WSMessage) {\n this.handleMessage(conn, message);\n }\n\n onClose(\n connection: Connection<unknown>,\n _code: number,\n _reason: string,\n _wasClean: boolean\n ): void | Promise<void> {\n // Read controlled awareness clientIDs from connection state\n // (survives hibernation unlike an in-memory Map)\n const controlledIds = getAwarenessIds(connection);\n if (controlledIds.length > 0) {\n awarenessProtocol.removeAwarenessStates(\n this.document.awareness,\n controlledIds,\n null\n );\n }\n }\n\n // TODO: explore why onError gets triggered when a connection closes\n\n onConnect(\n conn: Connection<unknown>,\n _ctx: ConnectionContext\n ): void | Promise<void> {\n // Note: awareness IDs are lazily initialized when the first awareness\n // message is received — no need to call setAwarenessIds(conn, []) here\n\n // send sync step 1\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, this.document);\n send(conn, encoding.toUint8Array(encoder));\n const awarenessStates = this.document.awareness.getStates();\n if (awarenessStates.size > 0) {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.document.awareness,\n Array.from(awarenessStates.keys())\n )\n );\n send(conn, encoding.toUint8Array(encoder));\n }\n }\n }\n\n return YjsMixin as unknown as TBase &\n YjsStatic &\n (new (...args: any[]) => YjsInstance);\n}\n\nexport const YServer = withYjs(Server);\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["YDoc","awarenessProtocol","decoding","syncProtocol","UndoManager","XmlText","XmlElement","XmlFragment","encoding","Server"],"sources":["../../src/server/index.ts"],"sourcesContent":["import * as decoding from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport debounce from \"lodash.debounce\";\nimport type { Connection, ConnectionContext, WSMessage } from \"partyserver\";\nimport { Server } from \"partyserver\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport {\n applyUpdate,\n Doc as YDoc,\n encodeStateAsUpdate,\n encodeStateVector,\n UndoManager,\n XmlText,\n XmlElement,\n XmlFragment\n} from \"yjs\";\n\nconst snapshotOrigin = Symbol(\"snapshot-origin\");\ntype YjsRootType =\n | \"Text\"\n | \"Map\"\n | \"Array\"\n | \"XmlText\"\n | \"XmlElement\"\n | \"XmlFragment\";\n\nconst wsReadyStateConnecting = 0;\nconst wsReadyStateOpen = 1;\n// oxlint-disable-next-line no-unused-vars\nconst wsReadyStateClosing = 2;\n// oxlint-disable-next-line no-unused-vars\nconst wsReadyStateClosed = 3;\n\nconst messageSync = 0;\nconst messageAwareness = 1;\n// oxlint-disable-next-line no-unused-vars\nconst messageAuth = 2;\n\n/**\n * Internal key used in connection.setState() to track which awareness\n * client IDs are controlled by each connection. This survives hibernation\n * because connection state is persisted to WebSocket attachments.\n */\nconst AWARENESS_IDS_KEY = \"__ypsAwarenessIds\";\n\ntype YServerConnectionState = {\n [AWARENESS_IDS_KEY]?: number[];\n [key: string]: unknown;\n};\n\nfunction getAwarenessIds(conn: Connection): number[] {\n try {\n const state = conn.state as YServerConnectionState | null;\n return state?.[AWARENESS_IDS_KEY] ?? [];\n } catch {\n return [];\n }\n}\n\nfunction setAwarenessIds(conn: Connection, ids: number[]): void {\n try {\n conn.setState((prev: YServerConnectionState | null) => ({\n ...prev,\n [AWARENESS_IDS_KEY]: ids\n }));\n } catch {\n // ignore — may fail if connection is already closed\n }\n}\n\nclass WSSharedDoc extends YDoc {\n awareness: awarenessProtocol.Awareness;\n\n constructor() {\n super({ gc: true });\n this.awareness = new awarenessProtocol.Awareness(this);\n this.awareness.setLocalState(null);\n\n // Disable the awareness protocol's built-in check interval.\n // It renews the local clock every 15s and removes peers after 30s,\n // but we handle peer cleanup via onClose instead. Clearing it here\n // prevents it from defeating Durable Object hibernation.\n clearInterval(\n (\n this.awareness as unknown as {\n _checkInterval: ReturnType<typeof setInterval>;\n }\n )._checkInterval\n );\n }\n}\n\nconst CALLBACK_DEFAULTS = {\n debounceWait: 2000,\n debounceMaxWait: 10000,\n timeout: 5000\n};\n\nfunction readSyncMessage(\n decoder: decoding.Decoder,\n encoder: encoding.Encoder,\n doc: YDoc,\n transactionOrigin: Connection,\n readOnly = false\n) {\n const messageType = decoding.readVarUint(decoder);\n switch (messageType) {\n case syncProtocol.messageYjsSyncStep1:\n syncProtocol.readSyncStep1(decoder, encoder, doc);\n break;\n case syncProtocol.messageYjsSyncStep2:\n if (!readOnly)\n syncProtocol.readSyncStep2(decoder, doc, transactionOrigin);\n break;\n case syncProtocol.messageYjsUpdate:\n if (!readOnly) syncProtocol.readUpdate(decoder, doc, transactionOrigin);\n break;\n default:\n throw new Error(\"Unknown message type\");\n }\n return messageType;\n}\n\nfunction send(conn: Connection, m: Uint8Array): void {\n if (\n conn.readyState !== undefined &&\n conn.readyState !== wsReadyStateConnecting &&\n conn.readyState !== wsReadyStateOpen\n ) {\n return;\n }\n try {\n conn.send(m);\n } catch {\n // connection is broken, ignore\n }\n}\n\nexport interface CallbackOptions {\n debounceWait?: number;\n debounceMaxWait?: number;\n timeout?: number;\n}\n\ntype ServerClass = new (...args: any[]) => Server;\n\nexport interface YjsInstance {\n readonly document: WSSharedDoc;\n onLoad(): Promise<YDoc | void>;\n onSave(): Promise<void>;\n unstable_replaceDocument(\n snapshotUpdate: Uint8Array,\n getMetadata?: (key: string) => YjsRootType\n ): void;\n isReadOnly(connection: Connection): boolean;\n onCustomMessage(connection: Connection, message: string): void;\n sendCustomMessage(connection: Connection, message: string): void;\n broadcastCustomMessage(message: string, excludeConnection?: Connection): void;\n handleMessage(connection: Connection, message: WSMessage): void;\n}\n\nexport interface YjsStatic {\n callbackOptions: CallbackOptions;\n}\n\nexport function withYjs<TBase extends ServerClass>(\n Base: TBase\n): TBase & YjsStatic & (new (...args: any[]) => YjsInstance) {\n class YjsMixin extends Base {\n static callbackOptions: CallbackOptions = {};\n\n readonly document: WSSharedDoc = new WSSharedDoc();\n\n async onLoad(): Promise<YDoc | void> {\n // to be implemented by the user\n return;\n }\n\n async onSave(): Promise<void> {\n // to be implemented by the user\n }\n\n /**\n * Replaces the document with a different state using Yjs UndoManager key remapping.\n *\n * @param snapshotUpdate - The snapshot update to replace the document with.\n * @param getMetadata (optional) - A function that returns the type of the root for a given key.\n */\n unstable_replaceDocument(\n snapshotUpdate: Uint8Array,\n getMetadata: (key: string) => YjsRootType = () => \"Map\"\n ): void {\n try {\n const doc = this.document;\n const snapshotDoc = new YDoc();\n applyUpdate(snapshotDoc, snapshotUpdate, snapshotOrigin);\n\n const currentStateVector = encodeStateVector(doc);\n const snapshotStateVector = encodeStateVector(snapshotDoc);\n\n const changesSinceSnapshotUpdate = encodeStateAsUpdate(\n doc,\n snapshotStateVector\n );\n\n const undoManager = new UndoManager(\n [...snapshotDoc.share.keys()].map((key) => {\n const type = getMetadata(key);\n if (type === \"Text\") {\n return snapshotDoc.getText(key);\n } else if (type === \"Map\") {\n return snapshotDoc.getMap(key);\n } else if (type === \"Array\") {\n return snapshotDoc.getArray(key);\n } else if (type === \"XmlText\") {\n return snapshotDoc.get(key, XmlText);\n } else if (type === \"XmlElement\") {\n return snapshotDoc.get(key, XmlElement);\n } else if (type === \"XmlFragment\") {\n return snapshotDoc.get(key, XmlFragment);\n }\n throw new Error(`Unknown root type: ${type} for key: ${key}`);\n }),\n {\n trackedOrigins: new Set([snapshotOrigin])\n }\n );\n\n applyUpdate(snapshotDoc, changesSinceSnapshotUpdate, snapshotOrigin);\n undoManager.undo();\n\n const documentChangesSinceSnapshotUpdate = encodeStateAsUpdate(\n snapshotDoc,\n currentStateVector\n );\n\n applyUpdate(this.document, documentChangesSinceSnapshotUpdate);\n } catch (error) {\n throw new Error(\n `Failed to replace document: ${error instanceof Error ? error.message : \"Unknown error\"}`\n );\n }\n }\n\n async onStart(): Promise<void> {\n const src = await this.onLoad();\n if (src != null) {\n const state = encodeStateAsUpdate(src);\n applyUpdate(this.document, state);\n }\n\n // Broadcast doc updates to all connections.\n // Uses this.getConnections() which works for both hibernate and non-hibernate\n // modes and survives DO hibernation (unlike an in-memory Map).\n this.document.on(\"update\", (update: Uint8Array) => {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeUpdate(encoder, update);\n const message = encoding.toUint8Array(encoder);\n for (const conn of this.getConnections()) {\n send(conn, message);\n }\n });\n\n // Track which awareness clientIDs each connection controls.\n // Stored in connection.setState() so it survives hibernation.\n // When conn is null (internal changes like removeAwarenessStates on close),\n // broadcast the update to remaining connections.\n // When conn is non-null (client message), handleMessage broadcasts directly.\n this.document.awareness.on(\n \"update\",\n (\n {\n added,\n updated,\n removed\n }: {\n added: Array<number>;\n updated: Array<number>;\n removed: Array<number>;\n },\n conn: Connection | null\n ) => {\n if (conn !== null) {\n // Track which clientIDs this connection controls\n try {\n const currentIds = new Set(getAwarenessIds(conn));\n for (const clientID of added) currentIds.add(clientID);\n for (const clientID of removed) currentIds.delete(clientID);\n setAwarenessIds(conn, [...currentIds]);\n } catch (_e) {\n // ignore — best-effort tracking\n }\n } else {\n // Internal awareness change (e.g. removeAwarenessStates on close)\n // — broadcast to all remaining connections\n const changedClients = added.concat(updated, removed);\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.document.awareness,\n changedClients\n )\n );\n const buff = encoding.toUint8Array(encoder);\n for (const c of this.getConnections()) {\n send(c, buff);\n }\n }\n }\n );\n\n // Debounced persistence handler\n const ctor = this.constructor as typeof YjsMixin;\n this.document.on(\n \"update\",\n debounce(\n (_update: Uint8Array, _origin: Connection, _doc: YDoc) => {\n try {\n this.onSave().catch((err) => {\n console.error(\"failed to persist:\", err);\n });\n } catch (err) {\n console.error(\"failed to persist:\", err);\n }\n },\n ctor.callbackOptions.debounceWait || CALLBACK_DEFAULTS.debounceWait,\n {\n maxWait:\n ctor.callbackOptions.debounceMaxWait ||\n CALLBACK_DEFAULTS.debounceMaxWait\n }\n )\n );\n\n // After hibernation wake-up, the doc is empty but existing connections\n // survive. Re-sync by sending sync step 1 to all connections — they'll\n // respond with sync step 2 containing their full state.\n // On first start there are no connections, so this is a no-op.\n const syncEncoder = encoding.createEncoder();\n encoding.writeVarUint(syncEncoder, messageSync);\n syncProtocol.writeSyncStep1(syncEncoder, this.document);\n const syncMessage = encoding.toUint8Array(syncEncoder);\n for (const conn of this.getConnections()) {\n send(conn, syncMessage);\n }\n }\n\n // oxlint-disable-next-line no-unused-vars\n isReadOnly(connection: Connection): boolean {\n // to be implemented by the user\n return false;\n }\n\n /**\n * Handle custom string messages from the client.\n * Override this method to implement custom message handling.\n * @param connection - The connection that sent the message\n * @param message - The custom message string (without the __YPS: prefix)\n */\n // oxlint-disable-next-line no-unused-vars\n onCustomMessage(connection: Connection, message: string): void {\n // to be implemented by the user\n console.warn(\n `Received custom message but onCustomMessage is not implemented in ${this.constructor.name}:`,\n message\n );\n }\n\n /**\n * Send a custom string message to a specific connection.\n * @param connection - The connection to send the message to\n * @param message - The custom message string to send\n */\n sendCustomMessage(connection: Connection, message: string): void {\n if (\n connection.readyState !== undefined &&\n connection.readyState !== wsReadyStateConnecting &&\n connection.readyState !== wsReadyStateOpen\n ) {\n return;\n }\n try {\n connection.send(`__YPS:${message}`);\n } catch (e) {\n console.warn(\"Failed to send custom message\", e);\n }\n }\n\n /**\n * Broadcast a custom string message to all connected clients.\n * @param message - The custom message string to broadcast\n * @param excludeConnection - Optional connection to exclude from the broadcast\n */\n broadcastCustomMessage(\n message: string,\n excludeConnection?: Connection\n ): void {\n const formattedMessage = `__YPS:${message}`;\n for (const conn of this.getConnections()) {\n if (excludeConnection && conn === excludeConnection) {\n continue;\n }\n if (\n conn.readyState !== undefined &&\n conn.readyState !== wsReadyStateConnecting &&\n conn.readyState !== wsReadyStateOpen\n ) {\n continue;\n }\n try {\n conn.send(formattedMessage);\n } catch (e) {\n console.warn(\"Failed to broadcast custom message\", e);\n }\n }\n }\n\n handleMessage(connection: Connection, message: WSMessage) {\n if (typeof message === \"string\") {\n // Handle custom messages with __YPS: prefix\n if (message.startsWith(\"__YPS:\")) {\n const customMessage = message.slice(6); // Remove __YPS: prefix\n this.onCustomMessage(connection, customMessage);\n return;\n }\n console.warn(\n `Received non-prefixed string message. Custom messages should be sent using sendMessage() on the provider.`\n );\n return;\n }\n try {\n const encoder = encoding.createEncoder();\n // Convert ArrayBuffer to Uint8Array if needed (ArrayBufferView like Uint8Array can be used directly)\n const uint8Array =\n message instanceof Uint8Array\n ? message\n : message instanceof ArrayBuffer\n ? new Uint8Array(message)\n : new Uint8Array(\n message.buffer,\n message.byteOffset,\n message.byteLength\n );\n const decoder = decoding.createDecoder(uint8Array);\n const messageType = decoding.readVarUint(decoder);\n switch (messageType) {\n case messageSync:\n encoding.writeVarUint(encoder, messageSync);\n readSyncMessage(\n decoder,\n encoder,\n this.document,\n connection,\n this.isReadOnly(connection)\n );\n\n // If the `encoder` only contains the type of reply message and no\n // message, there is no need to send the message. When `encoder` only\n // contains the type of reply, its length is 1.\n if (encoding.length(encoder) > 1) {\n send(connection, encoding.toUint8Array(encoder));\n }\n break;\n case messageAwareness: {\n const awarenessData = decoding.readVarUint8Array(decoder);\n awarenessProtocol.applyAwarenessUpdate(\n this.document.awareness,\n awarenessData,\n connection\n );\n // Forward raw awareness bytes to all connections\n const awarenessEncoder = encoding.createEncoder();\n encoding.writeVarUint(awarenessEncoder, messageAwareness);\n encoding.writeVarUint8Array(awarenessEncoder, awarenessData);\n const awarenessBuff = encoding.toUint8Array(awarenessEncoder);\n for (const c of this.getConnections()) {\n send(c, awarenessBuff);\n }\n break;\n }\n }\n } catch (err) {\n console.error(err);\n // @ts-expect-error - TODO: fix this\n this.document.emit(\"error\", [err]);\n }\n }\n\n onMessage(conn: Connection, message: WSMessage) {\n this.handleMessage(conn, message);\n }\n\n onClose(\n connection: Connection<unknown>,\n _code: number,\n _reason: string,\n _wasClean: boolean\n ): void | Promise<void> {\n // Read controlled awareness clientIDs from connection state\n // (survives hibernation unlike an in-memory Map)\n const controlledIds = getAwarenessIds(connection);\n if (controlledIds.length > 0) {\n awarenessProtocol.removeAwarenessStates(\n this.document.awareness,\n controlledIds,\n null\n );\n }\n }\n\n // TODO: explore why onError gets triggered when a connection closes\n\n onConnect(\n conn: Connection<unknown>,\n _ctx: ConnectionContext\n ): void | Promise<void> {\n // Note: awareness IDs are lazily initialized when the first awareness\n // message is received — no need to call setAwarenessIds(conn, []) here\n\n // send sync step 1\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, this.document);\n send(conn, encoding.toUint8Array(encoder));\n const awarenessStates = this.document.awareness.getStates();\n if (awarenessStates.size > 0) {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.document.awareness,\n Array.from(awarenessStates.keys())\n )\n );\n send(conn, encoding.toUint8Array(encoder));\n }\n }\n }\n\n return YjsMixin as unknown as TBase &\n YjsStatic &\n (new (...args: any[]) => YjsInstance);\n}\n\nexport const YServer = withYjs(Server);\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,MAAM,iBAAiB,OAAO,kBAAkB;AAShD,MAAM,yBAAyB;AAC/B,MAAM,mBAAmB;AAMzB,MAAM,cAAc;AACpB,MAAM,mBAAmB;;;;;;AASzB,MAAM,oBAAoB;AAO1B,SAAS,gBAAgB,MAA4B;AACnD,KAAI;AAEF,SADc,KAAK,QACJ,sBAAsB,EAAE;SACjC;AACN,SAAO,EAAE;;;AAIb,SAAS,gBAAgB,MAAkB,KAAqB;AAC9D,KAAI;AACF,OAAK,UAAU,UAAyC;GACtD,GAAG;IACF,oBAAoB;GACtB,EAAE;SACG;;AAKV,IAAM,cAAN,cAA0BA,IAAAA,IAAK;CAC7B;CAEA,cAAc;AACZ,QAAM,EAAE,IAAI,MAAM,CAAC;AACnB,OAAK,YAAY,IAAIC,sBAAkB,UAAU,KAAK;AACtD,OAAK,UAAU,cAAc,KAAK;AAMlC,gBAEI,KAAK,UAGL,eACH;;;AAIL,MAAM,oBAAoB;CACxB,cAAc;CACd,iBAAiB;CACjB,SAAS;CACV;AAED,SAAS,gBACP,SACA,SACA,KACA,mBACA,WAAW,OACX;CACA,MAAM,cAAcC,cAAS,YAAY,QAAQ;AACjD,SAAQ,aAAR;EACE,KAAKC,iBAAa;AAChB,oBAAa,cAAc,SAAS,SAAS,IAAI;AACjD;EACF,KAAKA,iBAAa;AAChB,OAAI,CAAC,SACH,kBAAa,cAAc,SAAS,KAAK,kBAAkB;AAC7D;EACF,KAAKA,iBAAa;AAChB,OAAI,CAAC,SAAU,kBAAa,WAAW,SAAS,KAAK,kBAAkB;AACvE;EACF,QACE,OAAM,IAAI,MAAM,uBAAuB;;AAE3C,QAAO;;AAGT,SAAS,KAAK,MAAkB,GAAqB;AACnD,KACE,KAAK,eAAe,KAAA,KACpB,KAAK,eAAe,0BACpB,KAAK,eAAe,iBAEpB;AAEF,KAAI;AACF,OAAK,KAAK,EAAE;SACN;;AAgCV,SAAgB,QACd,MAC2D;CAC3D,MAAM,iBAAiB,KAAK;EAC1B,OAAO,kBAAmC,EAAE;EAE5C,WAAiC,IAAI,aAAa;EAElD,MAAM,SAA+B;EAKrC,MAAM,SAAwB;;;;;;;EAU9B,yBACE,gBACA,oBAAkD,OAC5C;AACN,OAAI;IACF,MAAM,MAAM,KAAK;IACjB,MAAM,cAAc,IAAIH,IAAAA,KAAM;AAC9B,KAAA,GAAA,IAAA,aAAY,aAAa,gBAAgB,eAAe;IAExD,MAAM,sBAAA,GAAA,IAAA,mBAAuC,IAAI;IAGjD,MAAM,8BAAA,GAAA,IAAA,qBACJ,MAAA,GAAA,IAAA,mBAH4C,YAIzB,CACpB;IAED,MAAM,cAAc,IAAII,IAAAA,YACtB,CAAC,GAAG,YAAY,MAAM,MAAM,CAAC,CAAC,KAAK,QAAQ;KACzC,MAAM,OAAO,YAAY,IAAI;AAC7B,SAAI,SAAS,OACX,QAAO,YAAY,QAAQ,IAAI;cACtB,SAAS,MAClB,QAAO,YAAY,OAAO,IAAI;cACrB,SAAS,QAClB,QAAO,YAAY,SAAS,IAAI;cACvB,SAAS,UAClB,QAAO,YAAY,IAAI,KAAKC,IAAAA,QAAQ;cAC3B,SAAS,aAClB,QAAO,YAAY,IAAI,KAAKC,IAAAA,WAAW;cAC9B,SAAS,cAClB,QAAO,YAAY,IAAI,KAAKC,IAAAA,YAAY;AAE1C,WAAM,IAAI,MAAM,sBAAsB,KAAK,YAAY,MAAM;MAC7D,EACF,EACE,gBAAgB,IAAI,IAAI,CAAC,eAAe,CAAC,EAC1C,CACF;AAED,KAAA,GAAA,IAAA,aAAY,aAAa,4BAA4B,eAAe;AACpE,gBAAY,MAAM;IAElB,MAAM,sCAAA,GAAA,IAAA,qBACJ,aACA,mBACD;AAED,KAAA,GAAA,IAAA,aAAY,KAAK,UAAU,mCAAmC;YACvD,OAAO;AACd,UAAM,IAAI,MACR,+BAA+B,iBAAiB,QAAQ,MAAM,UAAU,kBACzE;;;EAIL,MAAM,UAAyB;GAC7B,MAAM,MAAM,MAAM,KAAK,QAAQ;AAC/B,OAAI,OAAO,MAAM;IACf,MAAM,SAAA,GAAA,IAAA,qBAA4B,IAAI;AACtC,KAAA,GAAA,IAAA,aAAY,KAAK,UAAU,MAAM;;AAMnC,QAAK,SAAS,GAAG,WAAW,WAAuB;IACjD,MAAM,UAAUC,cAAS,eAAe;AACxC,kBAAS,aAAa,SAAS,YAAY;AAC3C,qBAAa,YAAY,SAAS,OAAO;IACzC,MAAM,UAAUA,cAAS,aAAa,QAAQ;AAC9C,SAAK,MAAM,QAAQ,KAAK,gBAAgB,CACtC,MAAK,MAAM,QAAQ;KAErB;AAOF,QAAK,SAAS,UAAU,GACtB,WAEE,EACE,OACA,SACA,WAMF,SACG;AACH,QAAI,SAAS,KAEX,KAAI;KACF,MAAM,aAAa,IAAI,IAAI,gBAAgB,KAAK,CAAC;AACjD,UAAK,MAAM,YAAY,MAAO,YAAW,IAAI,SAAS;AACtD,UAAK,MAAM,YAAY,QAAS,YAAW,OAAO,SAAS;AAC3D,qBAAgB,MAAM,CAAC,GAAG,WAAW,CAAC;aAC/B,IAAI;SAGR;KAGL,MAAM,iBAAiB,MAAM,OAAO,SAAS,QAAQ;KACrD,MAAM,UAAUA,cAAS,eAAe;AACxC,mBAAS,aAAa,SAAS,iBAAiB;AAChD,mBAAS,mBACP,SACAP,sBAAkB,sBAChB,KAAK,SAAS,WACd,eACD,CACF;KACD,MAAM,OAAOO,cAAS,aAAa,QAAQ;AAC3C,UAAK,MAAM,KAAK,KAAK,gBAAgB,CACnC,MAAK,GAAG,KAAK;;KAIpB;GAGD,MAAM,OAAO,KAAK;AAClB,QAAK,SAAS,GACZ,WAAA,GAAA,gBAAA,UAEG,SAAqB,SAAqB,SAAe;AACxD,QAAI;AACF,UAAK,QAAQ,CAAC,OAAO,QAAQ;AAC3B,cAAQ,MAAM,sBAAsB,IAAI;OACxC;aACK,KAAK;AACZ,aAAQ,MAAM,sBAAsB,IAAI;;MAG5C,KAAK,gBAAgB,gBAAgB,kBAAkB,cACvD,EACE,SACE,KAAK,gBAAgB,mBACrB,kBAAkB,iBACrB,CACF,CACF;GAMD,MAAM,cAAcA,cAAS,eAAe;AAC5C,iBAAS,aAAa,aAAa,YAAY;AAC/C,oBAAa,eAAe,aAAa,KAAK,SAAS;GACvD,MAAM,cAAcA,cAAS,aAAa,YAAY;AACtD,QAAK,MAAM,QAAQ,KAAK,gBAAgB,CACtC,MAAK,MAAM,YAAY;;EAK3B,WAAW,YAAiC;AAE1C,UAAO;;;;;;;;EAUT,gBAAgB,YAAwB,SAAuB;AAE7D,WAAQ,KACN,qEAAqE,KAAK,YAAY,KAAK,IAC3F,QACD;;;;;;;EAQH,kBAAkB,YAAwB,SAAuB;AAC/D,OACE,WAAW,eAAe,KAAA,KAC1B,WAAW,eAAe,0BAC1B,WAAW,eAAe,iBAE1B;AAEF,OAAI;AACF,eAAW,KAAK,SAAS,UAAU;YAC5B,GAAG;AACV,YAAQ,KAAK,iCAAiC,EAAE;;;;;;;;EASpD,uBACE,SACA,mBACM;GACN,MAAM,mBAAmB,SAAS;AAClC,QAAK,MAAM,QAAQ,KAAK,gBAAgB,EAAE;AACxC,QAAI,qBAAqB,SAAS,kBAChC;AAEF,QACE,KAAK,eAAe,KAAA,KACpB,KAAK,eAAe,0BACpB,KAAK,eAAe,iBAEpB;AAEF,QAAI;AACF,UAAK,KAAK,iBAAiB;aACpB,GAAG;AACV,aAAQ,KAAK,sCAAsC,EAAE;;;;EAK3D,cAAc,YAAwB,SAAoB;AACxD,OAAI,OAAO,YAAY,UAAU;AAE/B,QAAI,QAAQ,WAAW,SAAS,EAAE;KAChC,MAAM,gBAAgB,QAAQ,MAAM,EAAE;AACtC,UAAK,gBAAgB,YAAY,cAAc;AAC/C;;AAEF,YAAQ,KACN,4GACD;AACD;;AAEF,OAAI;IACF,MAAM,UAAUA,cAAS,eAAe;IAExC,MAAM,aACJ,mBAAmB,aACf,UACA,mBAAmB,cACjB,IAAI,WAAW,QAAQ,GACvB,IAAI,WACF,QAAQ,QACR,QAAQ,YACR,QAAQ,WACT;IACT,MAAM,UAAUN,cAAS,cAAc,WAAW;AAElD,YADoBA,cAAS,YAAY,QACtB,EAAnB;KACE,KAAK;AACH,oBAAS,aAAa,SAAS,YAAY;AAC3C,sBACE,SACA,SACA,KAAK,UACL,YACA,KAAK,WAAW,WAAW,CAC5B;AAKD,UAAIM,cAAS,OAAO,QAAQ,GAAG,EAC7B,MAAK,YAAYA,cAAS,aAAa,QAAQ,CAAC;AAElD;KACF,KAAK,kBAAkB;MACrB,MAAM,gBAAgBN,cAAS,kBAAkB,QAAQ;AACzD,4BAAkB,qBAChB,KAAK,SAAS,WACd,eACA,WACD;MAED,MAAM,mBAAmBM,cAAS,eAAe;AACjD,oBAAS,aAAa,kBAAkB,iBAAiB;AACzD,oBAAS,mBAAmB,kBAAkB,cAAc;MAC5D,MAAM,gBAAgBA,cAAS,aAAa,iBAAiB;AAC7D,WAAK,MAAM,KAAK,KAAK,gBAAgB,CACnC,MAAK,GAAG,cAAc;AAExB;;;YAGG,KAAK;AACZ,YAAQ,MAAM,IAAI;AAElB,SAAK,SAAS,KAAK,SAAS,CAAC,IAAI,CAAC;;;EAItC,UAAU,MAAkB,SAAoB;AAC9C,QAAK,cAAc,MAAM,QAAQ;;EAGnC,QACE,YACA,OACA,SACA,WACsB;GAGtB,MAAM,gBAAgB,gBAAgB,WAAW;AACjD,OAAI,cAAc,SAAS,EACzB,uBAAkB,sBAChB,KAAK,SAAS,WACd,eACA,KACD;;EAML,UACE,MACA,MACsB;GAKtB,MAAM,UAAUA,cAAS,eAAe;AACxC,iBAAS,aAAa,SAAS,YAAY;AAC3C,oBAAa,eAAe,SAAS,KAAK,SAAS;AACnD,QAAK,MAAMA,cAAS,aAAa,QAAQ,CAAC;GAC1C,MAAM,kBAAkB,KAAK,SAAS,UAAU,WAAW;AAC3D,OAAI,gBAAgB,OAAO,GAAG;IAC5B,MAAM,UAAUA,cAAS,eAAe;AACxC,kBAAS,aAAa,SAAS,iBAAiB;AAChD,kBAAS,mBACP,SACAP,sBAAkB,sBAChB,KAAK,SAAS,WACd,MAAM,KAAK,gBAAgB,MAAM,CAAC,CACnC,CACF;AACD,SAAK,MAAMO,cAAS,aAAa,QAAQ,CAAC;;;;AAKhD,QAAO;;AAKT,MAAa,UAAU,QAAQC,YAAAA,OAAO"}
@@ -14,7 +14,6 @@ import {
14
14
  encodeStateAsUpdate,
15
15
  encodeStateVector
16
16
  } from "yjs";
17
-
18
17
  //#region src/server/index.ts
19
18
  const snapshotOrigin = Symbol("snapshot-origin");
20
19
  const wsReadyStateConnecting = 0;
@@ -355,7 +354,7 @@ function withYjs(Base) {
355
354
  return YjsMixin;
356
355
  }
357
356
  const YServer = withYjs(Server);
358
-
359
357
  //#endregion
360
358
  export { YServer, withYjs };
359
+
361
360
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["YDoc"],"sources":["../../src/server/index.ts"],"sourcesContent":["import * as decoding from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport debounce from \"lodash.debounce\";\nimport type { Connection, ConnectionContext, WSMessage } from \"partyserver\";\nimport { Server } from \"partyserver\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport {\n applyUpdate,\n Doc as YDoc,\n encodeStateAsUpdate,\n encodeStateVector,\n UndoManager,\n XmlText,\n XmlElement,\n XmlFragment\n} from \"yjs\";\n\nconst snapshotOrigin = Symbol(\"snapshot-origin\");\ntype YjsRootType =\n | \"Text\"\n | \"Map\"\n | \"Array\"\n | \"XmlText\"\n | \"XmlElement\"\n | \"XmlFragment\";\n\nconst wsReadyStateConnecting = 0;\nconst wsReadyStateOpen = 1;\n// oxlint-disable-next-line no-unused-vars\nconst wsReadyStateClosing = 2;\n// oxlint-disable-next-line no-unused-vars\nconst wsReadyStateClosed = 3;\n\nconst messageSync = 0;\nconst messageAwareness = 1;\n// oxlint-disable-next-line no-unused-vars\nconst messageAuth = 2;\n\n/**\n * Internal key used in connection.setState() to track which awareness\n * client IDs are controlled by each connection. This survives hibernation\n * because connection state is persisted to WebSocket attachments.\n */\nconst AWARENESS_IDS_KEY = \"__ypsAwarenessIds\";\n\ntype YServerConnectionState = {\n [AWARENESS_IDS_KEY]?: number[];\n [key: string]: unknown;\n};\n\nfunction getAwarenessIds(conn: Connection): number[] {\n try {\n const state = conn.state as YServerConnectionState | null;\n return state?.[AWARENESS_IDS_KEY] ?? [];\n } catch {\n return [];\n }\n}\n\nfunction setAwarenessIds(conn: Connection, ids: number[]): void {\n try {\n conn.setState((prev: YServerConnectionState | null) => ({\n ...prev,\n [AWARENESS_IDS_KEY]: ids\n }));\n } catch {\n // ignore — may fail if connection is already closed\n }\n}\n\nclass WSSharedDoc extends YDoc {\n awareness: awarenessProtocol.Awareness;\n\n constructor() {\n super({ gc: true });\n this.awareness = new awarenessProtocol.Awareness(this);\n this.awareness.setLocalState(null);\n\n // Disable the awareness protocol's built-in check interval.\n // It renews the local clock every 15s and removes peers after 30s,\n // but we handle peer cleanup via onClose instead. Clearing it here\n // prevents it from defeating Durable Object hibernation.\n clearInterval(\n (\n this.awareness as unknown as {\n _checkInterval: ReturnType<typeof setInterval>;\n }\n )._checkInterval\n );\n }\n}\n\nconst CALLBACK_DEFAULTS = {\n debounceWait: 2000,\n debounceMaxWait: 10000,\n timeout: 5000\n};\n\nfunction readSyncMessage(\n decoder: decoding.Decoder,\n encoder: encoding.Encoder,\n doc: YDoc,\n transactionOrigin: Connection,\n readOnly = false\n) {\n const messageType = decoding.readVarUint(decoder);\n switch (messageType) {\n case syncProtocol.messageYjsSyncStep1:\n syncProtocol.readSyncStep1(decoder, encoder, doc);\n break;\n case syncProtocol.messageYjsSyncStep2:\n if (!readOnly)\n syncProtocol.readSyncStep2(decoder, doc, transactionOrigin);\n break;\n case syncProtocol.messageYjsUpdate:\n if (!readOnly) syncProtocol.readUpdate(decoder, doc, transactionOrigin);\n break;\n default:\n throw new Error(\"Unknown message type\");\n }\n return messageType;\n}\n\nfunction send(conn: Connection, m: Uint8Array): void {\n if (\n conn.readyState !== undefined &&\n conn.readyState !== wsReadyStateConnecting &&\n conn.readyState !== wsReadyStateOpen\n ) {\n return;\n }\n try {\n conn.send(m);\n } catch {\n // connection is broken, ignore\n }\n}\n\nexport interface CallbackOptions {\n debounceWait?: number;\n debounceMaxWait?: number;\n timeout?: number;\n}\n\ntype ServerClass = new (...args: any[]) => Server;\n\nexport interface YjsInstance {\n readonly document: WSSharedDoc;\n onLoad(): Promise<YDoc | void>;\n onSave(): Promise<void>;\n unstable_replaceDocument(\n snapshotUpdate: Uint8Array,\n getMetadata?: (key: string) => YjsRootType\n ): void;\n isReadOnly(connection: Connection): boolean;\n onCustomMessage(connection: Connection, message: string): void;\n sendCustomMessage(connection: Connection, message: string): void;\n broadcastCustomMessage(message: string, excludeConnection?: Connection): void;\n handleMessage(connection: Connection, message: WSMessage): void;\n}\n\nexport interface YjsStatic {\n callbackOptions: CallbackOptions;\n}\n\nexport function withYjs<TBase extends ServerClass>(\n Base: TBase\n): TBase & YjsStatic & (new (...args: any[]) => YjsInstance) {\n class YjsMixin extends Base {\n static callbackOptions: CallbackOptions = {};\n\n readonly document: WSSharedDoc = new WSSharedDoc();\n\n async onLoad(): Promise<YDoc | void> {\n // to be implemented by the user\n return;\n }\n\n async onSave(): Promise<void> {\n // to be implemented by the user\n }\n\n /**\n * Replaces the document with a different state using Yjs UndoManager key remapping.\n *\n * @param snapshotUpdate - The snapshot update to replace the document with.\n * @param getMetadata (optional) - A function that returns the type of the root for a given key.\n */\n unstable_replaceDocument(\n snapshotUpdate: Uint8Array,\n getMetadata: (key: string) => YjsRootType = () => \"Map\"\n ): void {\n try {\n const doc = this.document;\n const snapshotDoc = new YDoc();\n applyUpdate(snapshotDoc, snapshotUpdate, snapshotOrigin);\n\n const currentStateVector = encodeStateVector(doc);\n const snapshotStateVector = encodeStateVector(snapshotDoc);\n\n const changesSinceSnapshotUpdate = encodeStateAsUpdate(\n doc,\n snapshotStateVector\n );\n\n const undoManager = new UndoManager(\n [...snapshotDoc.share.keys()].map((key) => {\n const type = getMetadata(key);\n if (type === \"Text\") {\n return snapshotDoc.getText(key);\n } else if (type === \"Map\") {\n return snapshotDoc.getMap(key);\n } else if (type === \"Array\") {\n return snapshotDoc.getArray(key);\n } else if (type === \"XmlText\") {\n return snapshotDoc.get(key, XmlText);\n } else if (type === \"XmlElement\") {\n return snapshotDoc.get(key, XmlElement);\n } else if (type === \"XmlFragment\") {\n return snapshotDoc.get(key, XmlFragment);\n }\n throw new Error(`Unknown root type: ${type} for key: ${key}`);\n }),\n {\n trackedOrigins: new Set([snapshotOrigin])\n }\n );\n\n applyUpdate(snapshotDoc, changesSinceSnapshotUpdate, snapshotOrigin);\n undoManager.undo();\n\n const documentChangesSinceSnapshotUpdate = encodeStateAsUpdate(\n snapshotDoc,\n currentStateVector\n );\n\n applyUpdate(this.document, documentChangesSinceSnapshotUpdate);\n } catch (error) {\n throw new Error(\n `Failed to replace document: ${error instanceof Error ? error.message : \"Unknown error\"}`\n );\n }\n }\n\n async onStart(): Promise<void> {\n const src = await this.onLoad();\n if (src != null) {\n const state = encodeStateAsUpdate(src);\n applyUpdate(this.document, state);\n }\n\n // Broadcast doc updates to all connections.\n // Uses this.getConnections() which works for both hibernate and non-hibernate\n // modes and survives DO hibernation (unlike an in-memory Map).\n this.document.on(\"update\", (update: Uint8Array) => {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeUpdate(encoder, update);\n const message = encoding.toUint8Array(encoder);\n for (const conn of this.getConnections()) {\n send(conn, message);\n }\n });\n\n // Track which awareness clientIDs each connection controls.\n // Stored in connection.setState() so it survives hibernation.\n // When conn is null (internal changes like removeAwarenessStates on close),\n // broadcast the update to remaining connections.\n // When conn is non-null (client message), handleMessage broadcasts directly.\n this.document.awareness.on(\n \"update\",\n (\n {\n added,\n updated,\n removed\n }: {\n added: Array<number>;\n updated: Array<number>;\n removed: Array<number>;\n },\n conn: Connection | null\n ) => {\n if (conn !== null) {\n // Track which clientIDs this connection controls\n try {\n const currentIds = new Set(getAwarenessIds(conn));\n for (const clientID of added) currentIds.add(clientID);\n for (const clientID of removed) currentIds.delete(clientID);\n setAwarenessIds(conn, [...currentIds]);\n } catch (_e) {\n // ignore — best-effort tracking\n }\n } else {\n // Internal awareness change (e.g. removeAwarenessStates on close)\n // — broadcast to all remaining connections\n const changedClients = added.concat(updated, removed);\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.document.awareness,\n changedClients\n )\n );\n const buff = encoding.toUint8Array(encoder);\n for (const c of this.getConnections()) {\n send(c, buff);\n }\n }\n }\n );\n\n // Debounced persistence handler\n const ctor = this.constructor as typeof YjsMixin;\n this.document.on(\n \"update\",\n debounce(\n (_update: Uint8Array, _origin: Connection, _doc: YDoc) => {\n try {\n this.onSave().catch((err) => {\n console.error(\"failed to persist:\", err);\n });\n } catch (err) {\n console.error(\"failed to persist:\", err);\n }\n },\n ctor.callbackOptions.debounceWait || CALLBACK_DEFAULTS.debounceWait,\n {\n maxWait:\n ctor.callbackOptions.debounceMaxWait ||\n CALLBACK_DEFAULTS.debounceMaxWait\n }\n )\n );\n\n // After hibernation wake-up, the doc is empty but existing connections\n // survive. Re-sync by sending sync step 1 to all connections — they'll\n // respond with sync step 2 containing their full state.\n // On first start there are no connections, so this is a no-op.\n const syncEncoder = encoding.createEncoder();\n encoding.writeVarUint(syncEncoder, messageSync);\n syncProtocol.writeSyncStep1(syncEncoder, this.document);\n const syncMessage = encoding.toUint8Array(syncEncoder);\n for (const conn of this.getConnections()) {\n send(conn, syncMessage);\n }\n }\n\n // oxlint-disable-next-line no-unused-vars\n isReadOnly(connection: Connection): boolean {\n // to be implemented by the user\n return false;\n }\n\n /**\n * Handle custom string messages from the client.\n * Override this method to implement custom message handling.\n * @param connection - The connection that sent the message\n * @param message - The custom message string (without the __YPS: prefix)\n */\n // oxlint-disable-next-line no-unused-vars\n onCustomMessage(connection: Connection, message: string): void {\n // to be implemented by the user\n console.warn(\n `Received custom message but onCustomMessage is not implemented in ${this.constructor.name}:`,\n message\n );\n }\n\n /**\n * Send a custom string message to a specific connection.\n * @param connection - The connection to send the message to\n * @param message - The custom message string to send\n */\n sendCustomMessage(connection: Connection, message: string): void {\n if (\n connection.readyState !== undefined &&\n connection.readyState !== wsReadyStateConnecting &&\n connection.readyState !== wsReadyStateOpen\n ) {\n return;\n }\n try {\n connection.send(`__YPS:${message}`);\n } catch (e) {\n console.warn(\"Failed to send custom message\", e);\n }\n }\n\n /**\n * Broadcast a custom string message to all connected clients.\n * @param message - The custom message string to broadcast\n * @param excludeConnection - Optional connection to exclude from the broadcast\n */\n broadcastCustomMessage(\n message: string,\n excludeConnection?: Connection\n ): void {\n const formattedMessage = `__YPS:${message}`;\n for (const conn of this.getConnections()) {\n if (excludeConnection && conn === excludeConnection) {\n continue;\n }\n if (\n conn.readyState !== undefined &&\n conn.readyState !== wsReadyStateConnecting &&\n conn.readyState !== wsReadyStateOpen\n ) {\n continue;\n }\n try {\n conn.send(formattedMessage);\n } catch (e) {\n console.warn(\"Failed to broadcast custom message\", e);\n }\n }\n }\n\n handleMessage(connection: Connection, message: WSMessage) {\n if (typeof message === \"string\") {\n // Handle custom messages with __YPS: prefix\n if (message.startsWith(\"__YPS:\")) {\n const customMessage = message.slice(6); // Remove __YPS: prefix\n this.onCustomMessage(connection, customMessage);\n return;\n }\n console.warn(\n `Received non-prefixed string message. Custom messages should be sent using sendMessage() on the provider.`\n );\n return;\n }\n try {\n const encoder = encoding.createEncoder();\n // Convert ArrayBuffer to Uint8Array if needed (ArrayBufferView like Uint8Array can be used directly)\n const uint8Array =\n message instanceof Uint8Array\n ? message\n : message instanceof ArrayBuffer\n ? new Uint8Array(message)\n : new Uint8Array(\n message.buffer,\n message.byteOffset,\n message.byteLength\n );\n const decoder = decoding.createDecoder(uint8Array);\n const messageType = decoding.readVarUint(decoder);\n switch (messageType) {\n case messageSync:\n encoding.writeVarUint(encoder, messageSync);\n readSyncMessage(\n decoder,\n encoder,\n this.document,\n connection,\n this.isReadOnly(connection)\n );\n\n // If the `encoder` only contains the type of reply message and no\n // message, there is no need to send the message. When `encoder` only\n // contains the type of reply, its length is 1.\n if (encoding.length(encoder) > 1) {\n send(connection, encoding.toUint8Array(encoder));\n }\n break;\n case messageAwareness: {\n const awarenessData = decoding.readVarUint8Array(decoder);\n awarenessProtocol.applyAwarenessUpdate(\n this.document.awareness,\n awarenessData,\n connection\n );\n // Forward raw awareness bytes to all connections\n const awarenessEncoder = encoding.createEncoder();\n encoding.writeVarUint(awarenessEncoder, messageAwareness);\n encoding.writeVarUint8Array(awarenessEncoder, awarenessData);\n const awarenessBuff = encoding.toUint8Array(awarenessEncoder);\n for (const c of this.getConnections()) {\n send(c, awarenessBuff);\n }\n break;\n }\n }\n } catch (err) {\n console.error(err);\n // @ts-expect-error - TODO: fix this\n this.document.emit(\"error\", [err]);\n }\n }\n\n onMessage(conn: Connection, message: WSMessage) {\n this.handleMessage(conn, message);\n }\n\n onClose(\n connection: Connection<unknown>,\n _code: number,\n _reason: string,\n _wasClean: boolean\n ): void | Promise<void> {\n // Read controlled awareness clientIDs from connection state\n // (survives hibernation unlike an in-memory Map)\n const controlledIds = getAwarenessIds(connection);\n if (controlledIds.length > 0) {\n awarenessProtocol.removeAwarenessStates(\n this.document.awareness,\n controlledIds,\n null\n );\n }\n }\n\n // TODO: explore why onError gets triggered when a connection closes\n\n onConnect(\n conn: Connection<unknown>,\n _ctx: ConnectionContext\n ): void | Promise<void> {\n // Note: awareness IDs are lazily initialized when the first awareness\n // message is received — no need to call setAwarenessIds(conn, []) here\n\n // send sync step 1\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, this.document);\n send(conn, encoding.toUint8Array(encoder));\n const awarenessStates = this.document.awareness.getStates();\n if (awarenessStates.size > 0) {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.document.awareness,\n Array.from(awarenessStates.keys())\n )\n );\n send(conn, encoding.toUint8Array(encoder));\n }\n }\n }\n\n return YjsMixin as unknown as TBase &\n YjsStatic &\n (new (...args: any[]) => YjsInstance);\n}\n\nexport const YServer = withYjs(Server);\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["YDoc"],"sources":["../../src/server/index.ts"],"sourcesContent":["import * as decoding from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport debounce from \"lodash.debounce\";\nimport type { Connection, ConnectionContext, WSMessage } from \"partyserver\";\nimport { Server } from \"partyserver\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport {\n applyUpdate,\n Doc as YDoc,\n encodeStateAsUpdate,\n encodeStateVector,\n UndoManager,\n XmlText,\n XmlElement,\n XmlFragment\n} from \"yjs\";\n\nconst snapshotOrigin = Symbol(\"snapshot-origin\");\ntype YjsRootType =\n | \"Text\"\n | \"Map\"\n | \"Array\"\n | \"XmlText\"\n | \"XmlElement\"\n | \"XmlFragment\";\n\nconst wsReadyStateConnecting = 0;\nconst wsReadyStateOpen = 1;\n// oxlint-disable-next-line no-unused-vars\nconst wsReadyStateClosing = 2;\n// oxlint-disable-next-line no-unused-vars\nconst wsReadyStateClosed = 3;\n\nconst messageSync = 0;\nconst messageAwareness = 1;\n// oxlint-disable-next-line no-unused-vars\nconst messageAuth = 2;\n\n/**\n * Internal key used in connection.setState() to track which awareness\n * client IDs are controlled by each connection. This survives hibernation\n * because connection state is persisted to WebSocket attachments.\n */\nconst AWARENESS_IDS_KEY = \"__ypsAwarenessIds\";\n\ntype YServerConnectionState = {\n [AWARENESS_IDS_KEY]?: number[];\n [key: string]: unknown;\n};\n\nfunction getAwarenessIds(conn: Connection): number[] {\n try {\n const state = conn.state as YServerConnectionState | null;\n return state?.[AWARENESS_IDS_KEY] ?? [];\n } catch {\n return [];\n }\n}\n\nfunction setAwarenessIds(conn: Connection, ids: number[]): void {\n try {\n conn.setState((prev: YServerConnectionState | null) => ({\n ...prev,\n [AWARENESS_IDS_KEY]: ids\n }));\n } catch {\n // ignore — may fail if connection is already closed\n }\n}\n\nclass WSSharedDoc extends YDoc {\n awareness: awarenessProtocol.Awareness;\n\n constructor() {\n super({ gc: true });\n this.awareness = new awarenessProtocol.Awareness(this);\n this.awareness.setLocalState(null);\n\n // Disable the awareness protocol's built-in check interval.\n // It renews the local clock every 15s and removes peers after 30s,\n // but we handle peer cleanup via onClose instead. Clearing it here\n // prevents it from defeating Durable Object hibernation.\n clearInterval(\n (\n this.awareness as unknown as {\n _checkInterval: ReturnType<typeof setInterval>;\n }\n )._checkInterval\n );\n }\n}\n\nconst CALLBACK_DEFAULTS = {\n debounceWait: 2000,\n debounceMaxWait: 10000,\n timeout: 5000\n};\n\nfunction readSyncMessage(\n decoder: decoding.Decoder,\n encoder: encoding.Encoder,\n doc: YDoc,\n transactionOrigin: Connection,\n readOnly = false\n) {\n const messageType = decoding.readVarUint(decoder);\n switch (messageType) {\n case syncProtocol.messageYjsSyncStep1:\n syncProtocol.readSyncStep1(decoder, encoder, doc);\n break;\n case syncProtocol.messageYjsSyncStep2:\n if (!readOnly)\n syncProtocol.readSyncStep2(decoder, doc, transactionOrigin);\n break;\n case syncProtocol.messageYjsUpdate:\n if (!readOnly) syncProtocol.readUpdate(decoder, doc, transactionOrigin);\n break;\n default:\n throw new Error(\"Unknown message type\");\n }\n return messageType;\n}\n\nfunction send(conn: Connection, m: Uint8Array): void {\n if (\n conn.readyState !== undefined &&\n conn.readyState !== wsReadyStateConnecting &&\n conn.readyState !== wsReadyStateOpen\n ) {\n return;\n }\n try {\n conn.send(m);\n } catch {\n // connection is broken, ignore\n }\n}\n\nexport interface CallbackOptions {\n debounceWait?: number;\n debounceMaxWait?: number;\n timeout?: number;\n}\n\ntype ServerClass = new (...args: any[]) => Server;\n\nexport interface YjsInstance {\n readonly document: WSSharedDoc;\n onLoad(): Promise<YDoc | void>;\n onSave(): Promise<void>;\n unstable_replaceDocument(\n snapshotUpdate: Uint8Array,\n getMetadata?: (key: string) => YjsRootType\n ): void;\n isReadOnly(connection: Connection): boolean;\n onCustomMessage(connection: Connection, message: string): void;\n sendCustomMessage(connection: Connection, message: string): void;\n broadcastCustomMessage(message: string, excludeConnection?: Connection): void;\n handleMessage(connection: Connection, message: WSMessage): void;\n}\n\nexport interface YjsStatic {\n callbackOptions: CallbackOptions;\n}\n\nexport function withYjs<TBase extends ServerClass>(\n Base: TBase\n): TBase & YjsStatic & (new (...args: any[]) => YjsInstance) {\n class YjsMixin extends Base {\n static callbackOptions: CallbackOptions = {};\n\n readonly document: WSSharedDoc = new WSSharedDoc();\n\n async onLoad(): Promise<YDoc | void> {\n // to be implemented by the user\n return;\n }\n\n async onSave(): Promise<void> {\n // to be implemented by the user\n }\n\n /**\n * Replaces the document with a different state using Yjs UndoManager key remapping.\n *\n * @param snapshotUpdate - The snapshot update to replace the document with.\n * @param getMetadata (optional) - A function that returns the type of the root for a given key.\n */\n unstable_replaceDocument(\n snapshotUpdate: Uint8Array,\n getMetadata: (key: string) => YjsRootType = () => \"Map\"\n ): void {\n try {\n const doc = this.document;\n const snapshotDoc = new YDoc();\n applyUpdate(snapshotDoc, snapshotUpdate, snapshotOrigin);\n\n const currentStateVector = encodeStateVector(doc);\n const snapshotStateVector = encodeStateVector(snapshotDoc);\n\n const changesSinceSnapshotUpdate = encodeStateAsUpdate(\n doc,\n snapshotStateVector\n );\n\n const undoManager = new UndoManager(\n [...snapshotDoc.share.keys()].map((key) => {\n const type = getMetadata(key);\n if (type === \"Text\") {\n return snapshotDoc.getText(key);\n } else if (type === \"Map\") {\n return snapshotDoc.getMap(key);\n } else if (type === \"Array\") {\n return snapshotDoc.getArray(key);\n } else if (type === \"XmlText\") {\n return snapshotDoc.get(key, XmlText);\n } else if (type === \"XmlElement\") {\n return snapshotDoc.get(key, XmlElement);\n } else if (type === \"XmlFragment\") {\n return snapshotDoc.get(key, XmlFragment);\n }\n throw new Error(`Unknown root type: ${type} for key: ${key}`);\n }),\n {\n trackedOrigins: new Set([snapshotOrigin])\n }\n );\n\n applyUpdate(snapshotDoc, changesSinceSnapshotUpdate, snapshotOrigin);\n undoManager.undo();\n\n const documentChangesSinceSnapshotUpdate = encodeStateAsUpdate(\n snapshotDoc,\n currentStateVector\n );\n\n applyUpdate(this.document, documentChangesSinceSnapshotUpdate);\n } catch (error) {\n throw new Error(\n `Failed to replace document: ${error instanceof Error ? error.message : \"Unknown error\"}`\n );\n }\n }\n\n async onStart(): Promise<void> {\n const src = await this.onLoad();\n if (src != null) {\n const state = encodeStateAsUpdate(src);\n applyUpdate(this.document, state);\n }\n\n // Broadcast doc updates to all connections.\n // Uses this.getConnections() which works for both hibernate and non-hibernate\n // modes and survives DO hibernation (unlike an in-memory Map).\n this.document.on(\"update\", (update: Uint8Array) => {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeUpdate(encoder, update);\n const message = encoding.toUint8Array(encoder);\n for (const conn of this.getConnections()) {\n send(conn, message);\n }\n });\n\n // Track which awareness clientIDs each connection controls.\n // Stored in connection.setState() so it survives hibernation.\n // When conn is null (internal changes like removeAwarenessStates on close),\n // broadcast the update to remaining connections.\n // When conn is non-null (client message), handleMessage broadcasts directly.\n this.document.awareness.on(\n \"update\",\n (\n {\n added,\n updated,\n removed\n }: {\n added: Array<number>;\n updated: Array<number>;\n removed: Array<number>;\n },\n conn: Connection | null\n ) => {\n if (conn !== null) {\n // Track which clientIDs this connection controls\n try {\n const currentIds = new Set(getAwarenessIds(conn));\n for (const clientID of added) currentIds.add(clientID);\n for (const clientID of removed) currentIds.delete(clientID);\n setAwarenessIds(conn, [...currentIds]);\n } catch (_e) {\n // ignore — best-effort tracking\n }\n } else {\n // Internal awareness change (e.g. removeAwarenessStates on close)\n // — broadcast to all remaining connections\n const changedClients = added.concat(updated, removed);\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.document.awareness,\n changedClients\n )\n );\n const buff = encoding.toUint8Array(encoder);\n for (const c of this.getConnections()) {\n send(c, buff);\n }\n }\n }\n );\n\n // Debounced persistence handler\n const ctor = this.constructor as typeof YjsMixin;\n this.document.on(\n \"update\",\n debounce(\n (_update: Uint8Array, _origin: Connection, _doc: YDoc) => {\n try {\n this.onSave().catch((err) => {\n console.error(\"failed to persist:\", err);\n });\n } catch (err) {\n console.error(\"failed to persist:\", err);\n }\n },\n ctor.callbackOptions.debounceWait || CALLBACK_DEFAULTS.debounceWait,\n {\n maxWait:\n ctor.callbackOptions.debounceMaxWait ||\n CALLBACK_DEFAULTS.debounceMaxWait\n }\n )\n );\n\n // After hibernation wake-up, the doc is empty but existing connections\n // survive. Re-sync by sending sync step 1 to all connections — they'll\n // respond with sync step 2 containing their full state.\n // On first start there are no connections, so this is a no-op.\n const syncEncoder = encoding.createEncoder();\n encoding.writeVarUint(syncEncoder, messageSync);\n syncProtocol.writeSyncStep1(syncEncoder, this.document);\n const syncMessage = encoding.toUint8Array(syncEncoder);\n for (const conn of this.getConnections()) {\n send(conn, syncMessage);\n }\n }\n\n // oxlint-disable-next-line no-unused-vars\n isReadOnly(connection: Connection): boolean {\n // to be implemented by the user\n return false;\n }\n\n /**\n * Handle custom string messages from the client.\n * Override this method to implement custom message handling.\n * @param connection - The connection that sent the message\n * @param message - The custom message string (without the __YPS: prefix)\n */\n // oxlint-disable-next-line no-unused-vars\n onCustomMessage(connection: Connection, message: string): void {\n // to be implemented by the user\n console.warn(\n `Received custom message but onCustomMessage is not implemented in ${this.constructor.name}:`,\n message\n );\n }\n\n /**\n * Send a custom string message to a specific connection.\n * @param connection - The connection to send the message to\n * @param message - The custom message string to send\n */\n sendCustomMessage(connection: Connection, message: string): void {\n if (\n connection.readyState !== undefined &&\n connection.readyState !== wsReadyStateConnecting &&\n connection.readyState !== wsReadyStateOpen\n ) {\n return;\n }\n try {\n connection.send(`__YPS:${message}`);\n } catch (e) {\n console.warn(\"Failed to send custom message\", e);\n }\n }\n\n /**\n * Broadcast a custom string message to all connected clients.\n * @param message - The custom message string to broadcast\n * @param excludeConnection - Optional connection to exclude from the broadcast\n */\n broadcastCustomMessage(\n message: string,\n excludeConnection?: Connection\n ): void {\n const formattedMessage = `__YPS:${message}`;\n for (const conn of this.getConnections()) {\n if (excludeConnection && conn === excludeConnection) {\n continue;\n }\n if (\n conn.readyState !== undefined &&\n conn.readyState !== wsReadyStateConnecting &&\n conn.readyState !== wsReadyStateOpen\n ) {\n continue;\n }\n try {\n conn.send(formattedMessage);\n } catch (e) {\n console.warn(\"Failed to broadcast custom message\", e);\n }\n }\n }\n\n handleMessage(connection: Connection, message: WSMessage) {\n if (typeof message === \"string\") {\n // Handle custom messages with __YPS: prefix\n if (message.startsWith(\"__YPS:\")) {\n const customMessage = message.slice(6); // Remove __YPS: prefix\n this.onCustomMessage(connection, customMessage);\n return;\n }\n console.warn(\n `Received non-prefixed string message. Custom messages should be sent using sendMessage() on the provider.`\n );\n return;\n }\n try {\n const encoder = encoding.createEncoder();\n // Convert ArrayBuffer to Uint8Array if needed (ArrayBufferView like Uint8Array can be used directly)\n const uint8Array =\n message instanceof Uint8Array\n ? message\n : message instanceof ArrayBuffer\n ? new Uint8Array(message)\n : new Uint8Array(\n message.buffer,\n message.byteOffset,\n message.byteLength\n );\n const decoder = decoding.createDecoder(uint8Array);\n const messageType = decoding.readVarUint(decoder);\n switch (messageType) {\n case messageSync:\n encoding.writeVarUint(encoder, messageSync);\n readSyncMessage(\n decoder,\n encoder,\n this.document,\n connection,\n this.isReadOnly(connection)\n );\n\n // If the `encoder` only contains the type of reply message and no\n // message, there is no need to send the message. When `encoder` only\n // contains the type of reply, its length is 1.\n if (encoding.length(encoder) > 1) {\n send(connection, encoding.toUint8Array(encoder));\n }\n break;\n case messageAwareness: {\n const awarenessData = decoding.readVarUint8Array(decoder);\n awarenessProtocol.applyAwarenessUpdate(\n this.document.awareness,\n awarenessData,\n connection\n );\n // Forward raw awareness bytes to all connections\n const awarenessEncoder = encoding.createEncoder();\n encoding.writeVarUint(awarenessEncoder, messageAwareness);\n encoding.writeVarUint8Array(awarenessEncoder, awarenessData);\n const awarenessBuff = encoding.toUint8Array(awarenessEncoder);\n for (const c of this.getConnections()) {\n send(c, awarenessBuff);\n }\n break;\n }\n }\n } catch (err) {\n console.error(err);\n // @ts-expect-error - TODO: fix this\n this.document.emit(\"error\", [err]);\n }\n }\n\n onMessage(conn: Connection, message: WSMessage) {\n this.handleMessage(conn, message);\n }\n\n onClose(\n connection: Connection<unknown>,\n _code: number,\n _reason: string,\n _wasClean: boolean\n ): void | Promise<void> {\n // Read controlled awareness clientIDs from connection state\n // (survives hibernation unlike an in-memory Map)\n const controlledIds = getAwarenessIds(connection);\n if (controlledIds.length > 0) {\n awarenessProtocol.removeAwarenessStates(\n this.document.awareness,\n controlledIds,\n null\n );\n }\n }\n\n // TODO: explore why onError gets triggered when a connection closes\n\n onConnect(\n conn: Connection<unknown>,\n _ctx: ConnectionContext\n ): void | Promise<void> {\n // Note: awareness IDs are lazily initialized when the first awareness\n // message is received — no need to call setAwarenessIds(conn, []) here\n\n // send sync step 1\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, this.document);\n send(conn, encoding.toUint8Array(encoder));\n const awarenessStates = this.document.awareness.getStates();\n if (awarenessStates.size > 0) {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.document.awareness,\n Array.from(awarenessStates.keys())\n )\n );\n send(conn, encoding.toUint8Array(encoder));\n }\n }\n }\n\n return YjsMixin as unknown as TBase &\n YjsStatic &\n (new (...args: any[]) => YjsInstance);\n}\n\nexport const YServer = withYjs(Server);\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "y-partyserver",
3
- "version": "2.1.4",
3
+ "version": "2.2.0",
4
4
  "description": "",
5
5
  "keywords": [
6
6
  "collaboration",
@@ -58,18 +58,19 @@
58
58
  "dependencies": {
59
59
  "lib0": "^0.2.117",
60
60
  "lodash.debounce": "^4.0.8",
61
- "nanoid": "^5.1.6",
61
+ "nanoid": "^5.1.9",
62
62
  "y-protocols": "^1.0.7"
63
63
  },
64
64
  "devDependencies": {
65
- "@cloudflare/workers-types": "^4.20260303.0",
65
+ "@cloudflare/workers-types": "^4.20260424.1",
66
66
  "@types/lodash.debounce": "^4.0.9",
67
- "partyserver": "^0.4.1",
68
- "ws": "^8.19.0",
69
- "yjs": "^13.6.29"
67
+ "@types/node": "25.6.0",
68
+ "partyserver": "^0.5.0",
69
+ "ws": "^8.20.0",
70
+ "yjs": "^13.6.30"
70
71
  },
71
72
  "peerDependencies": {
72
- "@cloudflare/workers-types": "^4.20240729.0",
73
+ "@cloudflare/workers-types": "^4.20260424.1",
73
74
  "partyserver": ">=0.2.0 <1.0.0",
74
75
  "yjs": "^13.6.14"
75
76
  }