@hocuspocus/provider 3.4.6-rc.2 → 4.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
- import { WsReadyStates, awarenessStatesToArray, readAuthMessage, writeAuthentication } from "@hocuspocus/common";
1
+ import { WsReadyStates, awarenessStatesToArray, makeRoutingKey, parseRoutingKey, readAuthMessage, writeAuthentication } from "@hocuspocus/common";
2
2
  import * as Y from "yjs";
3
3
  import { retry } from "@lifeomic/attempt";
4
4
 
5
- //#region node_modules/lib0/math.js
5
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/math.js
6
6
  /**
7
7
  * Common Math expressions.
8
8
  *
@@ -26,7 +26,7 @@ const max = (a, b) => a > b ? a : b;
26
26
  const isNaN$1 = Number.isNaN;
27
27
 
28
28
  //#endregion
29
- //#region node_modules/lib0/binary.js
29
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/binary.js
30
30
  const BIT7 = 64;
31
31
  const BIT8 = 128;
32
32
  const BIT18 = 1 << 17;
@@ -70,7 +70,7 @@ const BITS31 = 2147483647;
70
70
  const BITS32 = 4294967295;
71
71
 
72
72
  //#endregion
73
- //#region node_modules/lib0/number.js
73
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/number.js
74
74
  /**
75
75
  * Utility helpers for working with numbers.
76
76
  *
@@ -87,7 +87,7 @@ const isNaN = Number.isNaN;
87
87
  const parseInt = Number.parseInt;
88
88
 
89
89
  //#endregion
90
- //#region node_modules/lib0/set.js
90
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/set.js
91
91
  /**
92
92
  * Utility module to work with sets.
93
93
  *
@@ -96,7 +96,7 @@ const parseInt = Number.parseInt;
96
96
  const create$2 = () => /* @__PURE__ */ new Set();
97
97
 
98
98
  //#endregion
99
- //#region node_modules/lib0/array.js
99
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/array.js
100
100
  /**
101
101
  * Transforms something array-like to an actual Array.
102
102
  *
@@ -109,7 +109,7 @@ const from = Array.from;
109
109
  const isArray$1 = Array.isArray;
110
110
 
111
111
  //#endregion
112
- //#region node_modules/lib0/string.js
112
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/string.js
113
113
  /**
114
114
  * Utility module to work with strings.
115
115
  *
@@ -124,7 +124,7 @@ const fromCodePoint = String.fromCodePoint;
124
124
  const MAX_UTF16_CHARACTER = fromCharCode(65535);
125
125
  /**
126
126
  * @param {string} str
127
- * @return {Uint8Array}
127
+ * @return {Uint8Array<ArrayBuffer>}
128
128
  */
