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