@hocuspocus/provider 1.0.0-alpha.4 → 1.0.0-alpha.40
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.js → hocuspocus-provider.cjs} +362 -186
- package/dist/hocuspocus-provider.cjs.map +1 -0
- package/dist/hocuspocus-provider.esm.js +359 -181
- 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 -32
- 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 +16 -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 +168 -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/backend/src/webhook.d.ts → playground/backend/src/redis.d.ts} +0 -0
- package/dist/playground/backend/src/slow.d.ts +1 -0
- package/dist/playground/backend/src/webhook.d.ts +1 -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/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/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 +15 -11
- package/src/EventEmitter.ts +1 -1
- package/src/HocuspocusCloudProvider.ts +34 -0
- package/src/HocuspocusProvider.ts +389 -159
- 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 -24
- package/dist/hocuspocus-provider.js.map +0 -1
- 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
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as Y from 'yjs';
|
|
2
|
+
import { retry } from '@lifeomic/attempt';
|
|
3
|
+
import { readAuthMessage, writeAuthentication, awarenessStatesToArray, WsReadyStates, Unauthorized, Forbidden } from '@hocuspocus/common';
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Utility module to work with key-value stores.
|
|
@@ -258,8 +260,6 @@ hasConf('production');
|
|
|
258
260
|
*/
|
|
259
261
|
|
|
260
262
|
const floor = Math.floor;
|
|
261
|
-
const round = Math.round;
|
|
262
|
-
const log10 = Math.log10;
|
|
263
263
|
|
|
264
264
|
/**
|
|
265
265
|
* @function
|
|
@@ -1372,23 +1372,26 @@ class EventEmitter {
|
|
|
1372
1372
|
}
|
|
1373
1373
|
}
|
|
1374
1374
|
|
|
1375
|
-
var MessageType;
|
|
1376
|
-
(function (MessageType) {
|
|
1377
|
-
MessageType[MessageType["Sync"] = 0] = "Sync";
|
|
1378
|
-
MessageType[MessageType["Awareness"] = 1] = "Awareness";
|
|
1379
|
-
MessageType[MessageType["Auth"] = 2] = "Auth";
|
|
1380
|
-
MessageType[MessageType["QueryAwareness"] = 3] = "QueryAwareness";
|
|
1381
|
-
})(MessageType || (MessageType = {}));
|
|
1382
|
-
|
|
1383
1375
|
class IncomingMessage {
|
|
1384
1376
|
constructor(data) {
|
|
1385
1377
|
this.data = data;
|
|
1386
1378
|
this.encoder = createEncoder();
|
|
1387
1379
|
this.decoder = createDecoder(new Uint8Array(this.data));
|
|
1388
|
-
this.type = readVarUint(this.decoder);
|
|
1389
1380
|
}
|
|
1390
|
-
|
|
1391
|
-
return
|
|
1381
|
+
readVarUint() {
|
|
1382
|
+
return readVarUint(this.decoder);
|
|
1383
|
+
}
|
|
1384
|
+
readVarUint8Array() {
|
|
1385
|
+
return readVarUint8Array(this.decoder);
|
|
1386
|
+
}
|
|
1387
|
+
writeVarUint(type) {
|
|
1388
|
+
return writeVarUint(this.encoder, type);
|
|
1389
|
+
}
|
|
1390
|
+
writeVarUint8Array(data) {
|
|
1391
|
+
return writeVarUint8Array(this.encoder, data);
|
|
1392
|
+
}
|
|
1393
|
+
length() {
|
|
1394
|
+
return length$1(this.encoder);
|
|
1392
1395
|
}
|
|
1393
1396
|
}
|
|
1394
1397
|
|
|
@@ -1519,32 +1522,45 @@ const readSyncMessage = (decoder, encoder, doc, transactionOrigin) => {
|
|
|
1519
1522
|
return messageType
|
|
1520
1523
|
};
|
|
1521
1524
|
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1525
|
+
var MessageType;
|
|
1526
|
+
(function (MessageType) {
|
|
1527
|
+
MessageType[MessageType["Sync"] = 0] = "Sync";
|
|
1528
|
+
MessageType[MessageType["Awareness"] = 1] = "Awareness";
|
|
1529
|
+
MessageType[MessageType["Auth"] = 2] = "Auth";
|
|
1530
|
+
MessageType[MessageType["QueryAwareness"] = 3] = "QueryAwareness";
|
|
1531
|
+
})(MessageType || (MessageType = {}));
|
|
1532
|
+
var WebSocketStatus;
|
|
1533
|
+
(function (WebSocketStatus) {
|
|
1534
|
+
WebSocketStatus["Connecting"] = "connecting";
|
|
1535
|
+
WebSocketStatus["Connected"] = "connected";
|
|
1536
|
+
WebSocketStatus["Disconnected"] = "disconnected";
|
|
1537
|
+
})(WebSocketStatus || (WebSocketStatus = {}));
|
|
1529
1538
|
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
}
|
|
1539
|
+
class OutgoingMessage {
|
|
1540
|
+
constructor() {
|
|
1541
|
+
this.encoder = createEncoder();
|
|
1542
|
+
}
|
|
1543
|
+
get(args) {
|
|
1544
|
+
return args.encoder;
|
|
1545
|
+
}
|
|
1546
|
+
toUint8Array() {
|
|
1547
|
+
return toUint8Array(this.encoder);
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1541
1550
|
|
|
1542
1551
|
class MessageReceiver {
|
|
1543
1552
|
constructor(message) {
|
|
1553
|
+
this.broadcasted = false;
|
|
1544
1554
|
this.message = message;
|
|
1545
1555
|
}
|
|
1556
|
+
setBroadcasted(value) {
|
|
1557
|
+
this.broadcasted = value;
|
|
1558
|
+
return this;
|
|
1559
|
+
}
|
|
1546
1560
|
apply(provider, emitSynced = true) {
|
|
1547
|
-
|
|
1561
|
+
const { message } = this;
|
|
1562
|
+
const type = message.readVarUint();
|
|
1563
|
+
switch (type) {
|
|
1548
1564
|
case MessageType.Sync:
|
|
1549
1565
|
this.applySyncMessage(provider, emitSynced);
|
|
1550
1566
|
break;
|
|
@@ -1558,31 +1574,49 @@ class MessageReceiver {
|
|
|
1558
1574
|
this.applyQueryAwarenessMessage(provider);
|
|
1559
1575
|
break;
|
|
1560
1576
|
default:
|
|
1561
|
-
throw new Error(`Can’t apply unknown type
|
|
1577
|
+
throw new Error(`Can’t apply message of unknown type: ${type}`);
|
|
1578
|
+
}
|
|
1579
|
+
// Reply
|
|
1580
|
+
if (message.length() > 1) {
|
|
1581
|
+
if (this.broadcasted) {
|
|
1582
|
+
// TODO: Some weird TypeScript error
|
|
1583
|
+
// @ts-ignore
|
|
1584
|
+
provider.broadcast(OutgoingMessage, { encoder: message.encoder });
|
|
1585
|
+
}
|
|
1586
|
+
else {
|
|
1587
|
+
// TODO: Some weird TypeScript error
|
|
1588
|
+
// @ts-ignore
|
|
1589
|
+
provider.send(OutgoingMessage, { encoder: message.encoder });
|
|
1590
|
+
}
|
|
1562
1591
|
}
|
|
1563
|
-
return this.message.encoder;
|
|
1564
1592
|
}
|
|
1565
1593
|
applySyncMessage(provider, emitSynced) {
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1594
|
+
const { message } = this;
|
|
1595
|
+
message.writeVarUint(MessageType.Sync);
|
|
1596
|
+
// Apply update
|
|
1597
|
+
const syncMessageType = readSyncMessage(message.decoder, message.encoder, provider.document, provider);
|
|
1598
|
+
// Synced once we receive Step2
|
|
1599
|
+
if (emitSynced && (syncMessageType === messageYjsSyncStep2)) {
|
|
1569
1600
|
provider.synced = true;
|
|
1570
1601
|
}
|
|
1602
|
+
if (syncMessageType === messageYjsUpdate || syncMessageType === messageYjsSyncStep2) {
|
|
1603
|
+
if (provider.unsyncedChanges > 0) {
|
|
1604
|
+
provider.unsyncedChanges -= 1;
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1571
1607
|
}
|
|
1572
1608
|
applyAwarenessMessage(provider) {
|
|
1573
|
-
|
|
1609
|
+
const { message } = this;
|
|
1610
|
+
applyAwarenessUpdate(provider.awareness, message.readVarUint8Array(), provider);
|
|
1574
1611
|
}
|
|
1575
|
-
// TODO: This isn’t really used. Needs to be implemented in the server, or removed here.
|
|
1576
1612
|
applyAuthMessage(provider) {
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
(provider, reason) => {
|
|
1580
|
-
console.warn(`Permission denied to access ${provider.url}.\n${reason}`);
|
|
1581
|
-
});
|
|
1613
|
+
const { message } = this;
|
|
1614
|
+
readAuthMessage(message.decoder, provider.permissionDeniedHandler.bind(provider), provider.authenticatedHandler.bind(provider));
|
|
1582
1615
|
}
|
|
1583
1616
|
applyQueryAwarenessMessage(provider) {
|
|
1584
|
-
|
|
1585
|
-
|
|
1617
|
+
const { message } = this;
|
|
1618
|
+
message.writeVarUint(MessageType.Awareness);
|
|
1619
|
+
message.writeVarUint8Array(encodeAwarenessUpdate(provider.awareness, Array.from(provider.awareness.getStates().keys())));
|
|
1586
1620
|
}
|
|
1587
1621
|
}
|
|
1588
1622
|
|
|
@@ -1602,18 +1636,6 @@ class MessageSender {
|
|
|
1602
1636
|
}
|
|
1603
1637
|
}
|
|
1604
1638
|
|
|
1605
|
-
class OutgoingMessage {
|
|
1606
|
-
constructor() {
|
|
1607
|
-
this.encoder = createEncoder();
|
|
1608
|
-
}
|
|
1609
|
-
get name() {
|
|
1610
|
-
if (typeof this.type === 'number') {
|
|
1611
|
-
return MessageType[this.type];
|
|
1612
|
-
}
|
|
1613
|
-
throw new Error('Type for outgoing message not set.');
|
|
1614
|
-
}
|
|
1615
|
-
}
|
|
1616
|
-
|
|
1617
1639
|
class SyncStepOneMessage extends OutgoingMessage {
|
|
1618
1640
|
constructor() {
|
|
1619
1641
|
super(...arguments);
|
|
@@ -1658,6 +1680,22 @@ class QueryAwarenessMessage extends OutgoingMessage {
|
|
|
1658
1680
|
}
|
|
1659
1681
|
}
|
|
1660
1682
|
|
|
1683
|
+
class AuthenticationMessage extends OutgoingMessage {
|
|
1684
|
+
constructor() {
|
|
1685
|
+
super(...arguments);
|
|
1686
|
+
this.type = MessageType.Auth;
|
|
1687
|
+
this.description = 'Authentication';
|
|
1688
|
+
}
|
|
1689
|
+
get(args) {
|
|
1690
|
+
if (typeof args.token === 'undefined') {
|
|
1691
|
+
throw new Error('The authentication message requires `token` as an argument.');
|
|
1692
|
+
}
|
|
1693
|
+
writeVarUint(this.encoder, this.type);
|
|
1694
|
+
writeAuthentication(this.encoder, args.token);
|
|
1695
|
+
return this.encoder;
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1661
1699
|
class AwarenessMessage extends OutgoingMessage {
|
|
1662
1700
|
constructor() {
|
|
1663
1701
|
super(...arguments);
|
|
@@ -1697,107 +1735,210 @@ class UpdateMessage extends OutgoingMessage {
|
|
|
1697
1735
|
}
|
|
1698
1736
|
}
|
|
1699
1737
|
|
|
1700
|
-
var awarenessStatesToArray = (states) => {
|
|
1701
|
-
return Array.from(states.entries()).map(([key, value]) => {
|
|
1702
|
-
return {
|
|
1703
|
-
clientId: key,
|
|
1704
|
-
...value,
|
|
1705
|
-
};
|
|
1706
|
-
});
|
|
1707
|
-
};
|
|
1708
|
-
|
|
1709
|
-
// @ts-nocheck
|
|
1710
|
-
var WebSocketStatus;
|
|
1711
|
-
(function (WebSocketStatus) {
|
|
1712
|
-
WebSocketStatus["Connecting"] = "connecting";
|
|
1713
|
-
WebSocketStatus["Connected"] = "connected";
|
|
1714
|
-
WebSocketStatus["Disconnected"] = "disconnected";
|
|
1715
|
-
})(WebSocketStatus || (WebSocketStatus = {}));
|
|
1716
1738
|
class HocuspocusProvider extends EventEmitter {
|
|
1717
|
-
constructor(
|
|
1739
|
+
constructor(configuration) {
|
|
1718
1740
|
super();
|
|
1719
|
-
this.
|
|
1720
|
-
url: '',
|
|
1741
|
+
this.configuration = {
|
|
1721
1742
|
name: '',
|
|
1743
|
+
url: '',
|
|
1744
|
+
// @ts-ignore
|
|
1745
|
+
document: undefined,
|
|
1746
|
+
// @ts-ignore
|
|
1747
|
+
awareness: undefined,
|
|
1748
|
+
WebSocketPolyfill: undefined,
|
|
1749
|
+
token: null,
|
|
1722
1750
|
parameters: {},
|
|
1723
|
-
debug: false,
|
|
1724
1751
|
connect: true,
|
|
1752
|
+
broadcast: true,
|
|
1725
1753
|
forceSyncInterval: false,
|
|
1726
|
-
reconnectTimeoutBase: 1200,
|
|
1727
|
-
maxReconnectTimeout: 2500,
|
|
1728
1754
|
// TODO: this should depend on awareness.outdatedTime
|
|
1729
1755
|
messageReconnectTimeout: 30000,
|
|
1756
|
+
// 1 second
|
|
1757
|
+
delay: 1000,
|
|
1758
|
+
// instant
|
|
1759
|
+
initialDelay: 0,
|
|
1760
|
+
// double the delay each time
|
|
1761
|
+
factor: 2,
|
|
1762
|
+
// unlimited retries
|
|
1763
|
+
maxAttempts: 0,
|
|
1764
|
+
// wait at least 1 second
|
|
1765
|
+
minDelay: 1000,
|
|
1766
|
+
// at least every 30 seconds
|
|
1767
|
+
maxDelay: 30000,
|
|
1768
|
+
// randomize
|
|
1769
|
+
jitter: true,
|
|
1770
|
+
// retry forever
|
|
1771
|
+
timeout: 0,
|
|
1772
|
+
onAuthenticated: () => null,
|
|
1773
|
+
onAuthenticationFailed: () => null,
|
|
1730
1774
|
onOpen: () => null,
|
|
1731
1775
|
onConnect: () => null,
|
|
1732
1776
|
onMessage: () => null,
|
|
1733
1777
|
onOutgoingMessage: () => null,
|
|
1778
|
+
onStatus: () => null,
|
|
1734
1779
|
onSynced: () => null,
|
|
1735
1780
|
onDisconnect: () => null,
|
|
1736
1781
|
onClose: () => null,
|
|
1737
1782
|
onDestroy: () => null,
|
|
1783
|
+
onAwarenessUpdate: () => null,
|
|
1738
1784
|
onAwarenessChange: () => null,
|
|
1785
|
+
quiet: false,
|
|
1739
1786
|
};
|
|
1740
1787
|
this.subscribedToBroadcastChannel = false;
|
|
1741
1788
|
this.webSocket = null;
|
|
1742
1789
|
this.shouldConnect = true;
|
|
1743
1790
|
this.status = WebSocketStatus.Disconnected;
|
|
1744
|
-
this.failedConnectionAttempts = 0;
|
|
1745
1791
|
this.isSynced = false;
|
|
1792
|
+
this.unsyncedChanges = 0;
|
|
1793
|
+
this.isAuthenticated = false;
|
|
1746
1794
|
this.lastMessageReceived = 0;
|
|
1747
1795
|
this.mux = createMutex();
|
|
1748
1796
|
this.intervals = {
|
|
1749
1797
|
forceSync: null,
|
|
1750
1798
|
connectionChecker: null,
|
|
1751
1799
|
};
|
|
1752
|
-
this.
|
|
1753
|
-
this.
|
|
1754
|
-
this.
|
|
1755
|
-
this.
|
|
1756
|
-
this.
|
|
1757
|
-
this.
|
|
1758
|
-
this.
|
|
1759
|
-
this.
|
|
1760
|
-
this.on('
|
|
1761
|
-
this.on('
|
|
1762
|
-
this.on('
|
|
1763
|
-
this.on('
|
|
1764
|
-
this.on('
|
|
1765
|
-
this.on('
|
|
1800
|
+
this.connectionAttempt = null;
|
|
1801
|
+
this.boundConnect = this.connect.bind(this);
|
|
1802
|
+
this.boundBeforeUnload = this.beforeUnload.bind(this);
|
|
1803
|
+
this.boundBroadcastChannelSubscriber = this.broadcastChannelSubscriber.bind(this);
|
|
1804
|
+
this.setConfiguration(configuration);
|
|
1805
|
+
this.configuration.document = configuration.document ? configuration.document : new Y.Doc();
|
|
1806
|
+
this.configuration.awareness = configuration.awareness ? configuration.awareness : new Awareness(this.document);
|
|
1807
|
+
this.configuration.WebSocketPolyfill = configuration.WebSocketPolyfill ? configuration.WebSocketPolyfill : WebSocket;
|
|
1808
|
+
this.on('open', this.configuration.onOpen);
|
|
1809
|
+
this.on('authenticated', this.configuration.onAuthenticated);
|
|
1810
|
+
this.on('authenticationFailed', this.configuration.onAuthenticationFailed);
|
|
1811
|
+
this.on('connect', this.configuration.onConnect);
|
|
1812
|
+
this.on('message', this.configuration.onMessage);
|
|
1813
|
+
this.on('outgoingMessage', this.configuration.onOutgoingMessage);
|
|
1814
|
+
this.on('synced', this.configuration.onSynced);
|
|
1815
|
+
this.on('status', this.configuration.onStatus);
|
|
1816
|
+
this.on('disconnect', this.configuration.onDisconnect);
|
|
1817
|
+
this.on('close', this.configuration.onClose);
|
|
1818
|
+
this.on('destroy', this.configuration.onDestroy);
|
|
1819
|
+
this.on('awarenessUpdate', this.configuration.onAwarenessUpdate);
|
|
1820
|
+
this.on('awarenessChange', this.configuration.onAwarenessChange);
|
|
1821
|
+
this.awareness.on('update', () => {
|
|
1822
|
+
this.emit('awarenessUpdate', { states: awarenessStatesToArray(this.awareness.getStates()) });
|
|
1823
|
+
});
|
|
1766
1824
|
this.awareness.on('change', () => {
|
|
1767
|
-
this.emit('awarenessChange', {
|
|
1768
|
-
states: awarenessStatesToArray(this.awareness.getStates()),
|
|
1769
|
-
});
|
|
1825
|
+
this.emit('awarenessChange', { states: awarenessStatesToArray(this.awareness.getStates()) });
|
|
1770
1826
|
});
|
|
1771
|
-
this.intervals.connectionChecker = setInterval(this.checkConnection.bind(this), this.options.messageReconnectTimeout / 10);
|
|
1772
1827
|
this.document.on('update', this.documentUpdateHandler.bind(this));
|
|
1773
1828
|
this.awareness.on('update', this.awarenessUpdateHandler.bind(this));
|
|
1774
|
-
this.
|
|
1775
|
-
|
|
1776
|
-
|
|
1829
|
+
this.registerEventListeners();
|
|
1830
|
+
this.intervals.connectionChecker = setInterval(this.checkConnection.bind(this), this.configuration.messageReconnectTimeout / 10);
|
|
1831
|
+
if (this.configuration.forceSyncInterval) {
|
|
1832
|
+
this.intervals.forceSync = setInterval(this.forceSync.bind(this), this.configuration.forceSyncInterval);
|
|
1777
1833
|
}
|
|
1778
|
-
if (
|
|
1779
|
-
this.connect
|
|
1834
|
+
if (typeof configuration.connect !== 'undefined') {
|
|
1835
|
+
this.shouldConnect = configuration.connect;
|
|
1780
1836
|
}
|
|
1837
|
+
if (!this.shouldConnect) {
|
|
1838
|
+
return;
|
|
1839
|
+
}
|
|
1840
|
+
this.connect();
|
|
1841
|
+
}
|
|
1842
|
+
setConfiguration(configuration = {}) {
|
|
1843
|
+
this.configuration = { ...this.configuration, ...configuration };
|
|
1844
|
+
}
|
|
1845
|
+
async connect() {
|
|
1846
|
+
if (this.status === WebSocketStatus.Connected) {
|
|
1847
|
+
return;
|
|
1848
|
+
}
|
|
1849
|
+
this.unsyncedChanges = 0; // set to 0 in case we got reconnected
|
|
1850
|
+
this.shouldConnect = true;
|
|
1851
|
+
this.subscribeToBroadcastChannel();
|
|
1852
|
+
try {
|
|
1853
|
+
await retry(this.createWebSocketConnection.bind(this), {
|
|
1854
|
+
delay: this.configuration.delay,
|
|
1855
|
+
initialDelay: this.configuration.initialDelay,
|
|
1856
|
+
factor: this.configuration.factor,
|
|
1857
|
+
maxAttempts: this.configuration.maxAttempts,
|
|
1858
|
+
minDelay: this.configuration.minDelay,
|
|
1859
|
+
maxDelay: this.configuration.maxDelay,
|
|
1860
|
+
jitter: this.configuration.jitter,
|
|
1861
|
+
timeout: this.configuration.timeout,
|
|
1862
|
+
beforeAttempt: context => {
|
|
1863
|
+
if (!this.shouldConnect) {
|
|
1864
|
+
context.abort();
|
|
1865
|
+
}
|
|
1866
|
+
},
|
|
1867
|
+
});
|
|
1868
|
+
}
|
|
1869
|
+
catch (error) {
|
|
1870
|
+
// If we aborted the connection attempt then don’t throw an error
|
|
1871
|
+
// ref: https://github.com/lifeomic/attempt/blob/master/src/index.ts#L136
|
|
1872
|
+
if (error && error.code !== 'ATTEMPT_ABORTED') {
|
|
1873
|
+
throw error;
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
createWebSocketConnection() {
|
|
1878
|
+
return new Promise((resolve, reject) => {
|
|
1879
|
+
// Init the WebSocket connection
|
|
1880
|
+
const ws = new this.configuration.WebSocketPolyfill(this.url);
|
|
1881
|
+
ws.binaryType = 'arraybuffer';
|
|
1882
|
+
ws.onmessage = this.onMessage.bind(this);
|
|
1883
|
+
ws.onclose = this.onClose.bind(this);
|
|
1884
|
+
ws.onopen = this.onOpen.bind(this);
|
|
1885
|
+
ws.onerror = (err) => {
|
|
1886
|
+
reject(err);
|
|
1887
|
+
};
|
|
1888
|
+
this.webSocket = ws;
|
|
1889
|
+
// Reset the status
|
|
1890
|
+
this.synced = false;
|
|
1891
|
+
this.status = WebSocketStatus.Connecting;
|
|
1892
|
+
this.emit('status', { status: WebSocketStatus.Connecting });
|
|
1893
|
+
// Store resolve/reject for later use
|
|
1894
|
+
this.connectionAttempt = {
|
|
1895
|
+
resolve,
|
|
1896
|
+
reject,
|
|
1897
|
+
};
|
|
1898
|
+
});
|
|
1899
|
+
}
|
|
1900
|
+
resolveConnectionAttempt() {
|
|
1901
|
+
var _a;
|
|
1902
|
+
(_a = this.connectionAttempt) === null || _a === void 0 ? void 0 : _a.resolve();
|
|
1903
|
+
this.connectionAttempt = null;
|
|
1904
|
+
this.status = WebSocketStatus.Connected;
|
|
1905
|
+
this.emit('status', { status: WebSocketStatus.Connected });
|
|
1906
|
+
this.emit('connect');
|
|
1907
|
+
}
|
|
1908
|
+
stopConnectionAttempt() {
|
|
1909
|
+
this.connectionAttempt = null;
|
|
1781
1910
|
}
|
|
1782
|
-
|
|
1783
|
-
|
|
1911
|
+
rejectConnectionAttempt() {
|
|
1912
|
+
var _a;
|
|
1913
|
+
(_a = this.connectionAttempt) === null || _a === void 0 ? void 0 : _a.reject();
|
|
1914
|
+
this.connectionAttempt = null;
|
|
1784
1915
|
}
|
|
1785
1916
|
get document() {
|
|
1786
|
-
return this.
|
|
1917
|
+
return this.configuration.document;
|
|
1787
1918
|
}
|
|
1788
1919
|
get awareness() {
|
|
1789
|
-
return this.
|
|
1920
|
+
return this.configuration.awareness;
|
|
1921
|
+
}
|
|
1922
|
+
get hasUnsyncedChanges() {
|
|
1923
|
+
return this.unsyncedChanges > 0;
|
|
1790
1924
|
}
|
|
1791
1925
|
checkConnection() {
|
|
1926
|
+
var _a;
|
|
1927
|
+
// Don’t check the connection when it’s not even established
|
|
1792
1928
|
if (this.status !== WebSocketStatus.Connected) {
|
|
1793
1929
|
return;
|
|
1794
1930
|
}
|
|
1795
|
-
|
|
1931
|
+
// Don’t close then connection while waiting for the first message
|
|
1932
|
+
if (!this.lastMessageReceived) {
|
|
1933
|
+
return;
|
|
1934
|
+
}
|
|
1935
|
+
// Don’t close the connection when a message was received recently
|
|
1936
|
+
if (this.configuration.messageReconnectTimeout >= getUnixTime() - this.lastMessageReceived) {
|
|
1796
1937
|
return;
|
|
1797
1938
|
}
|
|
1798
1939
|
// No message received in a long time, not even your own
|
|
1799
1940
|
// Awareness updates, which are updated every 15 seconds.
|
|
1800
|
-
this.webSocket.close();
|
|
1941
|
+
(_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.close();
|
|
1801
1942
|
}
|
|
1802
1943
|
forceSync() {
|
|
1803
1944
|
if (!this.webSocket) {
|
|
@@ -1805,18 +1946,21 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1805
1946
|
}
|
|
1806
1947
|
this.send(SyncStepOneMessage, { document: this.document });
|
|
1807
1948
|
}
|
|
1808
|
-
|
|
1949
|
+
beforeUnload() {
|
|
1950
|
+
removeAwarenessStates(this.awareness, [this.document.clientID], 'window unload');
|
|
1951
|
+
}
|
|
1952
|
+
registerEventListeners() {
|
|
1809
1953
|
if (typeof window === 'undefined') {
|
|
1810
1954
|
return;
|
|
1811
1955
|
}
|
|
1812
|
-
window.addEventListener('
|
|
1813
|
-
|
|
1814
|
-
});
|
|
1956
|
+
window.addEventListener('online', this.boundConnect);
|
|
1957
|
+
window.addEventListener('beforeunload', this.boundBeforeUnload);
|
|
1815
1958
|
}
|
|
1816
1959
|
documentUpdateHandler(update, origin) {
|
|
1817
1960
|
if (origin === this) {
|
|
1818
1961
|
return;
|
|
1819
1962
|
}
|
|
1963
|
+
this.unsyncedChanges += 1;
|
|
1820
1964
|
this.send(UpdateMessage, { update }, true);
|
|
1821
1965
|
}
|
|
1822
1966
|
awarenessUpdateHandler({ added, updated, removed }, origin) {
|
|
@@ -1826,16 +1970,26 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1826
1970
|
clients: changedClients,
|
|
1827
1971
|
}, true);
|
|
1828
1972
|
}
|
|
1973
|
+
permissionDeniedHandler(reason) {
|
|
1974
|
+
this.emit('authenticationFailed', { reason });
|
|
1975
|
+
this.isAuthenticated = false;
|
|
1976
|
+
this.shouldConnect = false;
|
|
1977
|
+
}
|
|
1978
|
+
authenticatedHandler() {
|
|
1979
|
+
this.isAuthenticated = true;
|
|
1980
|
+
this.emit('authenticated');
|
|
1981
|
+
this.startSync();
|
|
1982
|
+
}
|
|
1829
1983
|
// Ensure that the URL always ends with /
|
|
1830
1984
|
get serverUrl() {
|
|
1831
|
-
while (this.
|
|
1832
|
-
return this.
|
|
1985
|
+
while (this.configuration.url[this.configuration.url.length - 1] === '/') {
|
|
1986
|
+
return this.configuration.url.slice(0, this.configuration.url.length - 1);
|
|
1833
1987
|
}
|
|
1834
|
-
return this.
|
|
1988
|
+
return this.configuration.url;
|
|
1835
1989
|
}
|
|
1836
1990
|
get url() {
|
|
1837
|
-
const encodedParams = encodeQueryParams(this.
|
|
1838
|
-
return `${this.serverUrl}/${this.
|
|
1991
|
+
const encodedParams = encodeQueryParams(this.configuration.parameters);
|
|
1992
|
+
return `${this.serverUrl}/${this.configuration.name}${encodedParams.length === 0 ? '' : `?${encodedParams}`}`;
|
|
1839
1993
|
}
|
|
1840
1994
|
get synced() {
|
|
1841
1995
|
return this.isSynced;
|
|
@@ -1848,12 +2002,8 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1848
2002
|
this.emit('synced', { state });
|
|
1849
2003
|
this.emit('sync', { state });
|
|
1850
2004
|
}
|
|
1851
|
-
|
|
1852
|
-
this.
|
|
1853
|
-
if (this.status !== WebSocketStatus.Connected) {
|
|
1854
|
-
this.createWebSocketConnection();
|
|
1855
|
-
this.subscribeToBroadcastChannel();
|
|
1856
|
-
}
|
|
2005
|
+
get isAuthenticationRequired() {
|
|
2006
|
+
return !!this.configuration.token && !this.isAuthenticated;
|
|
1857
2007
|
}
|
|
1858
2008
|
disconnect() {
|
|
1859
2009
|
this.shouldConnect = false;
|
|
@@ -1868,27 +2018,24 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1868
2018
|
//
|
|
1869
2019
|
}
|
|
1870
2020
|
}
|
|
1871
|
-
|
|
1872
|
-
|
|
2021
|
+
async onOpen(event) {
|
|
2022
|
+
this.emit('open', { event });
|
|
2023
|
+
if (this.isAuthenticationRequired) {
|
|
2024
|
+
this.send(AuthenticationMessage, {
|
|
2025
|
+
token: await this.getToken(),
|
|
2026
|
+
});
|
|
1873
2027
|
return;
|
|
1874
2028
|
}
|
|
1875
|
-
this.
|
|
1876
|
-
this.webSocket.binaryType = 'arraybuffer';
|
|
1877
|
-
this.status = WebSocketStatus.Connecting;
|
|
1878
|
-
this.synced = false;
|
|
1879
|
-
this.webSocket.onmessage = this.onMessage.bind(this);
|
|
1880
|
-
this.webSocket.onclose = this.onClose.bind(this);
|
|
1881
|
-
this.webSocket.onopen = this.onOpen.bind(this);
|
|
1882
|
-
this.emit('status', { status: 'connecting' });
|
|
2029
|
+
this.startSync();
|
|
1883
2030
|
}
|
|
1884
|
-
|
|
1885
|
-
this.
|
|
2031
|
+
async getToken() {
|
|
2032
|
+
if (typeof this.configuration.token === 'function') {
|
|
2033
|
+
const token = await this.configuration.token();
|
|
2034
|
+
return token;
|
|
2035
|
+
}
|
|
2036
|
+
return this.configuration.token;
|
|
1886
2037
|
}
|
|
1887
|
-
|
|
1888
|
-
this.failedConnectionAttempts = 0;
|
|
1889
|
-
this.status = WebSocketStatus.Connected;
|
|
1890
|
-
this.emit('status', { status: 'connected' });
|
|
1891
|
-
this.emit('connect');
|
|
2038
|
+
startSync() {
|
|
1892
2039
|
this.send(SyncStepOneMessage, { document: this.document });
|
|
1893
2040
|
if (this.awareness.getLocalState() !== null) {
|
|
1894
2041
|
this.send(AwarenessMessage, {
|
|
@@ -1898,56 +2045,66 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1898
2045
|
}
|
|
1899
2046
|
}
|
|
1900
2047
|
send(Message, args, broadcast = false) {
|
|
1901
|
-
|
|
2048
|
+
var _a;
|
|
1902
2049
|
if (broadcast) {
|
|
1903
|
-
this.mux(() => {
|
|
1904
|
-
this.broadcast(Message, args);
|
|
1905
|
-
});
|
|
2050
|
+
this.mux(() => { this.broadcast(Message, args); });
|
|
1906
2051
|
}
|
|
1907
|
-
if (this.
|
|
2052
|
+
if (((_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.readyState) === WsReadyStates.Open) {
|
|
1908
2053
|
const messageSender = new MessageSender(Message, args);
|
|
1909
2054
|
this.emit('outgoingMessage', { message: messageSender.message });
|
|
1910
2055
|
messageSender.send(this.webSocket);
|
|
1911
2056
|
}
|
|
1912
2057
|
}
|
|
1913
2058
|
onMessage(event) {
|
|
1914
|
-
|
|
1915
|
-
this.webSocketConnectionEstablished();
|
|
1916
|
-
}
|
|
2059
|
+
this.resolveConnectionAttempt();
|
|
1917
2060
|
this.lastMessageReceived = getUnixTime();
|
|
1918
2061
|
const message = new IncomingMessage(event.data);
|
|
1919
2062
|
this.emit('message', { event, message });
|
|
1920
|
-
new MessageReceiver(message
|
|
1921
|
-
// TODO: What’s that doing?
|
|
1922
|
-
// if (encoding.length(encoder) > 1) {
|
|
1923
|
-
// this.send(encoding.toUint8Array(encoder))
|
|
1924
|
-
// }
|
|
2063
|
+
new MessageReceiver(message).apply(this);
|
|
1925
2064
|
}
|
|
1926
2065
|
onClose(event) {
|
|
1927
2066
|
this.emit('close', { event });
|
|
1928
2067
|
this.webSocket = null;
|
|
2068
|
+
this.isAuthenticated = false;
|
|
2069
|
+
this.synced = false;
|
|
1929
2070
|
if (this.status === WebSocketStatus.Connected) {
|
|
1930
|
-
this.synced = false;
|
|
1931
2071
|
// update awareness (all users except local left)
|
|
1932
2072
|
removeAwarenessStates(this.awareness, Array.from(this.awareness.getStates().keys()).filter(client => client !== this.document.clientID), this);
|
|
1933
2073
|
this.status = WebSocketStatus.Disconnected;
|
|
1934
|
-
this.emit('status', { status:
|
|
2074
|
+
this.emit('status', { status: WebSocketStatus.Disconnected });
|
|
1935
2075
|
this.emit('disconnect', { event });
|
|
1936
2076
|
}
|
|
1937
|
-
|
|
1938
|
-
this.
|
|
2077
|
+
if (event.code === Unauthorized.code) {
|
|
2078
|
+
if (!this.configuration.quiet) {
|
|
2079
|
+
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.');
|
|
2080
|
+
}
|
|
2081
|
+
this.shouldConnect = false;
|
|
1939
2082
|
}
|
|
2083
|
+
if (event.code === Forbidden.code) {
|
|
2084
|
+
if (!this.configuration.quiet) {
|
|
2085
|
+
console.warn('[HocuspocusProvider] The provided authentication token isn’t allowed to connect to this server. Will try again.');
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
if (this.connectionAttempt) {
|
|
2089
|
+
// That connection attempt failed.
|
|
2090
|
+
this.rejectConnectionAttempt();
|
|
2091
|
+
}
|
|
2092
|
+
else if (this.shouldConnect) {
|
|
2093
|
+
// The connection was closed by the server. Let’s just try again.
|
|
2094
|
+
this.connect();
|
|
2095
|
+
}
|
|
2096
|
+
// If we’ll reconnect, we’re done for now.
|
|
1940
2097
|
if (this.shouldConnect) {
|
|
1941
|
-
const wait = round(min(log10(this.failedConnectionAttempts + 1) * this.options.reconnectTimeoutBase, this.options.maxReconnectTimeout));
|
|
1942
|
-
this.log(`[close] Reconnecting in ${wait}ms …`);
|
|
1943
|
-
setTimeout(this.createWebSocketConnection.bind(this), wait);
|
|
1944
2098
|
return;
|
|
1945
2099
|
}
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
this.emit('disconnect', { event });
|
|
2100
|
+
// The status is set correctly already.
|
|
2101
|
+
if (this.status === WebSocketStatus.Disconnected) {
|
|
2102
|
+
return;
|
|
1950
2103
|
}
|
|
2104
|
+
// Let’s update the connection status.
|
|
2105
|
+
this.status = WebSocketStatus.Disconnected;
|
|
2106
|
+
this.emit('status', { status: WebSocketStatus.Disconnected });
|
|
2107
|
+
this.emit('disconnect', { event });
|
|
1951
2108
|
}
|
|
1952
2109
|
destroy() {
|
|
1953
2110
|
this.emit('destroy');
|
|
@@ -1955,27 +2112,35 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1955
2112
|
clearInterval(this.intervals.forceSync);
|
|
1956
2113
|
}
|
|
1957
2114
|
clearInterval(this.intervals.connectionChecker);
|
|
2115
|
+
removeAwarenessStates(this.awareness, [this.document.clientID], 'provider destroy');
|
|
2116
|
+
// If there is still a connection attempt outstanding then we should stop
|
|
2117
|
+
// it before calling disconnect, otherwise it will be rejected in the onClose
|
|
2118
|
+
// handler and trigger a retry
|
|
2119
|
+
this.stopConnectionAttempt();
|
|
1958
2120
|
this.disconnect();
|
|
1959
2121
|
this.awareness.off('update', this.awarenessUpdateHandler);
|
|
1960
2122
|
this.document.off('update', this.documentUpdateHandler);
|
|
1961
2123
|
this.removeAllListeners();
|
|
2124
|
+
if (typeof window === 'undefined') {
|
|
2125
|
+
return;
|
|
2126
|
+
}
|
|
2127
|
+
window.removeEventListener('online', this.boundConnect);
|
|
2128
|
+
window.removeEventListener('beforeunload', this.boundBeforeUnload);
|
|
1962
2129
|
}
|
|
1963
2130
|
get broadcastChannel() {
|
|
1964
|
-
return `${this.serverUrl}/${this.
|
|
2131
|
+
return `${this.serverUrl}/${this.configuration.name}`;
|
|
1965
2132
|
}
|
|
1966
2133
|
broadcastChannelSubscriber(data) {
|
|
1967
2134
|
this.mux(() => {
|
|
1968
2135
|
const message = new IncomingMessage(data);
|
|
1969
|
-
new MessageReceiver(message
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
// this.broadcast(encoding.toUint8Array(encoder))
|
|
1973
|
-
// }
|
|
2136
|
+
new MessageReceiver(message)
|
|
2137
|
+
.setBroadcasted(true)
|
|
2138
|
+
.apply(this, false);
|
|
1974
2139
|
});
|
|
1975
2140
|
}
|
|
1976
2141
|
subscribeToBroadcastChannel() {
|
|
1977
2142
|
if (!this.subscribedToBroadcastChannel) {
|
|
1978
|
-
subscribe(this.broadcastChannel, this.
|
|
2143
|
+
subscribe(this.broadcastChannel, this.boundBroadcastChannelSubscriber);
|
|
1979
2144
|
this.subscribedToBroadcastChannel = true;
|
|
1980
2145
|
}
|
|
1981
2146
|
this.mux(() => {
|
|
@@ -1993,25 +2158,38 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1993
2158
|
states: new Map(),
|
|
1994
2159
|
}, true);
|
|
1995
2160
|
if (this.subscribedToBroadcastChannel) {
|
|
1996
|
-
unsubscribe(this.broadcastChannel, this.
|
|
2161
|
+
unsubscribe(this.broadcastChannel, this.boundBroadcastChannelSubscriber);
|
|
1997
2162
|
this.subscribedToBroadcastChannel = false;
|
|
1998
2163
|
}
|
|
1999
2164
|
}
|
|
2000
2165
|
broadcast(Message, args) {
|
|
2001
|
-
if (this.
|
|
2002
|
-
|
|
2166
|
+
if (!this.configuration.broadcast) {
|
|
2167
|
+
return;
|
|
2003
2168
|
}
|
|
2004
|
-
|
|
2005
|
-
log(message) {
|
|
2006
|
-
if (!this.options.debug) {
|
|
2169
|
+
if (!this.subscribedToBroadcastChannel) {
|
|
2007
2170
|
return;
|
|
2008
2171
|
}
|
|
2009
|
-
|
|
2172
|
+
new MessageSender(Message, args).broadcast(this.broadcastChannel);
|
|
2010
2173
|
}
|
|
2011
2174
|
setAwarenessField(key, value) {
|
|
2012
2175
|
this.awareness.setLocalStateField(key, value);
|
|
2013
2176
|
}
|
|
2014
2177
|
}
|
|
2015
2178
|
|
|
2016
|
-
|
|
2179
|
+
class HocuspocusCloudProvider extends HocuspocusProvider {
|
|
2180
|
+
constructor(configuration) {
|
|
2181
|
+
if (!configuration.url) {
|
|
2182
|
+
configuration.url = 'wss://connect.hocuspocus.cloud';
|
|
2183
|
+
}
|
|
2184
|
+
if (configuration.key) {
|
|
2185
|
+
if (!configuration.parameters) {
|
|
2186
|
+
configuration.parameters = {};
|
|
2187
|
+
}
|
|
2188
|
+
configuration.parameters.key = configuration.key;
|
|
2189
|
+
}
|
|
2190
|
+
super(configuration);
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
export { HocuspocusCloudProvider, HocuspocusProvider, MessageType, WebSocketStatus };
|
|
2017
2195
|
//# sourceMappingURL=hocuspocus-provider.esm.js.map
|