@hocuspocus/provider 1.0.0-alpha.9 → 1.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hocuspocus-provider.cjs +374 -186
- package/dist/hocuspocus-provider.cjs.map +1 -1
- package/dist/hocuspocus-provider.esm.js +372 -182
- package/dist/hocuspocus-provider.esm.js.map +1 -1
- package/dist/packages/common/src/CloseEvents.d.ts +23 -0
- package/dist/packages/common/src/auth.d.ts +6 -0
- package/dist/packages/common/src/awarenessStatesToArray.d.ts +3 -0
- package/dist/packages/common/src/index.d.ts +4 -0
- package/dist/packages/common/src/types.d.ts +10 -0
- package/dist/packages/extension-database/src/Database.d.ts +30 -0
- package/dist/packages/extension-database/src/index.d.ts +1 -0
- package/dist/packages/extension-logger/src/Logger.d.ts +67 -0
- package/dist/packages/extension-logger/src/index.d.ts +1 -0
- package/dist/packages/{monitor → extension-monitor}/src/Collector.d.ts +4 -5
- package/dist/packages/{monitor → extension-monitor}/src/Dashboard.d.ts +2 -2
- package/dist/packages/{monitor → extension-monitor}/src/Storage.d.ts +0 -0
- package/dist/packages/{monitor → extension-monitor}/src/index.d.ts +3 -5
- package/dist/packages/extension-redis/src/Redis.d.ts +98 -0
- package/dist/packages/extension-redis/src/index.d.ts +1 -0
- package/dist/packages/extension-sqlite/src/SQLite.d.ts +26 -0
- package/dist/packages/extension-sqlite/src/index.d.ts +1 -0
- package/dist/packages/extension-throttle/src/index.d.ts +24 -0
- package/dist/packages/{webhook → extension-webhook}/src/index.d.ts +5 -11
- package/dist/packages/provider/src/EventEmitter.d.ts +1 -1
- package/dist/packages/provider/src/HocuspocusCloudProvider.d.ts +11 -0
- package/dist/packages/provider/src/HocuspocusProvider.d.ts +116 -33
- package/dist/packages/provider/src/IncomingMessage.d.ts +9 -6
- package/dist/packages/provider/src/MessageReceiver.d.ts +3 -2
- package/dist/packages/provider/src/MessageSender.d.ts +4 -9
- package/dist/packages/provider/src/OutgoingMessage.d.ts +5 -4
- package/dist/packages/provider/src/OutgoingMessages/AuthenticationMessage.d.ts +7 -0
- package/dist/packages/provider/src/OutgoingMessages/UpdateMessage.d.ts +1 -2
- package/dist/packages/provider/src/index.d.ts +1 -1
- package/dist/packages/provider/src/types.d.ts +54 -2
- package/dist/packages/server/src/Connection.d.ts +27 -7
- package/dist/packages/server/src/Debugger.d.ts +14 -0
- package/dist/packages/server/src/Document.d.ts +11 -5
- package/dist/packages/server/src/Hocuspocus.d.ts +63 -17
- package/dist/packages/server/src/IncomingMessage.d.ts +11 -7
- package/dist/packages/server/src/MessageReceiver.d.ts +13 -0
- package/dist/packages/server/src/OutgoingMessage.d.ts +6 -0
- package/dist/packages/server/src/index.d.ts +6 -0
- package/dist/packages/server/src/types.d.ts +180 -26
- package/dist/{demos/backend/src/create-document.d.ts → playground/backend/src/default.d.ts} +0 -0
- package/dist/{demos → playground}/backend/src/express.d.ts +0 -0
- package/dist/{demos → playground}/backend/src/koa.d.ts +0 -0
- package/dist/{demos/backend/src/minimal.d.ts → playground/backend/src/load-document.d.ts} +0 -0
- package/dist/{demos → playground}/backend/src/monitor.d.ts +0 -0
- package/dist/{demos → playground}/backend/src/redis.d.ts +0 -0
- package/dist/{demos → playground}/backend/src/slow.d.ts +0 -0
- package/dist/{demos → playground}/backend/src/webhook.d.ts +0 -0
- package/dist/tests/extension-database/fetch.d.ts +1 -0
- package/dist/tests/extension-logger/onListen.d.ts +1 -0
- package/dist/tests/extension-redis/closeConnections.d.ts +1 -0
- package/dist/tests/extension-redis/getConnectionCount.d.ts +1 -0
- package/dist/tests/extension-redis/getDocumentsCount.d.ts +1 -0
- package/dist/tests/extension-redis/onAwarenessChange.d.ts +1 -0
- package/dist/tests/extension-redis/onChange.d.ts +1 -0
- package/dist/tests/extension-redis/onStoreDocument.d.ts +1 -0
- package/dist/tests/extension-throttle/configuration.d.ts +1 -0
- package/dist/tests/provider/configuration.d.ts +1 -0
- package/dist/tests/provider/observe.d.ts +1 -0
- package/dist/tests/provider/observeDeep.d.ts +1 -0
- package/dist/tests/provider/onAuthenticated.d.ts +1 -0
- package/dist/tests/provider/onAuthenticationFailed.d.ts +1 -0
- package/dist/tests/provider/onAwarenessChange.d.ts +1 -0
- package/dist/tests/provider/onAwarenessUpdate.d.ts +1 -0
- package/dist/tests/provider/onClose.d.ts +1 -0
- package/dist/tests/provider/onConnect.d.ts +1 -0
- package/dist/tests/provider/onDisconnect.d.ts +1 -0
- package/dist/tests/provider/onMessage.d.ts +1 -0
- package/dist/tests/provider/onOpen.d.ts +1 -0
- package/dist/tests/provider/onSynced.d.ts +1 -0
- package/dist/tests/server/address.d.ts +1 -0
- package/dist/tests/server/afterStoreDocument.d.ts +1 -0
- package/dist/tests/server/beforeHandleMessage.d.ts +1 -0
- package/dist/tests/server/closeConnections.d.ts +1 -0
- package/dist/tests/server/getConnectionsCount.d.ts +1 -0
- package/dist/tests/server/getDocumentName.d.ts +1 -0
- package/dist/tests/server/getDocumentsCount.d.ts +1 -0
- package/dist/tests/server/getMessageLogs.d.ts +1 -0
- package/dist/tests/server/listen.d.ts +1 -0
- package/dist/tests/server/onAuthenticate.d.ts +1 -0
- package/dist/tests/server/onAwarenessUpdate.d.ts +1 -0
- package/dist/tests/server/onChange.d.ts +1 -0
- package/dist/tests/server/onConfigure.d.ts +1 -0
- package/dist/tests/server/onConnect.d.ts +1 -0
- package/dist/tests/server/onDestroy.d.ts +1 -0
- package/dist/tests/server/onDisconnect.d.ts +1 -0
- package/dist/tests/server/onListen.d.ts +1 -0
- package/dist/tests/server/onLoadDocument.d.ts +1 -0
- package/dist/tests/server/onRequest.d.ts +1 -0
- package/dist/tests/server/onStoreDocument.d.ts +1 -0
- package/dist/tests/server/onUpgrade.d.ts +1 -0
- package/dist/tests/server/requiresAuthentication.d.ts +1 -0
- package/dist/tests/server/websocketError.d.ts +1 -0
- package/dist/tests/transformer/TiptapTransformer.d.ts +1 -0
- package/dist/tests/utils/createDirectory.d.ts +1 -0
- package/dist/tests/utils/flushRedis.d.ts +1 -0
- package/dist/tests/utils/index.d.ts +8 -0
- package/dist/tests/utils/newHocuspocus.d.ts +2 -0
- package/dist/tests/utils/newHocuspocusProvider.d.ts +3 -0
- package/dist/tests/utils/randomInteger.d.ts +1 -0
- package/dist/tests/utils/redisConnectionSettings.d.ts +4 -0
- package/dist/tests/utils/removeDirectory.d.ts +1 -0
- package/dist/tests/utils/retryableAssertion.d.ts +2 -0
- package/dist/tests/utils/sleep.d.ts +1 -0
- package/package.json +14 -10
- package/src/EventEmitter.ts +1 -1
- package/src/HocuspocusCloudProvider.ts +34 -0
- package/src/HocuspocusProvider.ts +410 -162
- package/src/IncomingMessage.ts +35 -11
- package/src/MessageReceiver.ts +56 -24
- package/src/MessageSender.ts +5 -17
- package/src/OutgoingMessage.ts +9 -9
- package/src/OutgoingMessages/AuthenticationMessage.ts +21 -0
- package/src/OutgoingMessages/AwarenessMessage.ts +1 -1
- package/src/OutgoingMessages/SyncStepOneMessage.ts +0 -1
- package/src/OutgoingMessages/UpdateMessage.ts +4 -4
- package/src/index.ts +1 -1
- package/src/types.ts +70 -3
- package/CHANGELOG.md +0 -64
- package/LICENSE.md +0 -21
- package/dist/packages/logger/src/index.d.ts +0 -13
- package/dist/packages/provider/src/utils/awarenessStatesToArray.d.ts +0 -4
- package/dist/packages/provider/src/utils/index.d.ts +0 -1
- package/dist/packages/redis/src/Redis.d.ts +0 -22
- package/dist/packages/redis/src/RedisCluster.d.ts +0 -4
- package/dist/packages/redis/src/index.d.ts +0 -2
- package/dist/packages/rocksdb/src/index.d.ts +0 -30
- package/dist/packages/server/src/CloseEvents.d.ts +0 -3
- package/dist/packages/throttle/src/index.d.ts +0 -28
- package/src/utils/awarenessStatesToArray.ts +0 -8
- package/src/utils/index.ts +0 -1
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var Y = require('yjs');
|
|
6
|
+
var attempt = require('@lifeomic/attempt');
|
|
7
|
+
var common = require('@hocuspocus/common');
|
|
6
8
|
|
|
7
9
|
function _interopNamespace(e) {
|
|
8
10
|
if (e && e.__esModule) return e;
|
|
@@ -13,14 +15,12 @@ function _interopNamespace(e) {
|
|
|
13
15
|
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
16
|
Object.defineProperty(n, k, d.get ? d : {
|
|
15
17
|
enumerable: true,
|
|
16
|
-
get: function () {
|
|
17
|
-
return e[k];
|
|
18
|
-
}
|
|
18
|
+
get: function () { return e[k]; }
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
|
-
n[
|
|
23
|
+
n["default"] = e;
|
|
24
24
|
return Object.freeze(n);
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -284,8 +284,6 @@ hasConf('production');
|
|
|
284
284
|
*/
|
|
285
285
|
|
|
286
286
|
const floor = Math.floor;
|
|
287
|
-
const round = Math.round;
|
|
288
|
-
const log10 = Math.log10;
|
|
289
287
|
|
|
290
288
|
/**
|
|
291
289
|
* @function
|
|
@@ -1398,23 +1396,26 @@ class EventEmitter {
|
|
|
1398
1396
|
}
|
|
1399
1397
|
}
|
|
1400
1398
|
|
|
1401
|
-
exports.MessageType = void 0;
|
|
1402
|
-
(function (MessageType) {
|
|
1403
|
-
MessageType[MessageType["Sync"] = 0] = "Sync";
|
|
1404
|
-
MessageType[MessageType["Awareness"] = 1] = "Awareness";
|
|
1405
|
-
MessageType[MessageType["Auth"] = 2] = "Auth";
|
|
1406
|
-
MessageType[MessageType["QueryAwareness"] = 3] = "QueryAwareness";
|
|
1407
|
-
})(exports.MessageType || (exports.MessageType = {}));
|
|
1408
|
-
|
|
1409
1399
|
class IncomingMessage {
|
|
1410
1400
|
constructor(data) {
|
|
1411
1401
|
this.data = data;
|
|
1412
1402
|
this.encoder = createEncoder();
|
|
1413
1403
|
this.decoder = createDecoder(new Uint8Array(this.data));
|
|
1414
|
-
this.type = readVarUint(this.decoder);
|
|
1415
1404
|
}
|
|
1416
|
-
|
|
1417
|
-
return
|
|
1405
|
+
readVarUint() {
|
|
1406
|
+
return readVarUint(this.decoder);
|
|
1407
|
+
}
|
|
1408
|
+
readVarUint8Array() {
|
|
1409
|
+
return readVarUint8Array(this.decoder);
|
|
1410
|
+
}
|
|
1411
|
+
writeVarUint(type) {
|
|
1412
|
+
return writeVarUint(this.encoder, type);
|
|
1413
|
+
}
|
|
1414
|
+
writeVarUint8Array(data) {
|
|
1415
|
+
return writeVarUint8Array(this.encoder, data);
|
|
1416
|
+
}
|
|
1417
|
+
length() {
|
|
1418
|
+
return length$1(this.encoder);
|
|
1418
1419
|
}
|
|
1419
1420
|
}
|
|
1420
1421
|
|
|
@@ -1545,32 +1546,45 @@ const readSyncMessage = (decoder, encoder, doc, transactionOrigin) => {
|
|
|
1545
1546
|
return messageType
|
|
1546
1547
|
};
|
|
1547
1548
|
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1549
|
+
exports.MessageType = void 0;
|
|
1550
|
+
(function (MessageType) {
|
|
1551
|
+
MessageType[MessageType["Sync"] = 0] = "Sync";
|
|
1552
|
+
MessageType[MessageType["Awareness"] = 1] = "Awareness";
|
|
1553
|
+
MessageType[MessageType["Auth"] = 2] = "Auth";
|
|
1554
|
+
MessageType[MessageType["QueryAwareness"] = 3] = "QueryAwareness";
|
|
1555
|
+
})(exports.MessageType || (exports.MessageType = {}));
|
|
1556
|
+
exports.WebSocketStatus = void 0;
|
|
1557
|
+
(function (WebSocketStatus) {
|
|
1558
|
+
WebSocketStatus["Connecting"] = "connecting";
|
|
1559
|
+
WebSocketStatus["Connected"] = "connected";
|
|
1560
|
+
WebSocketStatus["Disconnected"] = "disconnected";
|
|
1561
|
+
})(exports.WebSocketStatus || (exports.WebSocketStatus = {}));
|
|
1555
1562
|
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
}
|
|
1563
|
+
class OutgoingMessage {
|
|
1564
|
+
constructor() {
|
|
1565
|
+
this.encoder = createEncoder();
|
|
1566
|
+
}
|
|
1567
|
+
get(args) {
|
|
1568
|
+
return args.encoder;
|
|
1569
|
+
}
|
|
1570
|
+
toUint8Array() {
|
|
1571
|
+
return toUint8Array(this.encoder);
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1567
1574
|
|
|
1568
1575
|
class MessageReceiver {
|
|
1569
1576
|
constructor(message) {
|
|
1577
|
+
this.broadcasted = false;
|
|
1570
1578
|
this.message = message;
|
|
1571
1579
|
}
|
|
1580
|
+
setBroadcasted(value) {
|
|
1581
|
+
this.broadcasted = value;
|
|
1582
|
+
return this;
|
|
1583
|
+
}
|
|
1572
1584
|
apply(provider, emitSynced = true) {
|
|
1573
|
-
|
|
1585
|
+
const { message } = this;
|
|
1586
|
+
const type = message.readVarUint();
|
|
1587
|
+
switch (type) {
|
|
1574
1588
|
case exports.MessageType.Sync:
|
|
1575
1589
|
this.applySyncMessage(provider, emitSynced);
|
|
1576
1590
|
break;
|
|
@@ -1584,31 +1598,49 @@ class MessageReceiver {
|
|
|
1584
1598
|
this.applyQueryAwarenessMessage(provider);
|
|
1585
1599
|
break;
|
|
1586
1600
|
default:
|
|
1587
|
-
throw new Error(`Can’t apply unknown type
|
|
1601
|
+
throw new Error(`Can’t apply message of unknown type: ${type}`);
|
|
1602
|
+
}
|
|
1603
|
+
// Reply
|
|
1604
|
+
if (message.length() > 1) {
|
|
1605
|
+
if (this.broadcasted) {
|
|
1606
|
+
// TODO: Some weird TypeScript error
|
|
1607
|
+
// @ts-ignore
|
|
1608
|
+
provider.broadcast(OutgoingMessage, { encoder: message.encoder });
|
|
1609
|
+
}
|
|
1610
|
+
else {
|
|
1611
|
+
// TODO: Some weird TypeScript error
|
|
1612
|
+
// @ts-ignore
|
|
1613
|
+
provider.send(OutgoingMessage, { encoder: message.encoder });
|
|
1614
|
+
}
|
|
1588
1615
|
}
|
|
1589
|
-
return this.message.encoder;
|
|
1590
1616
|
}
|
|
1591
1617
|
applySyncMessage(provider, emitSynced) {
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1618
|
+
const { message } = this;
|
|
1619
|
+
message.writeVarUint(exports.MessageType.Sync);
|
|
1620
|
+
// Apply update
|
|
1621
|
+
const syncMessageType = readSyncMessage(message.decoder, message.encoder, provider.document, provider);
|
|
1622
|
+
// Synced once we receive Step2
|
|
1623
|
+
if (emitSynced && (syncMessageType === messageYjsSyncStep2)) {
|
|
1595
1624
|
provider.synced = true;
|
|
1596
1625
|
}
|
|
1626
|
+
if (syncMessageType === messageYjsUpdate || syncMessageType === messageYjsSyncStep2) {
|
|
1627
|
+
if (provider.unsyncedChanges > 0) {
|
|
1628
|
+
provider.unsyncedChanges -= 1;
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1597
1631
|
}
|
|
1598
1632
|
applyAwarenessMessage(provider) {
|
|
1599
|
-
|
|
1633
|
+
const { message } = this;
|
|
1634
|
+
applyAwarenessUpdate(provider.awareness, message.readVarUint8Array(), provider);
|
|
1600
1635
|
}
|
|
1601
|
-
// TODO: This isn’t really used. Needs to be implemented in the server, or removed here.
|
|
1602
1636
|
applyAuthMessage(provider) {
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
(provider, reason) => {
|
|
1606
|
-
console.warn(`Permission denied to access ${provider.url}.\n${reason}`);
|
|
1607
|
-
});
|
|
1637
|
+
const { message } = this;
|
|
1638
|
+
common.readAuthMessage(message.decoder, provider.permissionDeniedHandler.bind(provider), provider.authenticatedHandler.bind(provider));
|
|
1608
1639
|
}
|
|
1609
1640
|
applyQueryAwarenessMessage(provider) {
|
|
1610
|
-
|
|
1611
|
-
|
|
1641
|
+
const { message } = this;
|
|
1642
|
+
message.writeVarUint(exports.MessageType.Awareness);
|
|
1643
|
+
message.writeVarUint8Array(encodeAwarenessUpdate(provider.awareness, Array.from(provider.awareness.getStates().keys())));
|
|
1612
1644
|
}
|
|
1613
1645
|
}
|
|
1614
1646
|
|
|
@@ -1628,18 +1660,6 @@ class MessageSender {
|
|
|
1628
1660
|
}
|
|
1629
1661
|
}
|
|
1630
1662
|
|
|
1631
|
-
class OutgoingMessage {
|
|
1632
|
-
constructor() {
|
|
1633
|
-
this.encoder = createEncoder();
|
|
1634
|
-
}
|
|
1635
|
-
get name() {
|
|
1636
|
-
if (typeof this.type === 'number') {
|
|
1637
|
-
return exports.MessageType[this.type];
|
|
1638
|
-
}
|
|
1639
|
-
throw new Error('Type for outgoing message not set.');
|
|
1640
|
-
}
|
|
1641
|
-
}
|
|
1642
|
-
|
|
1643
1663
|
class SyncStepOneMessage extends OutgoingMessage {
|
|
1644
1664
|
constructor() {
|
|
1645
1665
|
super(...arguments);
|
|
@@ -1684,6 +1704,22 @@ class QueryAwarenessMessage extends OutgoingMessage {
|
|
|
1684
1704
|
}
|
|
1685
1705
|
}
|
|
1686
1706
|
|
|
1707
|
+
class AuthenticationMessage extends OutgoingMessage {
|
|
1708
|
+
constructor() {
|
|
1709
|
+
super(...arguments);
|
|
1710
|
+
this.type = exports.MessageType.Auth;
|
|
1711
|
+
this.description = 'Authentication';
|
|
1712
|
+
}
|
|
1713
|
+
get(args) {
|
|
1714
|
+
if (typeof args.token === 'undefined') {
|
|
1715
|
+
throw new Error('The authentication message requires `token` as an argument.');
|
|
1716
|
+
}
|
|
1717
|
+
writeVarUint(this.encoder, this.type);
|
|
1718
|
+
common.writeAuthentication(this.encoder, args.token);
|
|
1719
|
+
return this.encoder;
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1687
1723
|
class AwarenessMessage extends OutgoingMessage {
|
|
1688
1724
|
constructor() {
|
|
1689
1725
|
super(...arguments);
|
|
@@ -1723,37 +1759,42 @@ class UpdateMessage extends OutgoingMessage {
|
|
|
1723
1759
|
}
|
|
1724
1760
|
}
|
|
1725
1761
|
|
|
1726
|
-
var awarenessStatesToArray = (states) => {
|
|
1727
|
-
return Array.from(states.entries()).map(([key, value]) => {
|
|
1728
|
-
return {
|
|
1729
|
-
clientId: key,
|
|
1730
|
-
...value,
|
|
1731
|
-
};
|
|
1732
|
-
});
|
|
1733
|
-
};
|
|
1734
|
-
|
|
1735
|
-
// @ts-nocheck
|
|
1736
|
-
exports.WebSocketStatus = void 0;
|
|
1737
|
-
(function (WebSocketStatus) {
|
|
1738
|
-
WebSocketStatus["Connecting"] = "connecting";
|
|
1739
|
-
WebSocketStatus["Connected"] = "connected";
|
|
1740
|
-
WebSocketStatus["Disconnected"] = "disconnected";
|
|
1741
|
-
})(exports.WebSocketStatus || (exports.WebSocketStatus = {}));
|
|
1742
1762
|
class HocuspocusProvider extends EventEmitter {
|
|
1743
|
-
constructor(
|
|
1763
|
+
constructor(configuration) {
|
|
1744
1764
|
super();
|
|
1745
|
-
this.
|
|
1746
|
-
url: '',
|
|
1765
|
+
this.configuration = {
|
|
1747
1766
|
name: '',
|
|
1767
|
+
url: '',
|
|
1768
|
+
// @ts-ignore
|
|
1769
|
+
document: undefined,
|
|
1770
|
+
// @ts-ignore
|
|
1771
|
+
awareness: undefined,
|
|
1772
|
+
WebSocketPolyfill: undefined,
|
|
1773
|
+
token: null,
|
|
1748
1774
|
parameters: {},
|
|
1749
|
-
debug: false,
|
|
1750
1775
|
connect: true,
|
|
1751
1776
|
broadcast: true,
|
|
1752
1777
|
forceSyncInterval: false,
|
|
1753
|
-
reconnectTimeoutBase: 1200,
|
|
1754
|
-
maxReconnectTimeout: 2500,
|
|
1755
1778
|
// TODO: this should depend on awareness.outdatedTime
|
|
1756
1779
|
messageReconnectTimeout: 30000,
|
|
1780
|
+
// 1 second
|
|
1781
|
+
delay: 1000,
|
|
1782
|
+
// instant
|
|
1783
|
+
initialDelay: 0,
|
|
1784
|
+
// double the delay each time
|
|
1785
|
+
factor: 2,
|
|
1786
|
+
// unlimited retries
|
|
1787
|
+
maxAttempts: 0,
|
|
1788
|
+
// wait at least 1 second
|
|
1789
|
+
minDelay: 1000,
|
|
1790
|
+
// at least every 30 seconds
|
|
1791
|
+
maxDelay: 30000,
|
|
1792
|
+
// randomize
|
|
1793
|
+
jitter: true,
|
|
1794
|
+
// retry forever
|
|
1795
|
+
timeout: 0,
|
|
1796
|
+
onAuthenticated: () => null,
|
|
1797
|
+
onAuthenticationFailed: () => null,
|
|
1757
1798
|
onOpen: () => null,
|
|
1758
1799
|
onConnect: () => null,
|
|
1759
1800
|
onMessage: () => null,
|
|
@@ -1763,70 +1804,183 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1763
1804
|
onDisconnect: () => null,
|
|
1764
1805
|
onClose: () => null,
|
|
1765
1806
|
onDestroy: () => null,
|
|
1807
|
+
onAwarenessUpdate: () => null,
|
|
1766
1808
|
onAwarenessChange: () => null,
|
|
1809
|
+
quiet: false,
|
|
1767
1810
|
};
|
|
1768
1811
|
this.subscribedToBroadcastChannel = false;
|
|
1769
1812
|
this.webSocket = null;
|
|
1770
1813
|
this.shouldConnect = true;
|
|
1771
1814
|
this.status = exports.WebSocketStatus.Disconnected;
|
|
1772
|
-
this.failedConnectionAttempts = 0;
|
|
1773
1815
|
this.isSynced = false;
|
|
1816
|
+
this.unsyncedChanges = 0;
|
|
1817
|
+
this.isAuthenticated = false;
|
|
1774
1818
|
this.lastMessageReceived = 0;
|
|
1775
1819
|
this.mux = createMutex();
|
|
1776
1820
|
this.intervals = {
|
|
1777
1821
|
forceSync: null,
|
|
1778
1822
|
connectionChecker: null,
|
|
1779
1823
|
};
|
|
1780
|
-
this.
|
|
1781
|
-
this.
|
|
1782
|
-
this.
|
|
1783
|
-
this.
|
|
1784
|
-
this.
|
|
1785
|
-
this.
|
|
1786
|
-
this.
|
|
1787
|
-
this.
|
|
1788
|
-
this.on('
|
|
1789
|
-
this.on('
|
|
1790
|
-
this.on('
|
|
1791
|
-
this.on('
|
|
1792
|
-
this.on('
|
|
1793
|
-
this.on('
|
|
1794
|
-
this.on('
|
|
1824
|
+
this.connectionAttempt = null;
|
|
1825
|
+
this.boundConnect = this.connect.bind(this);
|
|
1826
|
+
this.boundBeforeUnload = this.beforeUnload.bind(this);
|
|
1827
|
+
this.boundBroadcastChannelSubscriber = this.broadcastChannelSubscriber.bind(this);
|
|
1828
|
+
this.setConfiguration(configuration);
|
|
1829
|
+
this.configuration.document = configuration.document ? configuration.document : new Y__namespace.Doc();
|
|
1830
|
+
this.configuration.awareness = configuration.awareness ? configuration.awareness : new Awareness(this.document);
|
|
1831
|
+
this.configuration.WebSocketPolyfill = configuration.WebSocketPolyfill ? configuration.WebSocketPolyfill : WebSocket;
|
|
1832
|
+
this.on('open', this.configuration.onOpen);
|
|
1833
|
+
this.on('authenticated', this.configuration.onAuthenticated);
|
|
1834
|
+
this.on('authenticationFailed', this.configuration.onAuthenticationFailed);
|
|
1835
|
+
this.on('connect', this.configuration.onConnect);
|
|
1836
|
+
this.on('message', this.configuration.onMessage);
|
|
1837
|
+
this.on('outgoingMessage', this.configuration.onOutgoingMessage);
|
|
1838
|
+
this.on('synced', this.configuration.onSynced);
|
|
1839
|
+
this.on('status', this.configuration.onStatus);
|
|
1840
|
+
this.on('disconnect', this.configuration.onDisconnect);
|
|
1841
|
+
this.on('close', this.configuration.onClose);
|
|
1842
|
+
this.on('destroy', this.configuration.onDestroy);
|
|
1843
|
+
this.on('awarenessUpdate', this.configuration.onAwarenessUpdate);
|
|
1844
|
+
this.on('awarenessChange', this.configuration.onAwarenessChange);
|
|
1845
|
+
this.awareness.on('update', () => {
|
|
1846
|
+
this.emit('awarenessUpdate', { states: common.awarenessStatesToArray(this.awareness.getStates()) });
|
|
1847
|
+
});
|
|
1795
1848
|
this.awareness.on('change', () => {
|
|
1796
|
-
this.emit('awarenessChange', {
|
|
1797
|
-
states: awarenessStatesToArray(this.awareness.getStates()),
|
|
1798
|
-
});
|
|
1849
|
+
this.emit('awarenessChange', { states: common.awarenessStatesToArray(this.awareness.getStates()) });
|
|
1799
1850
|
});
|
|
1800
|
-
this.intervals.connectionChecker = setInterval(this.checkConnection.bind(this), this.options.messageReconnectTimeout / 10);
|
|
1801
1851
|
this.document.on('update', this.documentUpdateHandler.bind(this));
|
|
1802
1852
|
this.awareness.on('update', this.awarenessUpdateHandler.bind(this));
|
|
1803
|
-
this.
|
|
1804
|
-
|
|
1805
|
-
|
|
1853
|
+
this.registerEventListeners();
|
|
1854
|
+
this.intervals.connectionChecker = setInterval(this.checkConnection.bind(this), this.configuration.messageReconnectTimeout / 10);
|
|
1855
|
+
if (this.configuration.forceSyncInterval) {
|
|
1856
|
+
this.intervals.forceSync = setInterval(this.forceSync.bind(this), this.configuration.forceSyncInterval);
|
|
1806
1857
|
}
|
|
1807
|
-
if (
|
|
1808
|
-
this.connect
|
|
1858
|
+
if (typeof configuration.connect !== 'undefined') {
|
|
1859
|
+
this.shouldConnect = configuration.connect;
|
|
1860
|
+
}
|
|
1861
|
+
if (!this.shouldConnect) {
|
|
1862
|
+
return;
|
|
1809
1863
|
}
|
|
1864
|
+
this.connect();
|
|
1810
1865
|
}
|
|
1811
|
-
|
|
1812
|
-
this.
|
|
1866
|
+
setConfiguration(configuration = {}) {
|
|
1867
|
+
this.configuration = { ...this.configuration, ...configuration };
|
|
1868
|
+
}
|
|
1869
|
+
async connect() {
|
|
1870
|
+
if (this.status === exports.WebSocketStatus.Connected) {
|
|
1871
|
+
return;
|
|
1872
|
+
}
|
|
1873
|
+
// Always cancel any previously initiated connection retryer instances
|
|
1874
|
+
if (this.cancelWebsocketRetry) {
|
|
1875
|
+
this.cancelWebsocketRetry();
|
|
1876
|
+
this.cancelWebsocketRetry = undefined;
|
|
1877
|
+
}
|
|
1878
|
+
this.unsyncedChanges = 0; // set to 0 in case we got reconnected
|
|
1879
|
+
this.shouldConnect = true;
|
|
1880
|
+
this.subscribeToBroadcastChannel();
|
|
1881
|
+
const abortableRetry = () => {
|
|
1882
|
+
let cancelAttempt = false;
|
|
1883
|
+
const retryPromise = attempt.retry(this.createWebSocketConnection.bind(this), {
|
|
1884
|
+
delay: this.configuration.delay,
|
|
1885
|
+
initialDelay: this.configuration.initialDelay,
|
|
1886
|
+
factor: this.configuration.factor,
|
|
1887
|
+
maxAttempts: this.configuration.maxAttempts,
|
|
1888
|
+
minDelay: this.configuration.minDelay,
|
|
1889
|
+
maxDelay: this.configuration.maxDelay,
|
|
1890
|
+
jitter: this.configuration.jitter,
|
|
1891
|
+
timeout: this.configuration.timeout,
|
|
1892
|
+
beforeAttempt: context => {
|
|
1893
|
+
if (!this.shouldConnect || cancelAttempt) {
|
|
1894
|
+
context.abort();
|
|
1895
|
+
}
|
|
1896
|
+
},
|
|
1897
|
+
}).catch((error) => {
|
|
1898
|
+
// If we aborted the connection attempt then don’t throw an error
|
|
1899
|
+
// ref: https://github.com/lifeomic/attempt/blob/master/src/index.ts#L136
|
|
1900
|
+
if (error && error.code !== 'ATTEMPT_ABORTED') {
|
|
1901
|
+
throw error;
|
|
1902
|
+
}
|
|
1903
|
+
});
|
|
1904
|
+
return {
|
|
1905
|
+
retryPromise,
|
|
1906
|
+
cancelFunc: () => {
|
|
1907
|
+
cancelAttempt = true;
|
|
1908
|
+
},
|
|
1909
|
+
};
|
|
1910
|
+
};
|
|
1911
|
+
const { retryPromise, cancelFunc } = abortableRetry();
|
|
1912
|
+
this.cancelWebsocketRetry = cancelFunc;
|
|
1913
|
+
return retryPromise;
|
|
1914
|
+
}
|
|
1915
|
+
createWebSocketConnection() {
|
|
1916
|
+
return new Promise((resolve, reject) => {
|
|
1917
|
+
if (this.webSocket) {
|
|
1918
|
+
this.webSocket.close();
|
|
1919
|
+
this.webSocket = null;
|
|
1920
|
+
}
|
|
1921
|
+
// Init the WebSocket connection
|
|
1922
|
+
const ws = new this.configuration.WebSocketPolyfill(this.url);
|
|
1923
|
+
ws.binaryType = 'arraybuffer';
|
|
1924
|
+
ws.onmessage = this.onMessage.bind(this);
|
|
1925
|
+
ws.onclose = this.onClose.bind(this);
|
|
1926
|
+
ws.onopen = this.onOpen.bind(this);
|
|
1927
|
+
ws.onerror = (err) => {
|
|
1928
|
+
reject(err);
|
|
1929
|
+
};
|
|
1930
|
+
this.webSocket = ws;
|
|
1931
|
+
// Reset the status
|
|
1932
|
+
this.synced = false;
|
|
1933
|
+
this.status = exports.WebSocketStatus.Connecting;
|
|
1934
|
+
this.emit('status', { status: exports.WebSocketStatus.Connecting });
|
|
1935
|
+
// Store resolve/reject for later use
|
|
1936
|
+
this.connectionAttempt = {
|
|
1937
|
+
resolve,
|
|
1938
|
+
reject,
|
|
1939
|
+
};
|
|
1940
|
+
});
|
|
1941
|
+
}
|
|
1942
|
+
resolveConnectionAttempt() {
|
|
1943
|
+
var _a;
|
|
1944
|
+
(_a = this.connectionAttempt) === null || _a === void 0 ? void 0 : _a.resolve();
|
|
1945
|
+
this.connectionAttempt = null;
|
|
1946
|
+
this.status = exports.WebSocketStatus.Connected;
|
|
1947
|
+
this.emit('status', { status: exports.WebSocketStatus.Connected });
|
|
1948
|
+
this.emit('connect');
|
|
1949
|
+
}
|
|
1950
|
+
stopConnectionAttempt() {
|
|
1951
|
+
this.connectionAttempt = null;
|
|
1952
|
+
}
|
|
1953
|
+
rejectConnectionAttempt() {
|
|
1954
|
+
var _a;
|
|
1955
|
+
(_a = this.connectionAttempt) === null || _a === void 0 ? void 0 : _a.reject();
|
|
1956
|
+
this.connectionAttempt = null;
|
|
1813
1957
|
}
|
|
1814
1958
|
get document() {
|
|
1815
|
-
return this.
|
|
1959
|
+
return this.configuration.document;
|
|
1816
1960
|
}
|
|
1817
1961
|
get awareness() {
|
|
1818
|
-
return this.
|
|
1962
|
+
return this.configuration.awareness;
|
|
1963
|
+
}
|
|
1964
|
+
get hasUnsyncedChanges() {
|
|
1965
|
+
return this.unsyncedChanges > 0;
|
|
1819
1966
|
}
|
|
1820
1967
|
checkConnection() {
|
|
1968
|
+
var _a;
|
|
1969
|
+
// Don’t check the connection when it’s not even established
|
|
1821
1970
|
if (this.status !== exports.WebSocketStatus.Connected) {
|
|
1822
1971
|
return;
|
|
1823
1972
|
}
|
|
1824
|
-
|
|
1973
|
+
// Don’t close then connection while waiting for the first message
|
|
1974
|
+
if (!this.lastMessageReceived) {
|
|
1975
|
+
return;
|
|
1976
|
+
}
|
|
1977
|
+
// Don’t close the connection when a message was received recently
|
|
1978
|
+
if (this.configuration.messageReconnectTimeout >= getUnixTime() - this.lastMessageReceived) {
|
|
1825
1979
|
return;
|
|
1826
1980
|
}
|
|
1827
1981
|
// No message received in a long time, not even your own
|
|
1828
1982
|
// Awareness updates, which are updated every 15 seconds.
|
|
1829
|
-
this.webSocket.close();
|
|
1983
|
+
(_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.close();
|
|
1830
1984
|
}
|
|
1831
1985
|
forceSync() {
|
|
1832
1986
|
if (!this.webSocket) {
|
|
@@ -1834,18 +1988,21 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1834
1988
|
}
|
|
1835
1989
|
this.send(SyncStepOneMessage, { document: this.document });
|
|
1836
1990
|
}
|
|
1837
|
-
|
|
1991
|
+
beforeUnload() {
|
|
1992
|
+
removeAwarenessStates(this.awareness, [this.document.clientID], 'window unload');
|
|
1993
|
+
}
|
|
1994
|
+
registerEventListeners() {
|
|
1838
1995
|
if (typeof window === 'undefined') {
|
|
1839
1996
|
return;
|
|
1840
1997
|
}
|
|
1841
|
-
window.addEventListener('
|
|
1842
|
-
|
|
1843
|
-
});
|
|
1998
|
+
window.addEventListener('online', this.boundConnect);
|
|
1999
|
+
window.addEventListener('beforeunload', this.boundBeforeUnload);
|
|
1844
2000
|
}
|
|
1845
2001
|
documentUpdateHandler(update, origin) {
|
|
1846
2002
|
if (origin === this) {
|
|
1847
2003
|
return;
|
|
1848
2004
|
}
|
|
2005
|
+
this.unsyncedChanges += 1;
|
|
1849
2006
|
this.send(UpdateMessage, { update }, true);
|
|
1850
2007
|
}
|
|
1851
2008
|
awarenessUpdateHandler({ added, updated, removed }, origin) {
|
|
@@ -1855,16 +2012,26 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1855
2012
|
clients: changedClients,
|
|
1856
2013
|
}, true);
|
|
1857
2014
|
}
|
|
2015
|
+
permissionDeniedHandler(reason) {
|
|
2016
|
+
this.emit('authenticationFailed', { reason });
|
|
2017
|
+
this.isAuthenticated = false;
|
|
2018
|
+
this.shouldConnect = false;
|
|
2019
|
+
}
|
|
2020
|
+
authenticatedHandler() {
|
|
2021
|
+
this.isAuthenticated = true;
|
|
2022
|
+
this.emit('authenticated');
|
|
2023
|
+
this.startSync();
|
|
2024
|
+
}
|
|
1858
2025
|
// Ensure that the URL always ends with /
|
|
1859
2026
|
get serverUrl() {
|
|
1860
|
-
while (this.
|
|
1861
|
-
return this.
|
|
2027
|
+
while (this.configuration.url[this.configuration.url.length - 1] === '/') {
|
|
2028
|
+
return this.configuration.url.slice(0, this.configuration.url.length - 1);
|
|
1862
2029
|
}
|
|
1863
|
-
return this.
|
|
2030
|
+
return this.configuration.url;
|
|
1864
2031
|
}
|
|
1865
2032
|
get url() {
|
|
1866
|
-
const encodedParams = encodeQueryParams(this.
|
|
1867
|
-
return `${this.serverUrl}/${this.
|
|
2033
|
+
const encodedParams = encodeQueryParams(this.configuration.parameters);
|
|
2034
|
+
return `${this.serverUrl}/${this.configuration.name}${encodedParams.length === 0 ? '' : `?${encodedParams}`}`;
|
|
1868
2035
|
}
|
|
1869
2036
|
get synced() {
|
|
1870
2037
|
return this.isSynced;
|
|
@@ -1877,12 +2044,8 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1877
2044
|
this.emit('synced', { state });
|
|
1878
2045
|
this.emit('sync', { state });
|
|
1879
2046
|
}
|
|
1880
|
-
|
|
1881
|
-
this.
|
|
1882
|
-
if (this.status !== exports.WebSocketStatus.Connected) {
|
|
1883
|
-
this.createWebSocketConnection();
|
|
1884
|
-
this.subscribeToBroadcastChannel();
|
|
1885
|
-
}
|
|
2047
|
+
get isAuthenticationRequired() {
|
|
2048
|
+
return !!this.configuration.token && !this.isAuthenticated;
|
|
1886
2049
|
}
|
|
1887
2050
|
disconnect() {
|
|
1888
2051
|
this.shouldConnect = false;
|
|
@@ -1897,27 +2060,24 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1897
2060
|
//
|
|
1898
2061
|
}
|
|
1899
2062
|
}
|
|
1900
|
-
|
|
1901
|
-
|
|
2063
|
+
async onOpen(event) {
|
|
2064
|
+
this.emit('open', { event });
|
|
2065
|
+
if (this.isAuthenticationRequired) {
|
|
2066
|
+
this.send(AuthenticationMessage, {
|
|
2067
|
+
token: await this.getToken(),
|
|
2068
|
+
});
|
|
1902
2069
|
return;
|
|
1903
2070
|
}
|
|
1904
|
-
this.
|
|
1905
|
-
this.webSocket.binaryType = 'arraybuffer';
|
|
1906
|
-
this.status = exports.WebSocketStatus.Connecting;
|
|
1907
|
-
this.synced = false;
|
|
1908
|
-
this.webSocket.onmessage = this.onMessage.bind(this);
|
|
1909
|
-
this.webSocket.onclose = this.onClose.bind(this);
|
|
1910
|
-
this.webSocket.onopen = this.onOpen.bind(this);
|
|
1911
|
-
this.emit('status', { status: 'connecting' });
|
|
2071
|
+
this.startSync();
|
|
1912
2072
|
}
|
|
1913
|
-
|
|
1914
|
-
this.
|
|
2073
|
+
async getToken() {
|
|
2074
|
+
if (typeof this.configuration.token === 'function') {
|
|
2075
|
+
const token = await this.configuration.token();
|
|
2076
|
+
return token;
|
|
2077
|
+
}
|
|
2078
|
+
return this.configuration.token;
|
|
1915
2079
|
}
|
|
1916
|
-
|
|
1917
|
-
this.failedConnectionAttempts = 0;
|
|
1918
|
-
this.status = exports.WebSocketStatus.Connected;
|
|
1919
|
-
this.emit('status', { status: 'connected' });
|
|
1920
|
-
this.emit('connect');
|
|
2080
|
+
startSync() {
|
|
1921
2081
|
this.send(SyncStepOneMessage, { document: this.document });
|
|
1922
2082
|
if (this.awareness.getLocalState() !== null) {
|
|
1923
2083
|
this.send(AwarenessMessage, {
|
|
@@ -1927,55 +2087,66 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1927
2087
|
}
|
|
1928
2088
|
}
|
|
1929
2089
|
send(Message, args, broadcast = false) {
|
|
2090
|
+
var _a;
|
|
1930
2091
|
if (broadcast) {
|
|
1931
|
-
this.mux(() => {
|
|
1932
|
-
this.broadcast(Message, args);
|
|
1933
|
-
});
|
|
2092
|
+
this.mux(() => { this.broadcast(Message, args); });
|
|
1934
2093
|
}
|
|
1935
|
-
if (this.
|
|
2094
|
+
if (((_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.readyState) === common.WsReadyStates.Open) {
|
|
1936
2095
|
const messageSender = new MessageSender(Message, args);
|
|
1937
2096
|
this.emit('outgoingMessage', { message: messageSender.message });
|
|
1938
2097
|
messageSender.send(this.webSocket);
|
|
1939
2098
|
}
|
|
1940
2099
|
}
|
|
1941
2100
|
onMessage(event) {
|
|
1942
|
-
|
|
1943
|
-
this.webSocketConnectionEstablished();
|
|
1944
|
-
}
|
|
2101
|
+
this.resolveConnectionAttempt();
|
|
1945
2102
|
this.lastMessageReceived = getUnixTime();
|
|
1946
2103
|
const message = new IncomingMessage(event.data);
|
|
1947
2104
|
this.emit('message', { event, message });
|
|
1948
|
-
new MessageReceiver(message
|
|
1949
|
-
// TODO: What’s that doing?
|
|
1950
|
-
// if (encoding.length(encoder) > 1) {
|
|
1951
|
-
// this.send(encoding.toUint8Array(encoder))
|
|
1952
|
-
// }
|
|
2105
|
+
new MessageReceiver(message).apply(this);
|
|
1953
2106
|
}
|
|
1954
2107
|
onClose(event) {
|
|
1955
2108
|
this.emit('close', { event });
|
|
1956
2109
|
this.webSocket = null;
|
|
2110
|
+
this.isAuthenticated = false;
|
|
2111
|
+
this.synced = false;
|
|
1957
2112
|
if (this.status === exports.WebSocketStatus.Connected) {
|
|
1958
|
-
this.synced = false;
|
|
1959
2113
|
// update awareness (all users except local left)
|
|
1960
2114
|
removeAwarenessStates(this.awareness, Array.from(this.awareness.getStates().keys()).filter(client => client !== this.document.clientID), this);
|
|
1961
2115
|
this.status = exports.WebSocketStatus.Disconnected;
|
|
1962
|
-
this.emit('status', { status:
|
|
2116
|
+
this.emit('status', { status: exports.WebSocketStatus.Disconnected });
|
|
1963
2117
|
this.emit('disconnect', { event });
|
|
1964
2118
|
}
|
|
1965
|
-
|
|
1966
|
-
this.
|
|
2119
|
+
if (event.code === common.Unauthorized.code) {
|
|
2120
|
+
if (!this.configuration.quiet) {
|
|
2121
|
+
console.warn('[HocuspocusProvider] An authentication token is required, but you didn’t send one. Try adding a `token` to your HocuspocusProvider configuration. Won’t try again.');
|
|
2122
|
+
}
|
|
2123
|
+
this.shouldConnect = false;
|
|
2124
|
+
}
|
|
2125
|
+
if (event.code === common.Forbidden.code) {
|
|
2126
|
+
if (!this.configuration.quiet) {
|
|
2127
|
+
console.warn('[HocuspocusProvider] The provided authentication token isn’t allowed to connect to this server. Will try again.');
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
if (this.connectionAttempt) {
|
|
2131
|
+
// That connection attempt failed.
|
|
2132
|
+
this.rejectConnectionAttempt();
|
|
1967
2133
|
}
|
|
2134
|
+
else if (this.shouldConnect) {
|
|
2135
|
+
// The connection was closed by the server. Let’s just try again.
|
|
2136
|
+
this.connect();
|
|
2137
|
+
}
|
|
2138
|
+
// If we’ll reconnect, we’re done for now.
|
|
1968
2139
|
if (this.shouldConnect) {
|
|
1969
|
-
const wait = round(min(log10(this.failedConnectionAttempts + 1) * this.options.reconnectTimeoutBase, this.options.maxReconnectTimeout));
|
|
1970
|
-
this.log(`[close] Reconnecting in ${wait}ms …`);
|
|
1971
|
-
setTimeout(this.createWebSocketConnection.bind(this), wait);
|
|
1972
2140
|
return;
|
|
1973
2141
|
}
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
this.emit('disconnect', { event });
|
|
2142
|
+
// The status is set correctly already.
|
|
2143
|
+
if (this.status === exports.WebSocketStatus.Disconnected) {
|
|
2144
|
+
return;
|
|
1978
2145
|
}
|
|
2146
|
+
// Let’s update the connection status.
|
|
2147
|
+
this.status = exports.WebSocketStatus.Disconnected;
|
|
2148
|
+
this.emit('status', { status: exports.WebSocketStatus.Disconnected });
|
|
2149
|
+
this.emit('disconnect', { event });
|
|
1979
2150
|
}
|
|
1980
2151
|
destroy() {
|
|
1981
2152
|
this.emit('destroy');
|
|
@@ -1983,27 +2154,35 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1983
2154
|
clearInterval(this.intervals.forceSync);
|
|
1984
2155
|
}
|
|
1985
2156
|
clearInterval(this.intervals.connectionChecker);
|
|
2157
|
+
removeAwarenessStates(this.awareness, [this.document.clientID], 'provider destroy');
|
|
2158
|
+
// If there is still a connection attempt outstanding then we should stop
|
|
2159
|
+
// it before calling disconnect, otherwise it will be rejected in the onClose
|
|
2160
|
+
// handler and trigger a retry
|
|
2161
|
+
this.stopConnectionAttempt();
|
|
1986
2162
|
this.disconnect();
|
|
1987
2163
|
this.awareness.off('update', this.awarenessUpdateHandler);
|
|
1988
2164
|
this.document.off('update', this.documentUpdateHandler);
|
|
1989
2165
|
this.removeAllListeners();
|
|
2166
|
+
if (typeof window === 'undefined') {
|
|
2167
|
+
return;
|
|
2168
|
+
}
|
|
2169
|
+
window.removeEventListener('online', this.boundConnect);
|
|
2170
|
+
window.removeEventListener('beforeunload', this.boundBeforeUnload);
|
|
1990
2171
|
}
|
|
1991
2172
|
get broadcastChannel() {
|
|
1992
|
-
return `${this.serverUrl}/${this.
|
|
2173
|
+
return `${this.serverUrl}/${this.configuration.name}`;
|
|
1993
2174
|
}
|
|
1994
2175
|
broadcastChannelSubscriber(data) {
|
|
1995
2176
|
this.mux(() => {
|
|
1996
2177
|
const message = new IncomingMessage(data);
|
|
1997
|
-
new MessageReceiver(message
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
// this.broadcast(encoding.toUint8Array(encoder))
|
|
2001
|
-
// }
|
|
2178
|
+
new MessageReceiver(message)
|
|
2179
|
+
.setBroadcasted(true)
|
|
2180
|
+
.apply(this, false);
|
|
2002
2181
|
});
|
|
2003
2182
|
}
|
|
2004
2183
|
subscribeToBroadcastChannel() {
|
|
2005
2184
|
if (!this.subscribedToBroadcastChannel) {
|
|
2006
|
-
subscribe(this.broadcastChannel, this.
|
|
2185
|
+
subscribe(this.broadcastChannel, this.boundBroadcastChannelSubscriber);
|
|
2007
2186
|
this.subscribedToBroadcastChannel = true;
|
|
2008
2187
|
}
|
|
2009
2188
|
this.mux(() => {
|
|
@@ -2021,12 +2200,12 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
2021
2200
|
states: new Map(),
|
|
2022
2201
|
}, true);
|
|
2023
2202
|
if (this.subscribedToBroadcastChannel) {
|
|
2024
|
-
unsubscribe(this.broadcastChannel, this.
|
|
2203
|
+
unsubscribe(this.broadcastChannel, this.boundBroadcastChannelSubscriber);
|
|
2025
2204
|
this.subscribedToBroadcastChannel = false;
|
|
2026
2205
|
}
|
|
2027
2206
|
}
|
|
2028
2207
|
broadcast(Message, args) {
|
|
2029
|
-
if (!this.
|
|
2208
|
+
if (!this.configuration.broadcast) {
|
|
2030
2209
|
return;
|
|
2031
2210
|
}
|
|
2032
2211
|
if (!this.subscribedToBroadcastChannel) {
|
|
@@ -2034,17 +2213,26 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
2034
2213
|
}
|
|
2035
2214
|
new MessageSender(Message, args).broadcast(this.broadcastChannel);
|
|
2036
2215
|
}
|
|
2037
|
-
log(message) {
|
|
2038
|
-
if (!this.options.debug) {
|
|
2039
|
-
return;
|
|
2040
|
-
}
|
|
2041
|
-
console.log(message);
|
|
2042
|
-
}
|
|
2043
2216
|
setAwarenessField(key, value) {
|
|
2044
2217
|
this.awareness.setLocalStateField(key, value);
|
|
2045
2218
|
}
|
|
2046
2219
|
}
|
|
2047
2220
|
|
|
2221
|
+
class HocuspocusCloudProvider extends HocuspocusProvider {
|
|
2222
|
+
constructor(configuration) {
|
|
2223
|
+
if (!configuration.url) {
|
|
2224
|
+
configuration.url = 'wss://connect.hocuspocus.cloud';
|
|
2225
|
+
}
|
|
2226
|
+
if (configuration.key) {
|
|
2227
|
+
if (!configuration.parameters) {
|
|
2228
|
+
configuration.parameters = {};
|
|
2229
|
+
}
|
|
2230
|
+
configuration.parameters.key = configuration.key;
|
|
2231
|
+
}
|
|
2232
|
+
super(configuration);
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
exports.HocuspocusCloudProvider = HocuspocusCloudProvider;
|
|
2048
2237
|
exports.HocuspocusProvider = HocuspocusProvider;
|
|
2049
|
-
exports.awarenessStatesToArray = awarenessStatesToArray;
|
|
2050
2238
|
//# sourceMappingURL=hocuspocus-provider.cjs.map
|