@hocuspocus/provider 1.1.0 → 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 +352 -217
- package/dist/hocuspocus-provider.cjs.map +1 -1
- package/dist/hocuspocus-provider.esm.js +352 -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 +10 -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/index.d.ts +1 -0
- package/dist/packages/provider/src/types.d.ts +1 -0
- package/dist/packages/server/src/Connection.d.ts +1 -11
- 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/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 +100 -360
- 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/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 +1 -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
|
}
|
|
@@ -1585,6 +1578,7 @@ class MessageReceiver {
|
|
|
1585
1578
|
apply(provider, emitSynced = true) {
|
|
1586
1579
|
const { message } = this;
|
|
1587
1580
|
const type = message.readVarUint();
|
|
1581
|
+
const emptyMessageLength = message.length();
|
|
1588
1582
|
switch (type) {
|
|
1589
1583
|
case exports.MessageType.Sync:
|
|
1590
1584
|
this.applySyncMessage(provider, emitSynced);
|
|
@@ -1605,7 +1599,7 @@ class MessageReceiver {
|
|
|
1605
1599
|
throw new Error(`Can’t apply message of unknown type: ${type}`);
|
|
1606
1600
|
}
|
|
1607
1601
|
// Reply
|
|
1608
|
-
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)
|
|
1609
1603
|
if (this.broadcasted) {
|
|
1610
1604
|
// TODO: Some weird TypeScript error
|
|
1611
1605
|
// @ts-ignore
|
|
@@ -1624,7 +1618,7 @@ class MessageReceiver {
|
|
|
1624
1618
|
// Apply update
|
|
1625
1619
|
const syncMessageType = readSyncMessage(message.decoder, message.encoder, provider.document, provider);
|
|
1626
1620
|
// Synced once we receive Step2
|
|
1627
|
-
if (emitSynced &&
|
|
1621
|
+
if (emitSynced && syncMessageType === messageYjsSyncStep2) {
|
|
1628
1622
|
provider.synced = true;
|
|
1629
1623
|
}
|
|
1630
1624
|
if (syncMessageType === messageYjsUpdate || syncMessageType === messageYjsSyncStep2) {
|
|
@@ -1674,6 +1668,7 @@ class SyncStepOneMessage extends OutgoingMessage {
|
|
|
1674
1668
|
if (typeof args.document === 'undefined') {
|
|
1675
1669
|
throw new Error('The sync step one message requires document as an argument');
|
|
1676
1670
|
}
|
|
1671
|
+
writeVarString(this.encoder, args.documentName);
|
|
1677
1672
|
writeVarUint(this.encoder, this.type);
|
|
1678
1673
|
writeSyncStep1(this.encoder, args.document);
|
|
1679
1674
|
return this.encoder;
|
|
@@ -1690,6 +1685,7 @@ class SyncStepTwoMessage extends OutgoingMessage {
|
|
|
1690
1685
|
if (typeof args.document === 'undefined') {
|
|
1691
1686
|
throw new Error('The sync step two message requires document as an argument');
|
|
1692
1687
|
}
|
|
1688
|
+
writeVarString(this.encoder, args.documentName);
|
|
1693
1689
|
writeVarUint(this.encoder, this.type);
|
|
1694
1690
|
writeSyncStep2(this.encoder, args.document);
|
|
1695
1691
|
return this.encoder;
|
|
@@ -1703,6 +1699,9 @@ class QueryAwarenessMessage extends OutgoingMessage {
|
|
|
1703
1699
|
this.description = 'Queries awareness states';
|
|
1704
1700
|
}
|
|
1705
1701
|
get(args) {
|
|
1702
|
+
console.log('queryAwareness: writing string docName', args.documentName);
|
|
1703
|
+
console.log(this.encoder.cpos);
|
|
1704
|
+
writeVarString(this.encoder, args.documentName);
|
|
1706
1705
|
writeVarUint(this.encoder, this.type);
|
|
1707
1706
|
return this.encoder;
|
|
1708
1707
|
}
|
|
@@ -1718,6 +1717,7 @@ class AuthenticationMessage extends OutgoingMessage {
|
|
|
1718
1717
|
if (typeof args.token === 'undefined') {
|
|
1719
1718
|
throw new Error('The authentication message requires `token` as an argument.');
|
|
1720
1719
|
}
|
|
1720
|
+
writeVarString(this.encoder, args.documentName);
|
|
1721
1721
|
writeVarUint(this.encoder, this.type);
|
|
1722
1722
|
common.writeAuthentication(this.encoder, args.token);
|
|
1723
1723
|
return this.encoder;
|
|
@@ -1737,6 +1737,7 @@ class AwarenessMessage extends OutgoingMessage {
|
|
|
1737
1737
|
if (typeof args.clients === 'undefined') {
|
|
1738
1738
|
throw new Error('The awareness message requires clients as an argument');
|
|
1739
1739
|
}
|
|
1740
|
+
writeVarString(this.encoder, args.documentName);
|
|
1740
1741
|
writeVarUint(this.encoder, this.type);
|
|
1741
1742
|
let awarenessUpdate;
|
|
1742
1743
|
if (args.states === undefined) {
|
|
@@ -1757,6 +1758,7 @@ class UpdateMessage extends OutgoingMessage {
|
|
|
1757
1758
|
this.description = 'A document update';
|
|
1758
1759
|
}
|
|
1759
1760
|
get(args) {
|
|
1761
|
+
writeVarString(this.encoder, args.documentName);
|
|
1760
1762
|
writeVarUint(this.encoder, this.type);
|
|
1761
1763
|
writeUpdate(this.encoder, args.update);
|
|
1762
1764
|
return this.encoder;
|
|
@@ -1771,6 +1773,7 @@ class StatelessMessage extends OutgoingMessage {
|
|
|
1771
1773
|
}
|
|
1772
1774
|
get(args) {
|
|
1773
1775
|
var _a;
|
|
1776
|
+
writeVarString(this.encoder, args.documentName);
|
|
1774
1777
|
writeVarUint(this.encoder, this.type);
|
|
1775
1778
|
writeVarString(this.encoder, (_a = args.payload) !== null && _a !== void 0 ? _a : '');
|
|
1776
1779
|
return this.encoder;
|
|
@@ -1782,13 +1785,302 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1782
1785
|
super();
|
|
1783
1786
|
this.configuration = {
|
|
1784
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 = {
|
|
1785
2078
|
url: '',
|
|
1786
2079
|
// @ts-ignore
|
|
1787
2080
|
document: undefined,
|
|
1788
2081
|
// @ts-ignore
|
|
1789
2082
|
awareness: undefined,
|
|
1790
2083
|
WebSocketPolyfill: undefined,
|
|
1791
|
-
token: null,
|
|
1792
2084
|
parameters: {},
|
|
1793
2085
|
connect: true,
|
|
1794
2086
|
broadcast: true,
|
|
@@ -1811,29 +2103,22 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1811
2103
|
jitter: true,
|
|
1812
2104
|
// retry forever
|
|
1813
2105
|
timeout: 0,
|
|
1814
|
-
onAuthenticated: () => null,
|
|
1815
|
-
onAuthenticationFailed: () => null,
|
|
1816
2106
|
onOpen: () => null,
|
|
1817
2107
|
onConnect: () => null,
|
|
1818
2108
|
onMessage: () => null,
|
|
1819
2109
|
onOutgoingMessage: () => null,
|
|
1820
2110
|
onStatus: () => null,
|
|
1821
|
-
onSynced: () => null,
|
|
1822
2111
|
onDisconnect: () => null,
|
|
1823
2112
|
onClose: () => null,
|
|
1824
2113
|
onDestroy: () => null,
|
|
1825
2114
|
onAwarenessUpdate: () => null,
|
|
1826
2115
|
onAwarenessChange: () => null,
|
|
1827
|
-
onStateless: () => null,
|
|
1828
2116
|
quiet: false,
|
|
1829
2117
|
};
|
|
1830
2118
|
this.subscribedToBroadcastChannel = false;
|
|
1831
2119
|
this.webSocket = null;
|
|
1832
2120
|
this.shouldConnect = true;
|
|
1833
2121
|
this.status = exports.WebSocketStatus.Disconnected;
|
|
1834
|
-
this.isSynced = false;
|
|
1835
|
-
this.unsyncedChanges = 0;
|
|
1836
|
-
this.isAuthenticated = false;
|
|
1837
2122
|
this.lastMessageReceived = 0;
|
|
1838
2123
|
this.mux = createMutex();
|
|
1839
2124
|
this.intervals = {
|
|
@@ -1841,40 +2126,27 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1841
2126
|
connectionChecker: null,
|
|
1842
2127
|
};
|
|
1843
2128
|
this.connectionAttempt = null;
|
|
2129
|
+
this.receivedOnOpenPayload = undefined;
|
|
2130
|
+
this.receivedOnStatusPayload = undefined;
|
|
1844
2131
|
this.boundConnect = this.connect.bind(this);
|
|
1845
|
-
this.boundBeforeUnload = this.beforeUnload.bind(this);
|
|
1846
|
-
this.boundBroadcastChannelSubscriber = this.broadcastChannelSubscriber.bind(this);
|
|
1847
2132
|
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
2133
|
this.configuration.WebSocketPolyfill = configuration.WebSocketPolyfill ? configuration.WebSocketPolyfill : WebSocket;
|
|
1851
2134
|
this.on('open', this.configuration.onOpen);
|
|
1852
|
-
this.on('
|
|
1853
|
-
this.on('authenticationFailed', this.configuration.onAuthenticationFailed);
|
|
2135
|
+
this.on('open', this.onOpen.bind(this));
|
|
1854
2136
|
this.on('connect', this.configuration.onConnect);
|
|
1855
2137
|
this.on('message', this.configuration.onMessage);
|
|
1856
2138
|
this.on('outgoingMessage', this.configuration.onOutgoingMessage);
|
|
1857
|
-
this.on('synced', this.configuration.onSynced);
|
|
1858
2139
|
this.on('status', this.configuration.onStatus);
|
|
2140
|
+
this.on('status', this.onStatus.bind(this));
|
|
1859
2141
|
this.on('disconnect', this.configuration.onDisconnect);
|
|
1860
2142
|
this.on('close', this.configuration.onClose);
|
|
1861
2143
|
this.on('destroy', this.configuration.onDestroy);
|
|
1862
2144
|
this.on('awarenessUpdate', this.configuration.onAwarenessUpdate);
|
|
1863
2145
|
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));
|
|
2146
|
+
this.on('close', this.onClose.bind(this));
|
|
2147
|
+
this.on('message', this.onMessage.bind(this));
|
|
1873
2148
|
this.registerEventListeners();
|
|
1874
2149
|
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
2150
|
if (typeof configuration.connect !== 'undefined') {
|
|
1879
2151
|
this.shouldConnect = configuration.connect;
|
|
1880
2152
|
}
|
|
@@ -1883,6 +2155,23 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1883
2155
|
}
|
|
1884
2156
|
this.connect();
|
|
1885
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
|
+
}
|
|
1886
2175
|
setConfiguration(configuration = {}) {
|
|
1887
2176
|
this.configuration = { ...this.configuration, ...configuration };
|
|
1888
2177
|
}
|
|
@@ -1895,9 +2184,7 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1895
2184
|
this.cancelWebsocketRetry();
|
|
1896
2185
|
this.cancelWebsocketRetry = undefined;
|
|
1897
2186
|
}
|
|
1898
|
-
this.unsyncedChanges = 0; // set to 0 in case we got reconnected
|
|
1899
2187
|
this.shouldConnect = true;
|
|
1900
|
-
this.subscribeToBroadcastChannel();
|
|
1901
2188
|
const abortableRetry = () => {
|
|
1902
2189
|
let cancelAttempt = false;
|
|
1903
2190
|
const retryPromise = attempt.retry(this.createWebSocketConnection.bind(this), {
|
|
@@ -1941,15 +2228,14 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1941
2228
|
// Init the WebSocket connection
|
|
1942
2229
|
const ws = new this.configuration.WebSocketPolyfill(this.url);
|
|
1943
2230
|
ws.binaryType = 'arraybuffer';
|
|
1944
|
-
ws.onmessage = this.
|
|
1945
|
-
ws.onclose = this.
|
|
1946
|
-
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);
|
|
1947
2234
|
ws.onerror = (err) => {
|
|
1948
2235
|
reject(err);
|
|
1949
2236
|
};
|
|
1950
2237
|
this.webSocket = ws;
|
|
1951
2238
|
// Reset the status
|
|
1952
|
-
this.synced = false;
|
|
1953
2239
|
this.status = exports.WebSocketStatus.Connecting;
|
|
1954
2240
|
this.emit('status', { status: exports.WebSocketStatus.Connecting });
|
|
1955
2241
|
// Store resolve/reject for later use
|
|
@@ -1959,13 +2245,17 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1959
2245
|
};
|
|
1960
2246
|
});
|
|
1961
2247
|
}
|
|
2248
|
+
onMessage(event) {
|
|
2249
|
+
this.resolveConnectionAttempt();
|
|
2250
|
+
}
|
|
1962
2251
|
resolveConnectionAttempt() {
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
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
|
+
}
|
|
1969
2259
|
}
|
|
1970
2260
|
stopConnectionAttempt() {
|
|
1971
2261
|
this.connectionAttempt = null;
|
|
@@ -1975,15 +2265,6 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
1975
2265
|
(_a = this.connectionAttempt) === null || _a === void 0 ? void 0 : _a.reject();
|
|
1976
2266
|
this.connectionAttempt = null;
|
|
1977
2267
|
}
|
|
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
2268
|
checkConnection() {
|
|
1988
2269
|
var _a;
|
|
1989
2270
|
// Don’t check the connection when it’s not even established
|
|
@@ -2002,48 +2283,11 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
2002
2283
|
// Awareness updates, which are updated every 15 seconds.
|
|
2003
2284
|
(_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.close();
|
|
2004
2285
|
}
|
|
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
2286
|
registerEventListeners() {
|
|
2015
2287
|
if (typeof window === 'undefined') {
|
|
2016
2288
|
return;
|
|
2017
2289
|
}
|
|
2018
2290
|
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
2291
|
}
|
|
2048
2292
|
// Ensure that the URL always ends with /
|
|
2049
2293
|
get serverUrl() {
|
|
@@ -2054,28 +2298,10 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
2054
2298
|
}
|
|
2055
2299
|
get url() {
|
|
2056
2300
|
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;
|
|
2301
|
+
return `${this.serverUrl}${encodedParams.length === 0 ? '' : `?${encodedParams}`}`;
|
|
2075
2302
|
}
|
|
2076
2303
|
disconnect() {
|
|
2077
2304
|
this.shouldConnect = false;
|
|
2078
|
-
this.disconnectBroadcastChannel();
|
|
2079
2305
|
if (this.webSocket === null) {
|
|
2080
2306
|
return;
|
|
2081
2307
|
}
|
|
@@ -2086,58 +2312,15 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
2086
2312
|
//
|
|
2087
2313
|
}
|
|
2088
2314
|
}
|
|
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) {
|
|
2315
|
+
send(message) {
|
|
2116
2316
|
var _a;
|
|
2117
|
-
if (broadcast) {
|
|
2118
|
-
this.mux(() => { this.broadcast(Message, args); });
|
|
2119
|
-
}
|
|
2120
2317
|
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);
|
|
2318
|
+
this.webSocket.send(message);
|
|
2124
2319
|
}
|
|
2125
2320
|
}
|
|
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 });
|
|
2321
|
+
onClose({ event }) {
|
|
2135
2322
|
this.webSocket = null;
|
|
2136
|
-
this.isAuthenticated = false;
|
|
2137
|
-
this.synced = false;
|
|
2138
2323
|
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
2324
|
this.status = exports.WebSocketStatus.Disconnected;
|
|
2142
2325
|
this.emit('status', { status: exports.WebSocketStatus.Disconnected });
|
|
2143
2326
|
this.emit('disconnect', { event });
|
|
@@ -2151,6 +2334,7 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
2151
2334
|
if (event.code === common.Forbidden.code) {
|
|
2152
2335
|
if (!this.configuration.quiet) {
|
|
2153
2336
|
console.warn('[HocuspocusProvider] The provided authentication token isn’t allowed to connect to this server. Will try again.');
|
|
2337
|
+
return; // TODO REMOVE ME
|
|
2154
2338
|
}
|
|
2155
2339
|
}
|
|
2156
2340
|
if (this.connectionAttempt) {
|
|
@@ -2180,67 +2364,16 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
2180
2364
|
clearInterval(this.intervals.forceSync);
|
|
2181
2365
|
}
|
|
2182
2366
|
clearInterval(this.intervals.connectionChecker);
|
|
2183
|
-
removeAwarenessStates(this.awareness, [this.document.clientID], 'provider destroy');
|
|
2184
2367
|
// If there is still a connection attempt outstanding then we should stop
|
|
2185
2368
|
// it before calling disconnect, otherwise it will be rejected in the onClose
|
|
2186
2369
|
// handler and trigger a retry
|
|
2187
2370
|
this.stopConnectionAttempt();
|
|
2188
2371
|
this.disconnect();
|
|
2189
|
-
this.awareness.off('update', this.awarenessUpdateHandler);
|
|
2190
|
-
this.document.off('update', this.documentUpdateHandler);
|
|
2191
2372
|
this.removeAllListeners();
|
|
2192
2373
|
if (typeof window === 'undefined') {
|
|
2193
2374
|
return;
|
|
2194
2375
|
}
|
|
2195
2376
|
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
2377
|
}
|
|
2245
2378
|
}
|
|
2246
2379
|
|
|
@@ -2255,10 +2388,12 @@ class HocuspocusCloudProvider extends HocuspocusProvider {
|
|
|
2255
2388
|
}
|
|
2256
2389
|
configuration.parameters.key = configuration.key;
|
|
2257
2390
|
}
|
|
2391
|
+
configuration.websocketProvider = new HocuspocusProviderWebsocket({ url: configuration.url });
|
|
2258
2392
|
super(configuration);
|
|
2259
2393
|
}
|
|
2260
2394
|
}
|
|
2261
2395
|
|
|
2262
2396
|
exports.HocuspocusCloudProvider = HocuspocusCloudProvider;
|
|
2263
2397
|
exports.HocuspocusProvider = HocuspocusProvider;
|
|
2398
|
+
exports.HocuspocusProviderWebsocket = HocuspocusProviderWebsocket;
|
|
2264
2399
|
//# sourceMappingURL=hocuspocus-provider.cjs.map
|