@hocuspocus/provider 1.0.2 → 2.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hocuspocus-provider.cjs +370 -209
- package/dist/hocuspocus-provider.cjs.map +1 -1
- package/dist/hocuspocus-provider.esm.js +370 -210
- package/dist/hocuspocus-provider.esm.js.map +1 -1
- package/dist/packages/extension-monitor/src/Dashboard.d.ts +1 -1
- package/dist/packages/extension-monitor/src/index.d.ts +1 -1
- package/dist/packages/extension-redis/src/Redis.d.ts +19 -5
- package/dist/packages/provider/src/HocuspocusCloudProvider.d.ts +2 -1
- package/dist/packages/provider/src/HocuspocusProvider.d.ts +14 -70
- package/dist/packages/provider/src/HocuspocusProviderWebsocket.d.ts +115 -0
- package/dist/packages/provider/src/IncomingMessage.d.ts +2 -0
- package/dist/packages/provider/src/OutgoingMessages/StatelessMessage.d.ts +7 -0
- package/dist/packages/provider/src/index.d.ts +1 -0
- package/dist/packages/provider/src/types.d.ts +7 -1
- package/dist/packages/server/src/Connection.d.ts +10 -11
- package/dist/packages/server/src/Document.d.ts +9 -0
- package/dist/packages/server/src/Hocuspocus.d.ts +3 -8
- package/dist/packages/server/src/IncomingMessage.d.ts +2 -0
- package/dist/packages/server/src/MessageReceiver.d.ts +1 -2
- package/dist/packages/server/src/OutgoingMessage.d.ts +3 -1
- package/dist/packages/server/src/types.d.ts +19 -3
- package/dist/packages/transformer/src/Prosemirror.d.ts +1 -1
- package/dist/tests/providerwebsocket/configuration.d.ts +1 -0
- package/dist/tests/server/beforeBroadcastStateless.d.ts +1 -0
- package/dist/tests/server/onStateless.d.ts +1 -0
- package/dist/tests/utils/index.d.ts +1 -0
- package/dist/tests/utils/newHocuspocusProvider.d.ts +2 -2
- package/dist/tests/utils/newHocuspocusProviderWebsocket.d.ts +3 -0
- package/package.json +3 -3
- package/src/HocuspocusCloudProvider.ts +8 -1
- package/src/HocuspocusProvider.ts +111 -358
- package/src/HocuspocusProviderWebsocket.ts +475 -0
- package/src/IncomingMessage.ts +10 -0
- package/src/MessageReceiver.ts +9 -2
- package/src/OutgoingMessages/AuthenticationMessage.ts +2 -1
- package/src/OutgoingMessages/AwarenessMessage.ts +1 -0
- package/src/OutgoingMessages/QueryAwarenessMessage.ts +5 -0
- package/src/OutgoingMessages/StatelessMessage.ts +17 -0
- package/src/OutgoingMessages/SyncStepOneMessage.ts +1 -0
- package/src/OutgoingMessages/SyncStepTwoMessage.ts +1 -1
- package/src/OutgoingMessages/UpdateMessage.ts +3 -1
- package/src/index.ts +1 -0
- package/src/types.ts +7 -0
- /package/dist/tests/{provider/configuration.d.ts → extension-redis/onStateless.d.ts} +0 -0
- /package/dist/tests/{server/getDocumentName.d.ts → provider/onStateless.d.ts} +0 -0
|
@@ -3,8 +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
6
|
var common = require('@hocuspocus/common');
|
|
7
|
+
var attempt = require('@lifeomic/attempt');
|
|
8
8
|
|
|
9
9
|
function _interopNamespace(e) {
|
|
10
10
|
if (e && e.__esModule) return e;
|
|
@@ -1348,19 +1348,6 @@ const createMutex = () => {
|
|
|
1348
1348
|
}
|
|
1349
1349
|
};
|
|
1350
1350
|
|
|
1351
|
-
/**
|
|
1352
|
-
* Utility module to work with urls.
|
|
1353
|
-
*
|
|
1354
|
-
* @module url
|
|
1355
|
-
*/
|
|
1356
|
-
|
|
1357
|
-
/**
|
|
1358
|
-
* @param {Object<string,string>} params
|
|
1359
|
-
* @return {string}
|
|
1360
|
-
*/
|
|
1361
|
-
const encodeQueryParams = params =>
|
|
1362
|
-
map(params, (val, key) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`).join('&');
|
|
1363
|
-
|
|
1364
1351
|
class EventEmitter {
|
|
1365
1352
|
constructor() {
|
|
1366
1353
|
this.callbacks = {};
|
|
@@ -1405,12 +1392,18 @@ class IncomingMessage {
|
|
|
1405
1392
|
readVarUint() {
|
|
1406
1393
|
return readVarUint(this.decoder);
|
|
1407
1394
|
}
|
|
1395
|
+
readVarString() {
|
|
1396
|
+
return readVarString(this.decoder);
|
|
1397
|
+
}
|
|
1408
1398
|
readVarUint8Array() {
|
|
1409
1399
|
return readVarUint8Array(this.decoder);
|
|
1410
1400
|
}
|
|
1411
1401
|
writeVarUint(type) {
|
|
1412
1402
|
return writeVarUint(this.encoder, type);
|
|
1413
1403
|
}
|
|
1404
|
+
writeVarString(string) {
|
|
1405
|
+
return writeVarString(this.encoder, string);
|
|
1406
|
+
}
|
|
1414
1407
|
writeVarUint8Array(data) {
|
|
1415
1408
|
return writeVarUint8Array(this.encoder, data);
|
|
1416
1409
|
}
|
|
@@ -1552,6 +1545,7 @@ exports.MessageType = void 0;
|
|
|
1552
1545
|
MessageType[MessageType["Awareness"] = 1] = "Awareness";
|
|
1553
1546
|
MessageType[MessageType["Auth"] = 2] = "Auth";
|
|
1554
1547
|
MessageType[MessageType["QueryAwareness"] = 3] = "QueryAwareness";
|
|
1548
|
+
MessageType[MessageType["Stateless"] = 5] = "Stateless";
|
|
1555
1549
|
})(exports.MessageType || (exports.MessageType = {}));
|
|
1556
1550
|
exports.WebSocketStatus = void 0;
|
|
1557
1551
|
(function (WebSocketStatus) {
|
|
@@ -1584,6 +1578,7 @@ class MessageReceiver {
|
|
|
1584
1578
|
apply(provider, emitSynced = true) {
|
|
1585
1579
|
const { message } = this;
|
|
1586
1580
|
const type = message.readVarUint();
|
|
1581
|
+
const emptyMessageLength = message.length();
|
|
1587
1582
|
switch (type) {
|
|
1588
1583
|
case exports.MessageType.Sync:
|
|
1589
1584
|
this.applySyncMessage(provider, emitSynced);
|
|
@@ -1597,11 +1592,14 @@ class MessageReceiver {
|
|
|
1597
1592
|
case exports.MessageType.QueryAwareness:
|
|
1598
1593
|
this.applyQueryAwarenessMessage(provider);
|
|
1599
1594
|
break;
|
|
1595
|
+
case exports.MessageType.Stateless:
|
|
1596
|
+
provider.receiveStateless(readVarString(message.decoder));
|
|
1597
|
+
break;
|
|
1600
1598
|
default:
|
|
1601
1599
|
throw new Error(`Can’t apply message of unknown type: ${type}`);
|
|
1602
1600
|
}
|
|
1603
1601
|
// Reply
|
|
1604
|
-
if (message.length() > 1) {
|
|
1602
|
+
if (message.length() > emptyMessageLength + 1) { // length of documentName (considered in emptyMessageLength plus length of yjs sync type, set in applySyncMessage)
|
|
1605
1603
|
if (this.broadcasted) {
|
|
1606
1604
|
// TODO: Some weird TypeScript error
|
|
1607
1605
|
// @ts-ignore
|
|
@@ -1620,7 +1618,7 @@ class MessageReceiver {
|
|
|
1620
1618
|
// Apply update
|
|
1621
1619
|
const syncMessageType = readSyncMessage(message.decoder, message.encoder, provider.document, provider);
|
|
1622
1620
|
// Synced once we receive Step2
|
|
1623
|
-
if (emitSynced &&
|
|
1621
|
+
if (emitSynced && syncMessageType === messageYjsSyncStep2) {
|
|
1624
1622
|
provider.synced = true;
|
|
1625
1623
|
}
|
|
1626
1624
|
if (syncMessageType === messageYjsUpdate || syncMessageType === messageYjsSyncStep2) {
|
|
@@ -1670,6 +1668,7 @@ class SyncStepOneMessage extends OutgoingMessage {
|
|
|
1670
1668
|
if (typeof args.document === 'undefined') {
|
|
1671
1669
|
throw new Error('The sync step one message requires document as an argument');
|
|
1672
1670
|
}
|
|
1671
|
+
writeVarString(this.encoder, args.documentName);
|
|
1673
1672
|
writeVarUint(this.encoder, this.type);
|
|
1674
1673
|
writeSyncStep1(this.encoder, args.document);
|
|
1675
1674
|
return this.encoder;
|
|
@@ -1686,6 +1685,7 @@ class SyncStepTwoMessage extends OutgoingMessage {
|
|
|
1686
1685
|
if (typeof args.document === 'undefined') {
|
|
1687
1686
|
throw new Error('The sync step two message requires document as an argument');
|
|
1688
1687
|
}
|
|
1688
|
+
writeVarString(this.encoder, args.documentName);
|
|
1689
1689
|
writeVarUint(this.encoder, this.type);
|
|
1690
1690
|
writeSyncStep2(this.encoder, args.document);
|
|
1691
1691
|
return this.encoder;
|
|
@@ -1699,6 +1699,9 @@ class QueryAwarenessMessage extends OutgoingMessage {
|
|
|
1699
1699
|
this.description = 'Queries awareness states';
|
|
1700
1700
|
}
|
|
1701
1701
|
get(args) {
|
|
1702
|
+
console.log('queryAwareness: writing string docName', args.documentName);
|
|
1703
|
+
console.log(this.encoder.cpos);
|
|
1704
|
+
writeVarString(this.encoder, args.documentName);
|
|
1702
1705
|
writeVarUint(this.encoder, this.type);
|
|
1703
1706
|
return this.encoder;
|
|
1704
1707
|
}
|
|
@@ -1714,6 +1717,7 @@ class AuthenticationMessage extends OutgoingMessage {
|
|
|
1714
1717
|
if (typeof args.token === 'undefined') {
|
|
1715
1718
|
throw new Error('The authentication message requires `token` as an argument.');
|
|
1716
1719
|
}
|
|
1720
|
+
writeVarString(this.encoder, args.documentName);
|
|
1717
1721
|
writeVarUint(this.encoder, this.type);
|
|
1718
1722
|
common.writeAuthentication(this.encoder, args.token);
|
|
1719
1723
|
return this.encoder;
|
|
@@ -1733,6 +1737,7 @@ class AwarenessMessage extends OutgoingMessage {
|
|
|
1733
1737
|
if (typeof args.clients === 'undefined') {
|
|
1734
1738
|
throw new Error('The awareness message requires clients as an argument');
|
|
1735
1739
|
}
|
|
1740
|
+
writeVarString(this.encoder, args.documentName);
|
|
1736
1741
|
writeVarUint(this.encoder, this.type);
|
|
1737
1742
|
let awarenessUpdate;
|
|
1738
1743
|
if (args.states === undefined) {
|
|
@@ -1753,24 +1758,329 @@ class UpdateMessage extends OutgoingMessage {
|
|
|
1753
1758
|
this.description = 'A document update';
|
|
1754
1759
|
}
|
|
1755
1760
|
get(args) {
|
|
1761
|
+
writeVarString(this.encoder, args.documentName);
|
|
1756
1762
|
writeVarUint(this.encoder, this.type);
|
|
1757
1763
|
writeUpdate(this.encoder, args.update);
|
|
1758
1764
|
return this.encoder;
|
|
1759
1765
|
}
|
|
1760
1766
|
}
|
|
1761
1767
|
|
|
1768
|
+
class StatelessMessage extends OutgoingMessage {
|
|
1769
|
+
constructor() {
|
|
1770
|
+
super(...arguments);
|
|
1771
|
+
this.type = exports.MessageType.Stateless;
|
|
1772
|
+
this.description = 'A stateless message';
|
|
1773
|
+
}
|
|
1774
|
+
get(args) {
|
|
1775
|
+
var _a;
|
|
1776
|
+
writeVarString(this.encoder, args.documentName);
|
|
1777
|
+
writeVarUint(this.encoder, this.type);
|
|
1778
|
+
writeVarString(this.encoder, (_a = args.payload) !== null && _a !== void 0 ? _a : '');
|
|
1779
|
+
return this.encoder;
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1762
1783
|
class HocuspocusProvider extends EventEmitter {
|
|
1763
1784
|
constructor(configuration) {
|
|
1764
1785
|
super();
|
|
1765
1786
|
this.configuration = {
|
|
1766
1787
|
name: '',
|
|
1788
|
+
// @ts-ignore
|
|
1789
|
+
document: undefined,
|
|
1790
|
+
// @ts-ignore
|
|
1791
|
+
awareness: undefined,
|
|
1792
|
+
token: null,
|
|
1793
|
+
parameters: {},
|
|
1794
|
+
broadcast: true,
|
|
1795
|
+
forceSyncInterval: false,
|
|
1796
|
+
onAuthenticated: () => null,
|
|
1797
|
+
onAuthenticationFailed: () => null,
|
|
1798
|
+
onOpen: () => null,
|
|
1799
|
+
onConnect: () => null,
|
|
1800
|
+
onMessage: () => null,
|
|
1801
|
+
onOutgoingMessage: () => null,
|
|
1802
|
+
onStatus: () => null,
|
|
1803
|
+
onSynced: () => null,
|
|
1804
|
+
onDisconnect: () => null,
|
|
1805
|
+
onClose: () => null,
|
|
1806
|
+
onDestroy: () => null,
|
|
1807
|
+
onAwarenessUpdate: () => null,
|
|
1808
|
+
onAwarenessChange: () => null,
|
|
1809
|
+
onStateless: () => null,
|
|
1810
|
+
quiet: false,
|
|
1811
|
+
};
|
|
1812
|
+
this.subscribedToBroadcastChannel = false;
|
|
1813
|
+
this.isSynced = false;
|
|
1814
|
+
this.unsyncedChanges = 0;
|
|
1815
|
+
this.status = exports.WebSocketStatus.Disconnected;
|
|
1816
|
+
this.isAuthenticated = false;
|
|
1817
|
+
this.mux = createMutex();
|
|
1818
|
+
this.intervals = {
|
|
1819
|
+
forceSync: null,
|
|
1820
|
+
};
|
|
1821
|
+
this.boundBeforeUnload = this.beforeUnload.bind(this);
|
|
1822
|
+
this.boundBroadcastChannelSubscriber = this.broadcastChannelSubscriber.bind(this);
|
|
1823
|
+
this.setConfiguration(configuration);
|
|
1824
|
+
this.configuration.document = configuration.document ? configuration.document : new Y__namespace.Doc();
|
|
1825
|
+
this.configuration.awareness = configuration.awareness ? configuration.awareness : new Awareness(this.document);
|
|
1826
|
+
this.on('open', this.configuration.onOpen);
|
|
1827
|
+
this.on('message', this.configuration.onMessage);
|
|
1828
|
+
this.on('outgoingMessage', this.configuration.onOutgoingMessage);
|
|
1829
|
+
this.on('synced', this.configuration.onSynced);
|
|
1830
|
+
this.on('destroy', this.configuration.onDestroy);
|
|
1831
|
+
this.on('awarenessUpdate', this.configuration.onAwarenessUpdate);
|
|
1832
|
+
this.on('awarenessChange', this.configuration.onAwarenessChange);
|
|
1833
|
+
this.on('stateless', this.configuration.onStateless);
|
|
1834
|
+
this.on('authenticated', this.configuration.onAuthenticated);
|
|
1835
|
+
this.on('authenticationFailed', this.configuration.onAuthenticationFailed);
|
|
1836
|
+
this.configuration.websocketProvider.on('connect', this.configuration.onConnect);
|
|
1837
|
+
this.configuration.websocketProvider.on('connect', (e) => this.emit('connect', e));
|
|
1838
|
+
this.configuration.websocketProvider.on('open', this.onOpen.bind(this));
|
|
1839
|
+
this.configuration.websocketProvider.on('open', (e) => this.emit('open', e));
|
|
1840
|
+
this.configuration.websocketProvider.on('message', this.onMessage.bind(this));
|
|
1841
|
+
this.configuration.websocketProvider.on('close', this.onClose.bind(this));
|
|
1842
|
+
this.configuration.websocketProvider.on('close', this.configuration.onClose);
|
|
1843
|
+
this.configuration.websocketProvider.on('close', (e) => this.emit('close', e));
|
|
1844
|
+
this.configuration.websocketProvider.on('status', this.onStatus.bind(this));
|
|
1845
|
+
this.configuration.websocketProvider.on('disconnect', this.configuration.onDisconnect);
|
|
1846
|
+
this.configuration.websocketProvider.on('disconnect', (e) => this.emit('disconnect', e));
|
|
1847
|
+
this.configuration.websocketProvider.on('destroy', this.configuration.onDestroy);
|
|
1848
|
+
this.configuration.websocketProvider.on('destroy', (e) => this.emit('destroy', e));
|
|
1849
|
+
this.awareness.on('update', () => {
|
|
1850
|
+
this.emit('awarenessUpdate', { states: common.awarenessStatesToArray(this.awareness.getStates()) });
|
|
1851
|
+
});
|
|
1852
|
+
this.awareness.on('change', () => {
|
|
1853
|
+
this.emit('awarenessChange', { states: common.awarenessStatesToArray(this.awareness.getStates()) });
|
|
1854
|
+
});
|
|
1855
|
+
this.document.on('update', this.documentUpdateHandler.bind(this));
|
|
1856
|
+
this.awareness.on('update', this.awarenessUpdateHandler.bind(this));
|
|
1857
|
+
this.registerEventListeners();
|
|
1858
|
+
if (this.configuration.forceSyncInterval) {
|
|
1859
|
+
this.intervals.forceSync = setInterval(this.forceSync.bind(this), this.configuration.forceSyncInterval);
|
|
1860
|
+
}
|
|
1861
|
+
this.configuration.websocketProvider.attach(this);
|
|
1862
|
+
}
|
|
1863
|
+
onStatus({ status }) {
|
|
1864
|
+
this.status = status;
|
|
1865
|
+
this.configuration.onStatus({ status });
|
|
1866
|
+
this.emit('status', { status });
|
|
1867
|
+
}
|
|
1868
|
+
setConfiguration(configuration = {}) {
|
|
1869
|
+
this.configuration = { ...this.configuration, ...configuration };
|
|
1870
|
+
}
|
|
1871
|
+
get document() {
|
|
1872
|
+
return this.configuration.document;
|
|
1873
|
+
}
|
|
1874
|
+
get awareness() {
|
|
1875
|
+
return this.configuration.awareness;
|
|
1876
|
+
}
|
|
1877
|
+
get hasUnsyncedChanges() {
|
|
1878
|
+
return this.unsyncedChanges > 0;
|
|
1879
|
+
}
|
|
1880
|
+
forceSync() {
|
|
1881
|
+
this.send(SyncStepOneMessage, { document: this.document, documentName: this.configuration.name });
|
|
1882
|
+
}
|
|
1883
|
+
beforeUnload() {
|
|
1884
|
+
removeAwarenessStates(this.awareness, [this.document.clientID], 'window unload');
|
|
1885
|
+
}
|
|
1886
|
+
registerEventListeners() {
|
|
1887
|
+
if (typeof window === 'undefined') {
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1890
|
+
window.addEventListener('beforeunload', this.boundBeforeUnload);
|
|
1891
|
+
}
|
|
1892
|
+
sendStateless(payload) {
|
|
1893
|
+
this.send(StatelessMessage, { documentName: this.configuration.name, payload });
|
|
1894
|
+
}
|
|
1895
|
+
documentUpdateHandler(update, origin) {
|
|
1896
|
+
if (origin === this) {
|
|
1897
|
+
return;
|
|
1898
|
+
}
|
|
1899
|
+
this.unsyncedChanges += 1;
|
|
1900
|
+
this.send(UpdateMessage, { update, documentName: this.configuration.name }, true);
|
|
1901
|
+
}
|
|
1902
|
+
awarenessUpdateHandler({ added, updated, removed }, origin) {
|
|
1903
|
+
const changedClients = added.concat(updated).concat(removed);
|
|
1904
|
+
this.send(AwarenessMessage, {
|
|
1905
|
+
awareness: this.awareness,
|
|
1906
|
+
clients: changedClients,
|
|
1907
|
+
documentName: this.configuration.name,
|
|
1908
|
+
}, true);
|
|
1909
|
+
}
|
|
1910
|
+
get synced() {
|
|
1911
|
+
return this.isSynced;
|
|
1912
|
+
}
|
|
1913
|
+
set synced(state) {
|
|
1914
|
+
if (this.isSynced === state) {
|
|
1915
|
+
return;
|
|
1916
|
+
}
|
|
1917
|
+
this.isSynced = state;
|
|
1918
|
+
this.emit('synced', { state });
|
|
1919
|
+
this.emit('sync', { state });
|
|
1920
|
+
}
|
|
1921
|
+
receiveStateless(payload) {
|
|
1922
|
+
this.emit('stateless', { payload });
|
|
1923
|
+
}
|
|
1924
|
+
get isAuthenticationRequired() {
|
|
1925
|
+
return !!this.configuration.token && !this.isAuthenticated;
|
|
1926
|
+
}
|
|
1927
|
+
disconnect() {
|
|
1928
|
+
this.disconnectBroadcastChannel();
|
|
1929
|
+
this.configuration.websocketProvider.detach(this);
|
|
1930
|
+
}
|
|
1931
|
+
async onOpen(event) {
|
|
1932
|
+
this.emit('open', { event });
|
|
1933
|
+
if (this.isAuthenticationRequired) {
|
|
1934
|
+
this.send(AuthenticationMessage, {
|
|
1935
|
+
token: await this.getToken(),
|
|
1936
|
+
documentName: this.configuration.name,
|
|
1937
|
+
});
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
this.startSync();
|
|
1941
|
+
}
|
|
1942
|
+
async getToken() {
|
|
1943
|
+
if (typeof this.configuration.token === 'function') {
|
|
1944
|
+
const token = await this.configuration.token();
|
|
1945
|
+
return token;
|
|
1946
|
+
}
|
|
1947
|
+
return this.configuration.token;
|
|
1948
|
+
}
|
|
1949
|
+
startSync() {
|
|
1950
|
+
this.send(SyncStepOneMessage, { document: this.document, documentName: this.configuration.name });
|
|
1951
|
+
if (this.awareness.getLocalState() !== null) {
|
|
1952
|
+
this.send(AwarenessMessage, {
|
|
1953
|
+
awareness: this.awareness,
|
|
1954
|
+
clients: [this.document.clientID],
|
|
1955
|
+
documentName: this.configuration.name,
|
|
1956
|
+
});
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
send(message, args, broadcast = false) {
|
|
1960
|
+
if (broadcast) {
|
|
1961
|
+
this.mux(() => { this.broadcast(message, args); });
|
|
1962
|
+
}
|
|
1963
|
+
const messageSender = new MessageSender(message, args);
|
|
1964
|
+
this.emit('outgoingMessage', { message: messageSender.message });
|
|
1965
|
+
messageSender.send(this.configuration.websocketProvider);
|
|
1966
|
+
}
|
|
1967
|
+
onMessage(event) {
|
|
1968
|
+
const message = new IncomingMessage(event.data);
|
|
1969
|
+
const documentName = message.readVarString();
|
|
1970
|
+
if (documentName !== this.configuration.name) {
|
|
1971
|
+
return; // message is meant for another provider
|
|
1972
|
+
}
|
|
1973
|
+
message.writeVarString(documentName);
|
|
1974
|
+
this.emit('message', { event, message: new IncomingMessage(event.data) });
|
|
1975
|
+
new MessageReceiver(message).apply(this);
|
|
1976
|
+
}
|
|
1977
|
+
onClose(event) {
|
|
1978
|
+
this.isAuthenticated = false;
|
|
1979
|
+
this.synced = false;
|
|
1980
|
+
// update awareness (all users except local left)
|
|
1981
|
+
removeAwarenessStates(this.awareness, Array.from(this.awareness.getStates().keys()).filter(client => client !== this.document.clientID), this);
|
|
1982
|
+
}
|
|
1983
|
+
destroy() {
|
|
1984
|
+
this.emit('destroy');
|
|
1985
|
+
if (this.intervals.forceSync) {
|
|
1986
|
+
clearInterval(this.intervals.forceSync);
|
|
1987
|
+
}
|
|
1988
|
+
removeAwarenessStates(this.awareness, [this.document.clientID], 'provider destroy');
|
|
1989
|
+
this.disconnect();
|
|
1990
|
+
this.awareness.off('update', this.awarenessUpdateHandler);
|
|
1991
|
+
this.document.off('update', this.documentUpdateHandler);
|
|
1992
|
+
this.removeAllListeners();
|
|
1993
|
+
if (typeof window === 'undefined') {
|
|
1994
|
+
return;
|
|
1995
|
+
}
|
|
1996
|
+
window.removeEventListener('beforeunload', this.boundBeforeUnload);
|
|
1997
|
+
}
|
|
1998
|
+
permissionDeniedHandler(reason) {
|
|
1999
|
+
this.emit('authenticationFailed', { reason });
|
|
2000
|
+
this.isAuthenticated = false;
|
|
2001
|
+
this.disconnect();
|
|
2002
|
+
this.status = exports.WebSocketStatus.Disconnected;
|
|
2003
|
+
}
|
|
2004
|
+
authenticatedHandler() {
|
|
2005
|
+
this.isAuthenticated = true;
|
|
2006
|
+
this.emit('authenticated');
|
|
2007
|
+
this.startSync();
|
|
2008
|
+
}
|
|
2009
|
+
get broadcastChannel() {
|
|
2010
|
+
return `${this.configuration.name}`;
|
|
2011
|
+
}
|
|
2012
|
+
broadcastChannelSubscriber(data) {
|
|
2013
|
+
this.mux(() => {
|
|
2014
|
+
const message = new IncomingMessage(data);
|
|
2015
|
+
const documentName = message.readVarString();
|
|
2016
|
+
message.writeVarString(documentName);
|
|
2017
|
+
new MessageReceiver(message)
|
|
2018
|
+
.setBroadcasted(true)
|
|
2019
|
+
.apply(this, false);
|
|
2020
|
+
});
|
|
2021
|
+
}
|
|
2022
|
+
subscribeToBroadcastChannel() {
|
|
2023
|
+
if (!this.subscribedToBroadcastChannel) {
|
|
2024
|
+
subscribe(this.broadcastChannel, this.boundBroadcastChannelSubscriber);
|
|
2025
|
+
this.subscribedToBroadcastChannel = true;
|
|
2026
|
+
}
|
|
2027
|
+
this.mux(() => {
|
|
2028
|
+
this.broadcast(SyncStepOneMessage, { document: this.document });
|
|
2029
|
+
this.broadcast(SyncStepTwoMessage, { document: this.document });
|
|
2030
|
+
this.broadcast(QueryAwarenessMessage, { document: this.document });
|
|
2031
|
+
this.broadcast(AwarenessMessage, { awareness: this.awareness, clients: [this.document.clientID], document: this.document });
|
|
2032
|
+
});
|
|
2033
|
+
}
|
|
2034
|
+
disconnectBroadcastChannel() {
|
|
2035
|
+
// broadcast message with local awareness state set to null (indicating disconnect)
|
|
2036
|
+
this.send(AwarenessMessage, {
|
|
2037
|
+
awareness: this.awareness,
|
|
2038
|
+
clients: [this.document.clientID],
|
|
2039
|
+
states: new Map(),
|
|
2040
|
+
documentName: this.configuration.name,
|
|
2041
|
+
}, true);
|
|
2042
|
+
if (this.subscribedToBroadcastChannel) {
|
|
2043
|
+
unsubscribe(this.broadcastChannel, this.boundBroadcastChannelSubscriber);
|
|
2044
|
+
this.subscribedToBroadcastChannel = false;
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
broadcast(Message, args) {
|
|
2048
|
+
if (!this.configuration.broadcast) {
|
|
2049
|
+
return;
|
|
2050
|
+
}
|
|
2051
|
+
if (!this.subscribedToBroadcastChannel) {
|
|
2052
|
+
return;
|
|
2053
|
+
}
|
|
2054
|
+
new MessageSender(Message, args).broadcast(this.broadcastChannel);
|
|
2055
|
+
}
|
|
2056
|
+
setAwarenessField(key, value) {
|
|
2057
|
+
this.awareness.setLocalStateField(key, value);
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
/**
|
|
2062
|
+
* Utility module to work with urls.
|
|
2063
|
+
*
|
|
2064
|
+
* @module url
|
|
2065
|
+
*/
|
|
2066
|
+
|
|
2067
|
+
/**
|
|
2068
|
+
* @param {Object<string,string>} params
|
|
2069
|
+
* @return {string}
|
|
2070
|
+
*/
|
|
2071
|
+
const encodeQueryParams = params =>
|
|
2072
|
+
map(params, (val, key) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`).join('&');
|
|
2073
|
+
|
|
2074
|
+
class HocuspocusProviderWebsocket extends EventEmitter {
|
|
2075
|
+
constructor(configuration) {
|
|
2076
|
+
super();
|
|
2077
|
+
this.configuration = {
|
|
1767
2078
|
url: '',
|
|
1768
2079
|
// @ts-ignore
|
|
1769
2080
|
document: undefined,
|
|
1770
2081
|
// @ts-ignore
|
|
1771
2082
|
awareness: undefined,
|
|
1772
2083
|
WebSocketPolyfill: undefined,
|
|
1773
|
-
token: null,
|
|
1774
2084
|
parameters: {},
|
|
1775
2085
|
connect: true,
|
|
1776
2086
|
broadcast: true,
|
|
@@ -1793,14 +2103,11 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1793
2103
|
jitter: true,
|
|
1794
2104
|
// retry forever
|
|
1795
2105
|
timeout: 0,
|
|
1796
|
-
onAuthenticated: () => null,
|
|
1797
|
-
onAuthenticationFailed: () => null,
|
|
1798
2106
|
onOpen: () => null,
|
|
1799
2107
|
onConnect: () => null,
|
|
1800
2108
|
onMessage: () => null,
|
|
1801
2109
|
onOutgoingMessage: () => null,
|
|
1802
2110
|
onStatus: () => null,
|
|
1803
|
-
onSynced: () => null,
|
|
1804
2111
|
onDisconnect: () => null,
|
|
1805
2112
|
onClose: () => null,
|
|
1806
2113
|
onDestroy: () => null,
|
|
@@ -1812,9 +2119,6 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1812
2119
|
this.webSocket = null;
|
|
1813
2120
|
this.shouldConnect = true;
|
|
1814
2121
|
this.status = exports.WebSocketStatus.Disconnected;
|
|
1815
|
-
this.isSynced = false;
|
|
1816
|
-
this.unsyncedChanges = 0;
|
|
1817
|
-
this.isAuthenticated = false;
|
|
1818
2122
|
this.lastMessageReceived = 0;
|
|
1819
2123
|
this.mux = createMutex();
|
|
1820
2124
|
this.intervals = {
|
|
@@ -1822,39 +2126,27 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1822
2126
|
connectionChecker: null,
|
|
1823
2127
|
};
|
|
1824
2128
|
this.connectionAttempt = null;
|
|
2129
|
+
this.receivedOnOpenPayload = undefined;
|
|
2130
|
+
this.receivedOnStatusPayload = undefined;
|
|
1825
2131
|
this.boundConnect = this.connect.bind(this);
|
|
1826
|
-
this.boundBeforeUnload = this.beforeUnload.bind(this);
|
|
1827
|
-
this.boundBroadcastChannelSubscriber = this.broadcastChannelSubscriber.bind(this);
|
|
1828
2132
|
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
2133
|
this.configuration.WebSocketPolyfill = configuration.WebSocketPolyfill ? configuration.WebSocketPolyfill : WebSocket;
|
|
1832
2134
|
this.on('open', this.configuration.onOpen);
|
|
1833
|
-
this.on('
|
|
1834
|
-
this.on('authenticationFailed', this.configuration.onAuthenticationFailed);
|
|
2135
|
+
this.on('open', this.onOpen.bind(this));
|
|
1835
2136
|
this.on('connect', this.configuration.onConnect);
|
|
1836
2137
|
this.on('message', this.configuration.onMessage);
|
|
1837
2138
|
this.on('outgoingMessage', this.configuration.onOutgoingMessage);
|
|
1838
|
-
this.on('synced', this.configuration.onSynced);
|
|
1839
2139
|
this.on('status', this.configuration.onStatus);
|
|
2140
|
+
this.on('status', this.onStatus.bind(this));
|
|
1840
2141
|
this.on('disconnect', this.configuration.onDisconnect);
|
|
1841
2142
|
this.on('close', this.configuration.onClose);
|
|
1842
2143
|
this.on('destroy', this.configuration.onDestroy);
|
|
1843
2144
|
this.on('awarenessUpdate', this.configuration.onAwarenessUpdate);
|
|
1844
2145
|
this.on('awarenessChange', this.configuration.onAwarenessChange);
|
|
1845
|
-
this.
|
|
1846
|
-
|
|
1847
|
-
});
|
|
1848
|
-
this.awareness.on('change', () => {
|
|
1849
|
-
this.emit('awarenessChange', { states: common.awarenessStatesToArray(this.awareness.getStates()) });
|
|
1850
|
-
});
|
|
1851
|
-
this.document.on('update', this.documentUpdateHandler.bind(this));
|
|
1852
|
-
this.awareness.on('update', this.awarenessUpdateHandler.bind(this));
|
|
2146
|
+
this.on('close', this.onClose.bind(this));
|
|
2147
|
+
this.on('message', this.onMessage.bind(this));
|
|
1853
2148
|
this.registerEventListeners();
|
|
1854
2149
|
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);
|
|
1857
|
-
}
|
|
1858
2150
|
if (typeof configuration.connect !== 'undefined') {
|
|
1859
2151
|
this.shouldConnect = configuration.connect;
|
|
1860
2152
|
}
|
|
@@ -1863,6 +2155,23 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1863
2155
|
}
|
|
1864
2156
|
this.connect();
|
|
1865
2157
|
}
|
|
2158
|
+
async onOpen(event) {
|
|
2159
|
+
this.receivedOnOpenPayload = event;
|
|
2160
|
+
}
|
|
2161
|
+
async onStatus(data) {
|
|
2162
|
+
this.receivedOnStatusPayload = data;
|
|
2163
|
+
}
|
|
2164
|
+
attach(provider) {
|
|
2165
|
+
if (this.receivedOnOpenPayload) {
|
|
2166
|
+
provider.onOpen(this.receivedOnOpenPayload);
|
|
2167
|
+
}
|
|
2168
|
+
if (this.receivedOnStatusPayload) {
|
|
2169
|
+
provider.onStatus(this.receivedOnStatusPayload);
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
detach(provider) {
|
|
2173
|
+
// tell the server to remove the listener
|
|
2174
|
+
}
|
|
1866
2175
|
setConfiguration(configuration = {}) {
|
|
1867
2176
|
this.configuration = { ...this.configuration, ...configuration };
|
|
1868
2177
|
}
|
|
@@ -1875,9 +2184,7 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1875
2184
|
this.cancelWebsocketRetry();
|
|
1876
2185
|
this.cancelWebsocketRetry = undefined;
|
|
1877
2186
|
}
|
|
1878
|
-
this.unsyncedChanges = 0; // set to 0 in case we got reconnected
|
|
1879
2187
|
this.shouldConnect = true;
|
|
1880
|
-
this.subscribeToBroadcastChannel();
|
|
1881
2188
|
const abortableRetry = () => {
|
|
1882
2189
|
let cancelAttempt = false;
|
|
1883
2190
|
const retryPromise = attempt.retry(this.createWebSocketConnection.bind(this), {
|
|
@@ -1921,15 +2228,14 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1921
2228
|
// Init the WebSocket connection
|
|
1922
2229
|
const ws = new this.configuration.WebSocketPolyfill(this.url);
|
|
1923
2230
|
ws.binaryType = 'arraybuffer';
|
|
1924
|
-
ws.onmessage = this.
|
|
1925
|
-
ws.onclose = this.
|
|
1926
|
-
ws.onopen = this.
|
|
2231
|
+
ws.onmessage = (payload) => this.emit('message', payload);
|
|
2232
|
+
ws.onclose = (payload) => this.emit('close', { event: payload });
|
|
2233
|
+
ws.onopen = (payload) => this.emit('open', payload);
|
|
1927
2234
|
ws.onerror = (err) => {
|
|
1928
2235
|
reject(err);
|
|
1929
2236
|
};
|
|
1930
2237
|
this.webSocket = ws;
|
|
1931
2238
|
// Reset the status
|
|
1932
|
-
this.synced = false;
|
|
1933
2239
|
this.status = exports.WebSocketStatus.Connecting;
|
|
1934
2240
|
this.emit('status', { status: exports.WebSocketStatus.Connecting });
|
|
1935
2241
|
// Store resolve/reject for later use
|
|
@@ -1939,13 +2245,17 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1939
2245
|
};
|
|
1940
2246
|
});
|
|
1941
2247
|
}
|
|
2248
|
+
onMessage(event) {
|
|
2249
|
+
this.resolveConnectionAttempt();
|
|
2250
|
+
}
|
|
1942
2251
|
resolveConnectionAttempt() {
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
2252
|
+
if (this.connectionAttempt) {
|
|
2253
|
+
this.connectionAttempt.resolve();
|
|
2254
|
+
this.connectionAttempt = null;
|
|
2255
|
+
this.status = exports.WebSocketStatus.Connected;
|
|
2256
|
+
this.emit('status', { status: exports.WebSocketStatus.Connected });
|
|
2257
|
+
this.emit('connect');
|
|
2258
|
+
}
|
|
1949
2259
|
}
|
|
1950
2260
|
stopConnectionAttempt() {
|
|
1951
2261
|
this.connectionAttempt = null;
|
|
@@ -1955,15 +2265,6 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1955
2265
|
(_a = this.connectionAttempt) === null || _a === void 0 ? void 0 : _a.reject();
|
|
1956
2266
|
this.connectionAttempt = null;
|
|
1957
2267
|
}
|
|
1958
|
-
get document() {
|
|
1959
|
-
return this.configuration.document;
|
|
1960
|
-
}
|
|
1961
|
-
get awareness() {
|
|
1962
|
-
return this.configuration.awareness;
|
|
1963
|
-
}
|
|
1964
|
-
get hasUnsyncedChanges() {
|
|
1965
|
-
return this.unsyncedChanges > 0;
|
|
1966
|
-
}
|
|
1967
2268
|
checkConnection() {
|
|
1968
2269
|
var _a;
|
|
1969
2270
|
// Don’t check the connection when it’s not even established
|
|
@@ -1982,45 +2283,11 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1982
2283
|
// Awareness updates, which are updated every 15 seconds.
|
|
1983
2284
|
(_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.close();
|
|
1984
2285
|
}
|
|
1985
|
-
forceSync() {
|
|
1986
|
-
if (!this.webSocket) {
|
|
1987
|
-
return;
|
|
1988
|
-
}
|
|
1989
|
-
this.send(SyncStepOneMessage, { document: this.document });
|
|
1990
|
-
}
|
|
1991
|
-
beforeUnload() {
|
|
1992
|
-
removeAwarenessStates(this.awareness, [this.document.clientID], 'window unload');
|
|
1993
|
-
}
|
|
1994
2286
|
registerEventListeners() {
|
|
1995
2287
|
if (typeof window === 'undefined') {
|
|
1996
2288
|
return;
|
|
1997
2289
|
}
|
|
1998
2290
|
window.addEventListener('online', this.boundConnect);
|
|
1999
|
-
window.addEventListener('beforeunload', this.boundBeforeUnload);
|
|
2000
|
-
}
|
|
2001
|
-
documentUpdateHandler(update, origin) {
|
|
2002
|
-
if (origin === this) {
|
|
2003
|
-
return;
|
|
2004
|
-
}
|
|
2005
|
-
this.unsyncedChanges += 1;
|
|
2006
|
-
this.send(UpdateMessage, { update }, true);
|
|
2007
|
-
}
|
|
2008
|
-
awarenessUpdateHandler({ added, updated, removed }, origin) {
|
|
2009
|
-
const changedClients = added.concat(updated).concat(removed);
|
|
2010
|
-
this.send(AwarenessMessage, {
|
|
2011
|
-
awareness: this.awareness,
|
|
2012
|
-
clients: changedClients,
|
|
2013
|
-
}, true);
|
|
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
2291
|
}
|
|
2025
2292
|
// Ensure that the URL always ends with /
|
|
2026
2293
|
get serverUrl() {
|
|
@@ -2031,25 +2298,10 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
2031
2298
|
}
|
|
2032
2299
|
get url() {
|
|
2033
2300
|
const encodedParams = encodeQueryParams(this.configuration.parameters);
|
|
2034
|
-
return `${this.serverUrl}
|
|
2035
|
-
}
|
|
2036
|
-
get synced() {
|
|
2037
|
-
return this.isSynced;
|
|
2038
|
-
}
|
|
2039
|
-
set synced(state) {
|
|
2040
|
-
if (this.isSynced === state) {
|
|
2041
|
-
return;
|
|
2042
|
-
}
|
|
2043
|
-
this.isSynced = state;
|
|
2044
|
-
this.emit('synced', { state });
|
|
2045
|
-
this.emit('sync', { state });
|
|
2046
|
-
}
|
|
2047
|
-
get isAuthenticationRequired() {
|
|
2048
|
-
return !!this.configuration.token && !this.isAuthenticated;
|
|
2301
|
+
return `${this.serverUrl}${encodedParams.length === 0 ? '' : `?${encodedParams}`}`;
|
|
2049
2302
|
}
|
|
2050
2303
|
disconnect() {
|
|
2051
2304
|
this.shouldConnect = false;
|
|
2052
|
-
this.disconnectBroadcastChannel();
|
|
2053
2305
|
if (this.webSocket === null) {
|
|
2054
2306
|
return;
|
|
2055
2307
|
}
|
|
@@ -2060,58 +2312,15 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
2060
2312
|
//
|
|
2061
2313
|
}
|
|
2062
2314
|
}
|
|
2063
|
-
|
|
2064
|
-
this.emit('open', { event });
|
|
2065
|
-
if (this.isAuthenticationRequired) {
|
|
2066
|
-
this.send(AuthenticationMessage, {
|
|
2067
|
-
token: await this.getToken(),
|
|
2068
|
-
});
|
|
2069
|
-
return;
|
|
2070
|
-
}
|
|
2071
|
-
this.startSync();
|
|
2072
|
-
}
|
|
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;
|
|
2079
|
-
}
|
|
2080
|
-
startSync() {
|
|
2081
|
-
this.send(SyncStepOneMessage, { document: this.document });
|
|
2082
|
-
if (this.awareness.getLocalState() !== null) {
|
|
2083
|
-
this.send(AwarenessMessage, {
|
|
2084
|
-
awareness: this.awareness,
|
|
2085
|
-
clients: [this.document.clientID],
|
|
2086
|
-
});
|
|
2087
|
-
}
|
|
2088
|
-
}
|
|
2089
|
-
send(Message, args, broadcast = false) {
|
|
2315
|
+
send(message) {
|
|
2090
2316
|
var _a;
|
|
2091
|
-
if (broadcast) {
|
|
2092
|
-
this.mux(() => { this.broadcast(Message, args); });
|
|
2093
|
-
}
|
|
2094
2317
|
if (((_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.readyState) === common.WsReadyStates.Open) {
|
|
2095
|
-
|
|
2096
|
-
this.emit('outgoingMessage', { message: messageSender.message });
|
|
2097
|
-
messageSender.send(this.webSocket);
|
|
2318
|
+
this.webSocket.send(message);
|
|
2098
2319
|
}
|
|
2099
2320
|
}
|
|
2100
|
-
|
|
2101
|
-
this.resolveConnectionAttempt();
|
|
2102
|
-
this.lastMessageReceived = getUnixTime();
|
|
2103
|
-
const message = new IncomingMessage(event.data);
|
|
2104
|
-
this.emit('message', { event, message });
|
|
2105
|
-
new MessageReceiver(message).apply(this);
|
|
2106
|
-
}
|
|
2107
|
-
onClose(event) {
|
|
2108
|
-
this.emit('close', { event });
|
|
2321
|
+
onClose({ event }) {
|
|
2109
2322
|
this.webSocket = null;
|
|
2110
|
-
this.isAuthenticated = false;
|
|
2111
|
-
this.synced = false;
|
|
2112
2323
|
if (this.status === exports.WebSocketStatus.Connected) {
|
|
2113
|
-
// update awareness (all users except local left)
|
|
2114
|
-
removeAwarenessStates(this.awareness, Array.from(this.awareness.getStates().keys()).filter(client => client !== this.document.clientID), this);
|
|
2115
2324
|
this.status = exports.WebSocketStatus.Disconnected;
|
|
2116
2325
|
this.emit('status', { status: exports.WebSocketStatus.Disconnected });
|
|
2117
2326
|
this.emit('disconnect', { event });
|
|
@@ -2125,6 +2334,7 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
2125
2334
|
if (event.code === common.Forbidden.code) {
|
|
2126
2335
|
if (!this.configuration.quiet) {
|
|
2127
2336
|
console.warn('[HocuspocusProvider] The provided authentication token isn’t allowed to connect to this server. Will try again.');
|
|
2337
|
+
return; // TODO REMOVE ME
|
|
2128
2338
|
}
|
|
2129
2339
|
}
|
|
2130
2340
|
if (this.connectionAttempt) {
|
|
@@ -2154,67 +2364,16 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
2154
2364
|
clearInterval(this.intervals.forceSync);
|
|
2155
2365
|
}
|
|
2156
2366
|
clearInterval(this.intervals.connectionChecker);
|
|
2157
|
-
removeAwarenessStates(this.awareness, [this.document.clientID], 'provider destroy');
|
|
2158
2367
|
// If there is still a connection attempt outstanding then we should stop
|
|
2159
2368
|
// it before calling disconnect, otherwise it will be rejected in the onClose
|
|
2160
2369
|
// handler and trigger a retry
|
|
2161
2370
|
this.stopConnectionAttempt();
|
|
2162
2371
|
this.disconnect();
|
|
2163
|
-
this.awareness.off('update', this.awarenessUpdateHandler);
|
|
2164
|
-
this.document.off('update', this.documentUpdateHandler);
|
|
2165
2372
|
this.removeAllListeners();
|
|
2166
2373
|
if (typeof window === 'undefined') {
|
|
2167
2374
|
return;
|
|
2168
2375
|
}
|
|
2169
2376
|
window.removeEventListener('online', this.boundConnect);
|
|
2170
|
-
window.removeEventListener('beforeunload', this.boundBeforeUnload);
|
|
2171
|
-
}
|
|
2172
|
-
get broadcastChannel() {
|
|
2173
|
-
return `${this.serverUrl}/${this.configuration.name}`;
|
|
2174
|
-
}
|
|
2175
|
-
broadcastChannelSubscriber(data) {
|
|
2176
|
-
this.mux(() => {
|
|
2177
|
-
const message = new IncomingMessage(data);
|
|
2178
|
-
new MessageReceiver(message)
|
|
2179
|
-
.setBroadcasted(true)
|
|
2180
|
-
.apply(this, false);
|
|
2181
|
-
});
|
|
2182
|
-
}
|
|
2183
|
-
subscribeToBroadcastChannel() {
|
|
2184
|
-
if (!this.subscribedToBroadcastChannel) {
|
|
2185
|
-
subscribe(this.broadcastChannel, this.boundBroadcastChannelSubscriber);
|
|
2186
|
-
this.subscribedToBroadcastChannel = true;
|
|
2187
|
-
}
|
|
2188
|
-
this.mux(() => {
|
|
2189
|
-
this.broadcast(SyncStepOneMessage, { document: this.document });
|
|
2190
|
-
this.broadcast(SyncStepTwoMessage, { document: this.document });
|
|
2191
|
-
this.broadcast(QueryAwarenessMessage);
|
|
2192
|
-
this.broadcast(AwarenessMessage, { awareness: this.awareness, clients: [this.document.clientID] });
|
|
2193
|
-
});
|
|
2194
|
-
}
|
|
2195
|
-
disconnectBroadcastChannel() {
|
|
2196
|
-
// broadcast message with local awareness state set to null (indicating disconnect)
|
|
2197
|
-
this.send(AwarenessMessage, {
|
|
2198
|
-
awareness: this.awareness,
|
|
2199
|
-
clients: [this.document.clientID],
|
|
2200
|
-
states: new Map(),
|
|
2201
|
-
}, true);
|
|
2202
|
-
if (this.subscribedToBroadcastChannel) {
|
|
2203
|
-
unsubscribe(this.broadcastChannel, this.boundBroadcastChannelSubscriber);
|
|
2204
|
-
this.subscribedToBroadcastChannel = false;
|
|
2205
|
-
}
|
|
2206
|
-
}
|
|
2207
|
-
broadcast(Message, args) {
|
|
2208
|
-
if (!this.configuration.broadcast) {
|
|
2209
|
-
return;
|
|
2210
|
-
}
|
|
2211
|
-
if (!this.subscribedToBroadcastChannel) {
|
|
2212
|
-
return;
|
|
2213
|
-
}
|
|
2214
|
-
new MessageSender(Message, args).broadcast(this.broadcastChannel);
|
|
2215
|
-
}
|
|
2216
|
-
setAwarenessField(key, value) {
|
|
2217
|
-
this.awareness.setLocalStateField(key, value);
|
|
2218
2377
|
}
|
|
2219
2378
|
}
|
|
2220
2379
|
|
|
@@ -2229,10 +2388,12 @@ class HocuspocusCloudProvider extends HocuspocusProvider {
|
|
|
2229
2388
|
}
|
|
2230
2389
|
configuration.parameters.key = configuration.key;
|
|
2231
2390
|
}
|
|
2391
|
+
configuration.websocketProvider = new HocuspocusProviderWebsocket({ url: configuration.url });
|
|
2232
2392
|
super(configuration);
|
|
2233
2393
|
}
|
|
2234
2394
|
}
|
|
2235
2395
|
|
|
2236
2396
|
exports.HocuspocusCloudProvider = HocuspocusCloudProvider;
|
|
2237
2397
|
exports.HocuspocusProvider = HocuspocusProvider;
|
|
2398
|
+
exports.HocuspocusProviderWebsocket = HocuspocusProviderWebsocket;
|
|
2238
2399
|
//# sourceMappingURL=hocuspocus-provider.cjs.map
|