129
129
  const _encodeUtf8Polyfill = (str) => {
130
130
  const encodedString = unescape(encodeURIComponent(str));
@@ -137,7 +137,7 @@ const _encodeUtf8Polyfill = (str) => {
137
137
  const utf8TextEncoder = typeof TextEncoder !== "undefined" ? new TextEncoder() : null;
138
138
  /**
139
139
  * @param {string} str
140
- * @return {Uint8Array}
140
+ * @return {Uint8Array<ArrayBuffer>}
141
141
  */
142
142
  const _encodeUtf8Native = (str) => utf8TextEncoder.encode(str);
143
143
  /**
@@ -157,7 +157,7 @@ if (utf8TextDecoder && utf8TextDecoder.decode(new Uint8Array()).length === 1)
157
157
  utf8TextDecoder = null;
158
158
 
159
159
  //#endregion
160
- //#region node_modules/lib0/encoding.js
160
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/encoding.js
161
161
  /**
162
162
  * Efficient schema-less binary encoding with support for variable length encoding.
163
163
  *
@@ -210,7 +210,7 @@ const createEncoder = () => new Encoder();
210
210
  * @param {Encoder} encoder
211
211
  * @return {number}
212
212
  */
213
- const length$1 = (encoder) => {
213
+ const length = (encoder) => {
214
214
  let len = encoder.cpos;
215
215
  for (let i = 0; i < encoder.bufs.length; i++) len += encoder.bufs[i].length;
216
216
  return len;
@@ -220,10 +220,10 @@ const length$1 = (encoder) => {
220
220
  *
221
221
  * @function
222
222
  * @param {Encoder} encoder
223
- * @return {Uint8Array} The created ArrayBuffer.
223
+ * @return {Uint8Array<ArrayBuffer>} The created ArrayBuffer.
224
224
  */
225
225
  const toUint8Array = (encoder) => {
226
- const uint8arr = new Uint8Array(length$1(encoder));
226
+ const uint8arr = new Uint8Array(length(encoder));
227
227
  let curPos = 0;
228
228
  for (let i = 0; i < encoder.bufs.length; i++) {
229
229
  const d = encoder.bufs[i];
@@ -339,7 +339,7 @@ const writeVarUint8Array = (encoder, uint8Array) => {
339
339
  };
340
340
 
341
341
  //#endregion
342
- //#region node_modules/lib0/error.js
342
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/error.js
343
343
  /**
344
344
  * Error helpers.
345
345
  *
@@ -353,7 +353,7 @@ const writeVarUint8Array = (encoder, uint8Array) => {
353
353
  const create$1 = (s) => new Error(s);
354
354
 
355
355
  //#endregion
356
- //#region node_modules/lib0/decoding.js
356
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/decoding.js
357
357
  /**
358
358
  * Efficient schema-less binary decoding with support for variable length encoding.
359
359
  *
@@ -385,16 +385,17 @@ const errorUnexpectedEndOfArray = create$1("Unexpected end of array");
385
385
  const errorIntegerOutOfRange = create$1("Integer out of Range");
386
386
  /**
387
387
  * A Decoder handles the decoding of an Uint8Array.
388
+ * @template {ArrayBufferLike} [Buf=ArrayBufferLike]
388
389
  */
389
390
  var Decoder = class {
390
391
  /**
391
- * @param {Uint8Array} uint8Array Binary data to decode
392
+ * @param {Uint8Array<Buf>} uint8Array Binary data to decode
392
393
  */
393
394
  constructor(uint8Array) {
394
395
  /**
395
396
  * Decoding target.
396
397
  *
397
- * @type {Uint8Array}
398
+ * @type {Uint8Array<Buf>}
398
399
  */
399
400
  this.arr = uint8Array;
400
401
  /**
@@ -407,8 +408,9 @@ var Decoder = class {
407
408
  };
408
409
  /**
409
410
  * @function
410
- * @param {Uint8Array} uint8Array
411
- * @return {Decoder}
411
+ * @template {ArrayBufferLike} Buf
412
+ * @param {Uint8Array<Buf>} uint8Array
413
+ * @return {Decoder<Buf>}
412
414
  */
413
415
  const createDecoder = (uint8Array) => new Decoder(uint8Array);
414
416
  /**
@@ -418,9 +420,10 @@ const createDecoder = (uint8Array) => new Decoder(uint8Array);
418
420
  * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
419
421
  *
420
422
  * @function
421
- * @param {Decoder} decoder The decoder instance
423
+ * @template {ArrayBufferLike} Buf
424
+ * @param {Decoder<Buf>} decoder The decoder instance
422
425
  * @param {number} len The length of bytes to read
423
- * @return {Uint8Array}
426
+ * @return {Uint8Array<Buf>}
424
427
  */
425
428
  const readUint8Array = (decoder, len) => {
426
429
  const view = new Uint8Array(decoder.arr.buffer, decoder.pos + decoder.arr.byteOffset, len);
@@ -434,8 +437,9 @@ const readUint8Array = (decoder, len) => {
434
437
  * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
435
438
  *
436
439
  * @function
437
- * @param {Decoder} decoder
438
- * @return {Uint8Array}
440
+ * @template {ArrayBufferLike} Buf
441
+ * @param {Decoder<Buf>} decoder
442
+ * @return {Uint8Array<Buf>}
439
443
  */
440
444
  const readVarUint8Array = (decoder) => readUint8Array(decoder, readVarUint(decoder));
441
445
  /**
@@ -560,7 +564,7 @@ const peekVarString = (decoder) => {
560
564
  };
561
565
 
562
566
  //#endregion
563
- //#region node_modules/lib0/time.js
567
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/time.js
564
568
  /**
565
569
  * Return current unix time.
566
570
  *
@@ -569,13 +573,18 @@ const peekVarString = (decoder) => {
569
573
  const getUnixTime = Date.now;
570
574
 
571
575
  //#endregion
572
- //#region node_modules/lib0/map.js
576
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/map.js
573
577
  /**
574
578
  * Utility module to work with key-value stores.
575
579
  *
576
580
  * @module map
577
581
  */
578
582
  /**
583
+ * @template K
584
+ * @template V
585
+ * @typedef {Map<K,V>} GlobalMap
586
+ */
587
+ /**
579
588
  * Creates a new Map instance.
580
589
  *
581
590
  * @function
@@ -607,7 +616,7 @@ const setIfUndefined = (map, key, createT) => {
607
616
  };
608
617
 
609
618
  //#endregion
610
- //#region node_modules/lib0/observable.js
619
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/observable.js
611
620
  /**
612
621
  * Observable class prototype.
613
622
  *
@@ -679,41 +688,36 @@ var Observable = class {
679
688
  /* c8 ignore end */
680
689
 
681
690
  //#endregion
682
- //#region node_modules/lib0/object.js
691
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/trait/equality.js
692
+ const EqualityTraitSymbol = Symbol("Equality");
693
+
694
+ //#endregion
695
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/object.js
683
696
  /**
684
697
  * @param {Object<string,any>} obj
685
698
  */
686
699
  const keys = Object.keys;
687
700
  /**
688
- * @deprecated use object.size instead
689
701
  * @param {Object<string,any>} obj
690
702
  * @return {number}
691
703
  */
692
- const length = (obj) => keys(obj).length;
704
+ const size = (obj) => keys(obj).length;
693
705
  /**
694
706
  * Calls `Object.prototype.hasOwnProperty`.
695
707
  *
696
708
  * @param {any} obj
697
- * @param {string|symbol} key
709
+ * @param {string|number|symbol} key
698
710
  * @return {boolean}
699
711
  */
700
712
  const hasProperty = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
701
713
 
702
714
  //#endregion
703
- //#region node_modules/lib0/function.js
715
+ //#region node_modules/.pnpm/lib0@0.2.117/node_modules/lib0/function.js
704
716
  /**
705
717
  * Common functions and function call helpers.
706
718
  *
707
719
  * @module function
708
720
  */
709
- /**
710
- * @template T
711
- *
712
- * @param {T} a
713
- * @param {T} b
714
- * @return {boolean}
715
- */
716
- const equalityStrict = (a, b) => a === b;
717
721
  /* c8 ignore start */
718
722
  /**
719
723
  * @param {any} a
@@ -721,9 +725,9 @@ const equalityStrict = (a, b) => a === b;
721
725
  * @return {boolean}
722
726
  */
723
727
  const equalityDeep = (a, b) => {
724
- if (a == null || b == null) return equalityStrict(a, b);
725
- if (a.constructor !== b.constructor) return false;
726
728
  if (a === b) return true;
729
+ if (a == null || b == null || a.constructor !== b.constructor && (a.constructor || Object) !== (b.constructor || Object)) return false;
730
+ if (a[EqualityTraitSymbol] != null) return a[EqualityTraitSymbol](b);
727
731
  switch (a.constructor) {
728
732
  case ArrayBuffer:
729
733
  a = new Uint8Array(a);
@@ -740,8 +744,9 @@ const equalityDeep = (a, b) => {
740
744
  if (a.size !== b.size) return false;
741
745
  for (const key of a.keys()) if (!b.has(key) || !equalityDeep(a.get(key), b.get(key))) return false;
742
746
  break;
747
+ case void 0:
743
748
  case Object:
744
- if (length(a) !== length(b)) return false;
749
+ if (size(a) !== size(b)) return false;
745
750
  for (const key in a) if (!hasProperty(a, key) || !equalityDeep(a[key], b[key])) return false;
746
751
  break;
747
752
  case Array:
@@ -756,7 +761,7 @@ const equalityDeep = (a, b) => {
756
761
  const isArray = isArray$1;
757
762
 
758
763
  //#endregion
759
- //#region node_modules/y-protocols/awareness.js
764
+ //#region node_modules/.pnpm/y-protocols@1.0.7_yjs@13.6.29/node_modules/y-protocols/awareness.js
760
765
  /**
761
766
  * @module awareness-protocol
762
767
  */
@@ -1048,7 +1053,7 @@ var IncomingMessage = class {
1048
1053
  return writeVarUint8Array(this.encoder, data);
1049
1054
  }
1050
1055
  length() {
1051
- return length$1(this.encoder);
1056
+ return length(this.encoder);
1052
1057
  }
1053
1058
  };
1054
1059
 
@@ -1062,6 +1067,8 @@ let MessageType = /* @__PURE__ */ function(MessageType) {
1062
1067
  MessageType[MessageType["Stateless"] = 5] = "Stateless";
1063
1068
  MessageType[MessageType["CLOSE"] = 7] = "CLOSE";
1064
1069
  MessageType[MessageType["SyncStatus"] = 8] = "SyncStatus";
1070
+ MessageType[MessageType["Ping"] = 9] = "Ping";
1071
+ MessageType[MessageType["Pong"] = 10] = "Pong";
1065
1072
  return MessageType;
1066
1073
  }({});
1067
1074
  let WebSocketStatus = /* @__PURE__ */ function(WebSocketStatus) {
@@ -1102,7 +1109,10 @@ var CloseMessage = class extends OutgoingMessage {
1102
1109
 
1103
1110
  //#endregion
1104
1111
  //#region packages/provider/src/HocuspocusProviderWebsocket.ts
1105
- var HocuspocusProviderWebsocket = class extends EventEmitter {
1112
+ var HocuspocusProviderWebsocket = class HocuspocusProviderWebsocket extends EventEmitter {
1113
+ static {
1114
+ this.DEDUPLICATABLE_TYPES = new Set([MessageType.Awareness, MessageType.QueryAwareness]);
1115
+ }
1106
1116
  constructor(configuration) {
1107
1117
  super();
1108
1118
  this.messageQueue = [];
@@ -1169,14 +1179,20 @@ var HocuspocusProviderWebsocket = class extends EventEmitter {
1169
1179
  this.receivedOnOpenPayload = event;
1170
1180
  }
1171
1181
  attach(provider) {
1172
- this.configuration.providerMap.set(provider.configuration.name, provider);
1182
+ const key = provider.effectiveName;
1183
+ const existing = this.configuration.providerMap.get(key);
1184
+ if (existing && existing !== provider) {
1185
+ if (existing.isAuthenticated) throw new Error(`Cannot attach two providers with the same effective name "${key}". Use sessionAwareness: true to multiplex providers with the same document name.`);
1186
+ }
1187
+ this.configuration.providerMap.set(key, provider);
1173
1188
  if (this.status === WebSocketStatus.Disconnected && this.shouldConnect) this.connect();
1174
1189
  if (this.receivedOnOpenPayload && this.status === WebSocketStatus.Connected) provider.onOpen(this.receivedOnOpenPayload);
1175
1190
  }
1176
1191
  detach(provider) {
1177
- if (this.configuration.providerMap.has(provider.configuration.name)) {
1178
- provider.send(CloseMessage, { documentName: provider.configuration.name });
1179
- this.configuration.providerMap.delete(provider.configuration.name);
1192
+ const key = provider.effectiveName;
1193
+ if (this.configuration.providerMap.has(key)) {
1194
+ provider.send(CloseMessage, { documentName: key });
1195
+ this.configuration.providerMap.delete(key);
1180
1196
  }
1181
1197
  }
1182
1198
  setConfiguration(configuration = {}) {
@@ -1276,8 +1292,21 @@ var HocuspocusProviderWebsocket = class extends EventEmitter {
1276
1292
  onMessage(event) {
1277
1293
  this.resolveConnectionAttempt();
1278
1294
  this.lastMessageReceived = getUnixTime();
1279
- const documentName = new IncomingMessage(event.data).peekVarString();
1280
- this.configuration.providerMap.get(documentName)?.onMessage(event);
1295
+ const data = new Uint8Array(event.data);
1296
+ if (data.length === 1 && data[0] === MessageType.Ping) {
1297
+ this.sendPong();
1298
+ return;
1299
+ }
1300
+ const rawKey = new IncomingMessage(data).peekVarString();
1301
+ this.configuration.providerMap.get(rawKey)?.onMessage(event);
1302
+ }
1303
+ /**
1304
+ * Send application-level Pong response to server Ping
1305
+ */
1306
+ sendPong() {
1307
+ const encoder = createEncoder();
1308
+ writeVarUint(encoder, MessageType.Pong);
1309
+ this.send(toUint8Array(encoder));
1281
1310
  }
1282
1311
  resolveConnectionAttempt() {
1283
1312
  if (this.connectionAttempt) {
@@ -1332,9 +1361,32 @@ var HocuspocusProviderWebsocket = class extends EventEmitter {
1332
1361
  console.error(e);
1333
1362
  }
1334
1363
  }
1364
+ parseQueuedMessage(message) {
1365
+ try {
1366
+ const decoder = createDecoder(message);
1367
+ return {
1368
+ documentName: readVarString(decoder),
1369
+ messageType: readVarUint(decoder)
1370
+ };
1371
+ } catch {
1372
+ return null;
1373
+ }
1374
+ }
1375
+ addToQueue(message) {
1376
+ if (message instanceof Uint8Array) {
1377
+ const parsed = this.parseQueuedMessage(message);
1378
+ if (parsed && HocuspocusProviderWebsocket.DEDUPLICATABLE_TYPES.has(parsed.messageType)) this.messageQueue = this.messageQueue.filter((queued) => {
1379
+ if (!(queued instanceof Uint8Array)) return true;
1380
+ const queuedParsed = this.parseQueuedMessage(queued);
1381
+ if (!queuedParsed) return true;
1382
+ return !(queuedParsed.documentName === parsed.documentName && queuedParsed.messageType === parsed.messageType);
1383
+ });
1384
+ }
1385
+ this.messageQueue.push(message);
1386
+ }
1335
1387
  send(message) {
1336
1388
  if (this.webSocket?.readyState === WsReadyStates.Open) this.webSocket.send(message);
1337
- else this.messageQueue.push(message);
1389
+ else this.addToQueue(message);
1338
1390
  }
1339
1391
  onClose({ event }) {
1340
1392
  this.closeTries = 0;
@@ -1358,7 +1410,7 @@ var HocuspocusProviderWebsocket = class extends EventEmitter {
1358
1410
  };
1359
1411
 
1360
1412
  //#endregion
1361
- //#region node_modules/y-protocols/sync.js
1413
+ //#region node_modules/.pnpm/y-protocols@1.0.7_yjs@13.6.29/node_modules/y-protocols/sync.js
1362
1414
  /**
1363
1415
  * @module sync-protocol
1364
1416
  */
@@ -1426,11 +1478,13 @@ const readSyncStep1 = (decoder, encoder, doc) => writeSyncStep2(encoder, doc, re
1426
1478
  * @param {decoding.Decoder} decoder
1427
1479
  * @param {Y.Doc} doc
1428
1480
  * @param {any} transactionOrigin
1481
+ * @param {(error:Error)=>any} [errorHandler]
1429
1482
  */
1430
- const readSyncStep2 = (decoder, doc, transactionOrigin) => {
1483
+ const readSyncStep2 = (decoder, doc, transactionOrigin, errorHandler) => {
1431
1484
  try {
1432
1485
  Y.applyUpdate(doc, readVarUint8Array(decoder), transactionOrigin);
1433
1486
  } catch (error) {
1487
+ if (errorHandler != null) errorHandler(error);
1434
1488
  console.error("Caught error while handling a Yjs update", error);
1435
1489
  }
1436
1490
  };
@@ -1448,6 +1502,7 @@ const writeUpdate = (encoder, update) => {
1448
1502
  * @param {decoding.Decoder} decoder
1449
1503
  * @param {Y.Doc} doc
1450
1504
  * @param {any} transactionOrigin
1505
+ * @param {(error:Error)=>any} [errorHandler]
1451
1506
  */
1452
1507
  const readUpdate = readSyncStep2;
1453
1508
  /**
@@ -1455,18 +1510,19 @@ const readUpdate = readSyncStep2;
1455
1510
  * @param {encoding.Encoder} encoder The reply message. Does not need to be sent if empty.
1456
1511
  * @param {Y.Doc} doc
1457
1512
  * @param {any} transactionOrigin
1513
+ * @param {(error:Error)=>any} [errorHandler] Optional error handler that catches errors when reading Yjs messages.
1458
1514
  */
1459
- const readSyncMessage = (decoder, encoder, doc, transactionOrigin) => {
1515
+ const readSyncMessage = (decoder, encoder, doc, transactionOrigin, errorHandler) => {
1460
1516
  const messageType = readVarUint(decoder);
1461
1517
  switch (messageType) {
1462
1518
  case messageYjsSyncStep1:
1463
1519
  readSyncStep1(decoder, encoder, doc);
1464
1520
  break;
1465
1521
  case messageYjsSyncStep2:
1466
- readSyncStep2(decoder, doc, transactionOrigin);
1522
+ readSyncStep2(decoder, doc, transactionOrigin, errorHandler);
1467
1523
  break;
1468
1524
  case messageYjsUpdate:
1469
- readUpdate(decoder, doc, transactionOrigin);
1525
+ readUpdate(decoder, doc, transactionOrigin, errorHandler);
1470
1526
  break;
1471
1527
  default: throw new Error("Unknown message type");
1472
1528
  }
@@ -1505,15 +1561,13 @@ var MessageReceiver = class {
1505
1561
  case MessageType.CLOSE:
1506
1562
  const event = {
1507
1563
  code: 1e3,
1508
- reason: readVarString(message.decoder),
1509
- target: provider.configuration.websocketProvider.webSocket,
1510
- type: "close"
1564
+ reason: readVarString(message.decoder)
1511
1565
  };
1512
1566
  provider.onClose();
1513
1567
  provider.configuration.onClose({ event });
1514
1568
  provider.forwardClose({ event });
1515
1569
  break;
1516
- default: throw new Error(`Can’t apply message of unknown type: ${type}`);
1570
+ default: console.error(`Can’t apply message of unknown type: ${type}`);
1517
1571
  }
1518
1572
  if (message.length() > emptyMessageLength + 1) provider.send(OutgoingMessage, { encoder: message.encoder });
1519
1573
  }
@@ -1558,6 +1612,10 @@ var MessageSender = class {
1558
1612
  }
1559
1613
  };
1560
1614
 
1615
+ //#endregion
1616
+ //#region packages/provider/src/version.ts
1617
+ const version = "4.0.0-rc.1";
1618
+
1561
1619
  //#endregion
1562
1620
  //#region packages/provider/src/OutgoingMessages/AuthenticationMessage.ts
1563
1621
  var AuthenticationMessage = class extends OutgoingMessage {
@@ -1571,6 +1629,7 @@ var AuthenticationMessage = class extends OutgoingMessage {
1571
1629
  writeVarString(this.encoder, args.documentName);
1572
1630
  writeVarUint(this.encoder, this.type);
1573
1631
  writeAuthentication(this.encoder, args.token);
1632
+ writeVarString(this.encoder, version);
1574
1633
  return this.encoder;
1575
1634
  }
1576
1635
  };
@@ -1654,6 +1713,14 @@ var AwarenessError = class extends Error {
1654
1713
  }
1655
1714
  };
1656
1715
  var HocuspocusProvider = class extends EventEmitter {
1716
+ /**
1717
+ * The effective name used as the first VarString in messages.
1718
+ * When `sessionAwareness` is enabled, returns a composite key (documentName\0sessionId).
1719
+ * Otherwise, returns the plain document name.
1720
+ */
1721
+ get effectiveName() {
1722
+ return this.configuration.sessionAwareness ? makeRoutingKey(this.configuration.name, this.sessionId) : this.configuration.name;
1723
+ }
1657
1724
  constructor(configuration) {
1658
1725
  super();
1659
1726
  this.configuration = {
@@ -1661,6 +1728,7 @@ var HocuspocusProvider = class extends EventEmitter {
1661
1728
  document: void 0,
1662
1729
  awareness: void 0,
1663
1730
  token: null,
1731
+ sessionAwareness: true,
1664
1732
  forceSyncInterval: false,
1665
1733
  onAuthenticated: () => null,
1666
1734
  onAuthenticationFailed: () => null,
@@ -1684,6 +1752,7 @@ var HocuspocusProvider = class extends EventEmitter {
1684
1752
  this.authorizedScope = void 0;
1685
1753
  this.manageSocket = false;
1686
1754
  this._isAttached = false;
1755
+ this.sessionId = Math.random().toString(36).slice(2);
1687
1756
  this.intervals = { forceSync: null };
1688
1757
  this.boundDocumentUpdateHandler = this.documentUpdateHandler.bind(this);
1689
1758
  this.boundAwarenessUpdateHandler = this.awarenessUpdateHandler.bind(this);
@@ -1760,7 +1829,7 @@ var HocuspocusProvider = class extends EventEmitter {
1760
1829
  this.resetUnsyncedChanges();
1761
1830
  this.send(SyncStepOneMessage, {
1762
1831
  document: this.document,
1763
- documentName: this.configuration.name
1832
+ documentName: this.effectiveName
1764
1833
  });
1765
1834
  }
1766
1835
  pageHide() {
@@ -1772,7 +1841,7 @@ var HocuspocusProvider = class extends EventEmitter {
1772
1841
  }
1773
1842
  sendStateless(payload) {
1774
1843
  this.send(StatelessMessage, {
1775
- documentName: this.configuration.name,
1844
+ documentName: this.effectiveName,
1776
1845
  payload
1777
1846
  });
1778
1847
  }
@@ -1786,7 +1855,7 @@ var HocuspocusProvider = class extends EventEmitter {
1786
1855
  }
1787
1856
  this.send(AuthenticationMessage, {
1788
1857
  token: token ?? "",
1789
- documentName: this.configuration.name
1858
+ documentName: this.effectiveName
1790
1859
  });
1791
1860
  }
1792
1861
  documentUpdateHandler(update, origin) {
@@ -1794,7 +1863,7 @@ var HocuspocusProvider = class extends EventEmitter {
1794
1863
  this.incrementUnsyncedChanges();
1795
1864
  this.send(UpdateMessage, {
1796
1865
  update,
1797
- documentName: this.configuration.name
1866
+ documentName: this.effectiveName
1798
1867
  });
1799
1868
  }
1800
1869
  awarenessUpdateHandler({ added, updated, removed }, origin) {
@@ -1802,7 +1871,7 @@ var HocuspocusProvider = class extends EventEmitter {
1802
1871
  this.send(AwarenessMessage, {
1803
1872
  awareness: this.awareness,
1804
1873
  clients: changedClients,
1805
- documentName: this.configuration.name
1874
+ documentName: this.effectiveName
1806
1875
  });
1807
1876
  }
1808
1877
  /**
@@ -1844,12 +1913,12 @@ var HocuspocusProvider = class extends EventEmitter {
1844
1913
  this.resetUnsyncedChanges();
1845
1914
  this.send(SyncStepOneMessage, {
1846
1915
  document: this.document,
1847
- documentName: this.configuration.name
1916
+ documentName: this.effectiveName
1848
1917
  });
1849
1918
  if (this.awareness && this.awareness.getLocalState() !== null) this.send(AwarenessMessage, {
1850
1919
  awareness: this.awareness,
1851
1920
  clients: [this.document.clientID],
1852
- documentName: this.configuration.name
1921
+ documentName: this.effectiveName
1853
1922
  });
1854
1923
  }
1855
1924
  send(message, args) {
@@ -1860,8 +1929,8 @@ var HocuspocusProvider = class extends EventEmitter {
1860
1929
  }
1861
1930
  onMessage(event) {
1862
1931
  const message = new IncomingMessage(event.data);
1863
- const documentName = message.readVarString();
1864
- message.writeVarString(documentName);
1932
+ const { documentName } = parseRoutingKey(message.readVarString());
1933
+ message.writeVarString(this.effectiveName);
1865
1934
  this.emit("message", {
1866
1935
  event,
1867
1936
  message: new IncomingMessage(event.data)