@hocuspocus/provider 2.5.0 → 2.6.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.
@@ -1679,9 +1679,11 @@ class HocuspocusProviderWebsocket extends EventEmitter {
1679
1679
  };
1680
1680
  this.subscribedToBroadcastChannel = false;
1681
1681
  this.webSocket = null;
1682
+ this.webSocketHandlers = {};
1682
1683
  this.shouldConnect = true;
1683
1684
  this.status = exports.WebSocketStatus.Disconnected;
1684
1685
  this.lastMessageReceived = 0;
1686
+ this.identifier = 0;
1685
1687
  this.mux = createMutex();
1686
1688
  this.intervals = {
1687
1689
  forceSync: null,
@@ -1693,7 +1695,9 @@ class HocuspocusProviderWebsocket extends EventEmitter {
1693
1695
  this.boundConnect = this.connect.bind(this);
1694
1696
  this.closeTries = 0;
1695
1697
  this.setConfiguration(configuration);
1696
- this.configuration.WebSocketPolyfill = configuration.WebSocketPolyfill ? configuration.WebSocketPolyfill : WebSocket;
1698
+ this.configuration.WebSocketPolyfill = configuration.WebSocketPolyfill
1699
+ ? configuration.WebSocketPolyfill
1700
+ : WebSocket;
1697
1701
  this.on('open', this.configuration.onOpen);
1698
1702
  this.on('open', this.onOpen.bind(this));
1699
1703
  this.on('connect', this.configuration.onConnect);
@@ -1708,7 +1712,6 @@ class HocuspocusProviderWebsocket extends EventEmitter {
1708
1712
  this.on('awarenessChange', this.configuration.onAwarenessChange);
1709
1713
  this.on('close', this.onClose.bind(this));
1710
1714
  this.on('message', this.onMessage.bind(this));
1711
- this.registerEventListeners();
1712
1715
  this.intervals.connectionChecker = setInterval(this.checkConnection.bind(this), this.configuration.messageReconnectTimeout / 10);
1713
1716
  if (typeof configuration.connect !== 'undefined') {
1714
1717
  this.shouldConnect = configuration.connect;
@@ -1787,23 +1790,52 @@ class HocuspocusProviderWebsocket extends EventEmitter {
1787
1790
  this.cancelWebsocketRetry = cancelFunc;
1788
1791
  return retryPromise;
1789
1792
  }
1793
+ attachWebSocketListeners(ws, reject) {
1794
+ const { identifier } = ws;
1795
+ const onMessageHandler = (payload) => this.emit('message', payload);
1796
+ const onCloseHandler = (payload) => this.emit('close', { event: payload });
1797
+ const onOpenHandler = (payload) => this.emit('open', payload);
1798
+ const onErrorHandler = (err) => {
1799
+ reject(err);
1800
+ };
1801
+ this.webSocketHandlers[identifier] = {
1802
+ message: onMessageHandler,
1803
+ close: onCloseHandler,
1804
+ open: onOpenHandler,
1805
+ error: onErrorHandler,
1806
+ };
1807
+ const handlers = this.webSocketHandlers[ws.identifier];
1808
+ Object.keys(handlers).forEach(name => {
1809
+ ws.addEventListener(name, handlers[name]);
1810
+ });
1811
+ }
1812
+ cleanupWebSocket() {
1813
+ if (!this.webSocket) {
1814
+ return;
1815
+ }
1816
+ const { identifier } = this.webSocket;
1817
+ const handlers = this.webSocketHandlers[identifier];
1818
+ Object.keys(handlers).forEach(name => {
1819
+ var _a;
1820
+ (_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.removeEventListener(name, handlers[name]);
1821
+ delete this.webSocketHandlers[identifier];
1822
+ });
1823
+ this.webSocket.close();
1824
+ this.webSocket = null;
1825
+ }
1790
1826
  createWebSocketConnection() {
1791
1827
  return new Promise((resolve, reject) => {
1792
1828
  if (this.webSocket) {
1793
1829
  this.messageQueue = [];
1794
- this.webSocket.close();
1795
- this.webSocket = null;
1830
+ this.cleanupWebSocket();
1796
1831
  }
1797
1832
  this.lastMessageReceived = 0;
1833
+ this.identifier += 1;
1798
1834
  // Init the WebSocket connection
1799
1835
  const ws = new this.configuration.WebSocketPolyfill(this.url);
1800
1836
  ws.binaryType = 'arraybuffer';
1801
- ws.onmessage = (payload) => this.emit('message', payload);
1802
- ws.onclose = (payload) => this.emit('close', { event: payload });
1803
- ws.onopen = (payload) => this.emit('open', payload);
1804
- ws.onerror = (err) => {
1805
- reject(err);
1806
- };
1837
+ ws.identifier = this.identifier;
1838
+ this.attachWebSocketListeners(ws, reject);
1807
1839
  this.webSocket = ws;
1808
1840
  // Reset the status
1809
1841
  this.status = exports.WebSocketStatus.Connecting;
@@ -1849,7 +1881,8 @@ class HocuspocusProviderWebsocket extends EventEmitter {
1849
1881
  return;
1850
1882
  }
1851
1883
  // Don’t close the connection when a message was received recently
1852
- if (this.configuration.messageReconnectTimeout >= getUnixTime() - this.lastMessageReceived) {
1884
+ if (this.configuration.messageReconnectTimeout
1885
+ >= getUnixTime() - this.lastMessageReceived) {
1853
1886
  return;
1854
1887
  }
1855
1888
  // No message received in a long time, not even your own
@@ -1871,12 +1904,6 @@ class HocuspocusProviderWebsocket extends EventEmitter {
1871
1904
  this.messageQueue = [];
1872
1905
  }
1873
1906
  }
1874
- registerEventListeners() {
1875
- if (typeof window === 'undefined') {
1876
- return;
1877
- }
1878
- window.addEventListener('online', this.boundConnect);
1879
- }
1880
1907
  // Ensure that the URL always ends with /
1881
1908
  get serverUrl() {
1882
1909
  while (this.configuration.url[this.configuration.url.length - 1] === '/') {
@@ -1912,7 +1939,7 @@ class HocuspocusProviderWebsocket extends EventEmitter {
1912
1939
  }
1913
1940
  onClose({ event }) {
1914
1941
  this.closeTries = 0;
1915
- this.webSocket = null;
1942
+ this.cleanupWebSocket();
1916
1943
  if (this.status === exports.WebSocketStatus.Connected) {
1917
1944
  this.status = exports.WebSocketStatus.Disconnected;
1918
1945
  this.emit('status', { status: exports.WebSocketStatus.Disconnected });
@@ -1970,10 +1997,7 @@ class HocuspocusProviderWebsocket extends EventEmitter {
1970
1997
  this.stopConnectionAttempt();
1971
1998
  this.disconnect();
1972
1999
  this.removeAllListeners();
1973
- if (typeof window === 'undefined') {
1974
- return;
1975
- }
1976
- window.removeEventListener('online', this.boundConnect);
2000
+ this.cleanupWebSocket();
1977
2001
  }
1978
2002
  }
1979
2003
 
@@ -2572,6 +2596,9 @@ class HocuspocusProvider extends EventEmitter {
2572
2596
  }
2573
2597
  // not needed, but provides backward compatibility with e.g. lexicla/yjs
2574
2598
  async connect() {
2599
+ if (this.configuration.broadcast) {
2600
+ this.subscribeToBroadcastChannel();
2601
+ }
2575
2602
  return this.configuration.websocketProvider.connect();
2576
2603
  }
2577
2604
  disconnect() {
@@ -2760,36 +2787,45 @@ class TiptapCollabProvider extends HocuspocusProvider {
2760
2787
  super(configuration);
2761
2788
  this.tiptapCollabConfigurationPrefix = '__tiptapcollab__';
2762
2789
  }
2790
+ /**
2791
+ * note: this will only work if your server loaded @hocuspocus-pro/extension-history, or if you are on a Tiptap business plan.
2792
+ */
2763
2793
  createVersion(name) {
2764
- console.error('This doesnt work yet! If you want to join as a beta tester, send an email to humans@tiptap.dev');
2765
2794
  return this.sendStateless(JSON.stringify({ action: 'version.create', name }));
2766
2795
  }
2796
+ /**
2797
+ * note: this will only work if your server loaded @hocuspocus-pro/extension-history, or if you are on a Tiptap business plan.
2798
+ */
2767
2799
  revertToVersion(targetVersion) {
2768
- console.error('This doesnt work yet! If you want to join as a beta tester, send an email to humans@tiptap.dev');
2769
- return this.sendStateless(JSON.stringify({ action: 'version.revert', version: targetVersion }));
2800
+ return this.sendStateless(JSON.stringify({ action: 'document.revert', version: targetVersion }));
2770
2801
  }
2802
+ /**
2803
+ * note: this will only work if your server loaded @hocuspocus-pro/extension-history, or if you are on a Tiptap business plan.
2804
+ *
2805
+ * The server will reply with a stateless message (THistoryVersionPreviewEvent)
2806
+ */
2807
+ previewVersion(targetVersion) {
2808
+ return this.sendStateless(JSON.stringify({ action: 'version.preview', version: targetVersion }));
2809
+ }
2810
+ /**
2811
+ * note: this will only work if your server loaded @hocuspocus-pro/extension-history, or if you are on a Tiptap business plan.
2812
+ */
2771
2813
  getVersions() {
2772
- console.error('This doesnt work yet! If you want to join as a beta tester, send an email to humans@tiptap.dev');
2773
2814
  return this.configuration.document.getArray(`${this.tiptapCollabConfigurationPrefix}versions`).toArray();
2774
2815
  }
2775
2816
  watchVersions(callback) {
2776
- console.error('This doesnt work yet! If you want to join as a beta tester, send an email to humans@tiptap.dev');
2777
2817
  return this.configuration.document.getArray('__tiptapcollab__versions').observe(callback);
2778
2818
  }
2779
2819
  unwatchVersions(callback) {
2780
- console.error('This doesnt work yet! If you want to join as a beta tester, send an email to humans@tiptap.dev');
2781
2820
  return this.configuration.document.getArray('__tiptapcollab__versions').unobserve(callback);
2782
2821
  }
2783
2822
  isAutoVersioning() {
2784
- console.error('This doesnt work yet! If you want to join as a beta tester, send an email to humans@tiptap.dev');
2785
2823
  return !!this.configuration.document.getMap(`${this.tiptapCollabConfigurationPrefix}config`).get('autoVersioning');
2786
2824
  }
2787
2825
  enableAutoVersioning() {
2788
- console.error('This doesnt work yet! If you want to join as a beta tester, send an email to humans@tiptap.dev');
2789
2826
  return this.configuration.document.getMap(`${this.tiptapCollabConfigurationPrefix}config`).set('autoVersioning', 1);
2790
2827
  }
2791
2828
  disableAutoVersioning() {
2792
- console.error('This doesnt work yet! If you want to join as a beta tester, send an email to humans@tiptap.dev');
2793
2829
  return this.configuration.document.getMap(`${this.tiptapCollabConfigurationPrefix}config`).set('autoVersioning', 0);
2794
2830
  }
2795
2831
  }