@hocuspocus/provider 1.0.0-alpha.35 → 1.0.0-alpha.38

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.
Files changed (29) hide show
  1. package/dist/hocuspocus-provider.cjs +24 -8
  2. package/dist/hocuspocus-provider.cjs.map +1 -1
  3. package/dist/hocuspocus-provider.esm.js +24 -8
  4. package/dist/hocuspocus-provider.esm.js.map +1 -1
  5. package/dist/packages/extension-database/src/Database.d.ts +3 -5
  6. package/dist/packages/extension-monitor/src/Collector.d.ts +2 -1
  7. package/dist/packages/extension-redis/src/Redis.d.ts +91 -9
  8. package/dist/packages/extension-redis/src/index.d.ts +0 -1
  9. package/dist/packages/provider/src/HocuspocusProvider.d.ts +6 -0
  10. package/dist/packages/server/src/Document.d.ts +1 -1
  11. package/dist/packages/server/src/Hocuspocus.d.ts +6 -2
  12. package/dist/packages/server/src/MessageReceiver.d.ts +1 -1
  13. package/dist/packages/server/src/OutgoingMessage.d.ts +1 -0
  14. package/dist/packages/server/src/index.d.ts +3 -4
  15. package/dist/packages/server/src/types.d.ts +26 -6
  16. package/dist/tests/{extension-redis-rewrite/closeConnections.d.ts → extension-database/fetch.d.ts} +0 -0
  17. package/dist/tests/{extension-redis-rewrite/getConnectionCount.d.ts → extension-redis/closeConnections.d.ts} +0 -0
  18. package/dist/tests/{extension-redis-rewrite/getDocumentsCount.d.ts → extension-redis/getConnectionCount.d.ts} +0 -0
  19. package/dist/tests/{extension-redis-rewrite/onAwarenessChange.d.ts → extension-redis/getDocumentsCount.d.ts} +0 -0
  20. package/dist/tests/{extension-redis-rewrite/onChange.d.ts → extension-redis/onAwarenessChange.d.ts} +0 -0
  21. package/dist/tests/{extension-redis-rewrite/onStoreDocument.d.ts → extension-redis/onChange.d.ts} +0 -0
  22. package/dist/tests/extension-redis/{onLoadDocument.d.ts → onStoreDocument.d.ts} +0 -0
  23. package/dist/tests/utils/index.d.ts +1 -0
  24. package/dist/tests/utils/randomInteger.d.ts +1 -0
  25. package/package.json +4 -4
  26. package/src/HocuspocusProvider.ts +24 -7
  27. package/src/MessageReceiver.ts +8 -2
  28. package/dist/packages/extension-redis/src/RedisCluster.d.ts +0 -4
  29. package/dist/tests/extension-redis/onSynced.d.ts +0 -1
@@ -1,12 +1,10 @@
1
- import { Extension, onChangePayload, onLoadDocumentPayload, storePayload } from '@hocuspocus/server';
1
+ import { Extension, onChangePayload, onLoadDocumentPayload, storePayload, fetchPayload } from '@hocuspocus/server';
2
2
  export interface DatabaseConfiguration {
3
3
  /**
4
4
  * Pass a Promise to retrieve updates from your database. The Promise should resolve to
5
5
  * an array of items with Y.js-compatible binary data.
6
6
  */
7
- fetch: ({ documentName }: {
8
- documentName: string;
9
- }) => Promise<Uint8Array | null>;
7
+ fetch: (data: fetchPayload) => Promise<Uint8Array | null>;
10
8
  /**
11
9
  * Pass a function to store updates in your database.
12
10
  */
@@ -24,7 +22,7 @@ export declare class Database implements Extension {
24
22
  /**
25
23
  * Get stored data from the database.
26
24
  */
27
- onLoadDocument({ document, documentName }: onLoadDocumentPayload): Promise<any>;
25
+ onLoadDocument(data: onLoadDocumentPayload): Promise<any>;
28
26
  /**
29
27
  * Store new updates in the database.
30
28
  */
@@ -50,11 +50,12 @@ export declare class Collector {
50
50
  documents(): {};
51
51
  info(): Promise<{
52
52
  configuration: Partial<Configuration>;
53
- ipAddress: string;
53
+ ipAddress: string | null;
54
54
  nodeVersion: string;
55
55
  platform: NodeJS.Platform;
56
56
  started: string;
57
57
  version: string;
58
58
  }>;
59
+ private getIpAddress;
59
60
  private static readableYDoc;
60
61
  }
@@ -1,16 +1,98 @@
1
- import { RedisPersistence } from 'y-redis';
2
- import { Extension, onConnectPayload, onLoadDocumentPayload, onDisconnectPayload } from '@hocuspocus/server';
1
+ import RedisClient from 'ioredis';
2
+ import Redlock from 'redlock';
3
+ import { Document, Extension, afterLoadDocumentPayload, afterStoreDocumentPayload, onDisconnectPayload, onStoreDocumentPayload, onAwarenessUpdatePayload, onChangePayload, Debugger, onConfigurePayload, onListenPayload } from '@hocuspocus/server';
3
4
  export interface Configuration {
5
+ /**
6
+ * Redis port
7
+ */
8
+ port: number;
9
+ /**
10
+ * Redis host
11
+ */
12
+ host: string;
13
+ /**
14
+ * Options passed directly to Redis constructor
15
+ *
16
+ * https://github.com/luin/ioredis/blob/master/API.md#new-redisport-host-options
17
+ */
18
+ options?: RedisClient.RedisOptions;
19
+ /**
20
+ * An unique instance name, required to filter messages in Redis.
21
+ * If none is provided an unique id is generated.
22
+ */
23
+ identifier: string;
24
+ /**
25
+ * Namespace for Redis keys, if none is provided 'hocuspocus' is used
26
+ */
27
+ prefix: string;
28
+ /**
29
+ * The maximum time for the Redis lock in ms (in case it can’t be released).
30
+ */
31
+ lockTimeout: number;
4
32
  }
5
33
  export declare class Redis implements Extension {
34
+ /**
35
+ * Make sure to give that extension a higher priority, so
36
+ * the `onStoreDocument` hook is able to intercept the chain,
37
+ * before documents are stored to the database.
38
+ */
39
+ priority: number;
6
40
  configuration: Configuration;
7
- cluster: boolean;
8
- persistence: RedisPersistence | undefined;
41
+ pub: RedisClient.Redis;
42
+ sub: RedisClient.Redis;
43
+ documents: Map<string, Document>;
44
+ redlock: Redlock;
45
+ locks: Map<string, Redlock.Lock>;
46
+ logger: Debugger;
47
+ constructor(configuration: Partial<Configuration>);
48
+ onConfigure({ instance }: onConfigurePayload): Promise<void>;
49
+ onListen({ configuration }: onListenPayload): Promise<void>;
50
+ private getKey;
51
+ private pubKey;
52
+ private subKey;
53
+ private lockKey;
54
+ /**
55
+ * Once a document is laoded, subscribe to the channel in Redis.
56
+ */
57
+ afterLoadDocument({ documentName, document }: afterLoadDocumentPayload): Promise<unknown>;
58
+ /**
59
+ * Publish the first sync step through Redis.
60
+ */
61
+ private publishFirstSyncStep;
62
+ /**
63
+ * Let’s ask Redis who is connected already.
64
+ */
65
+ private requestAwarenessFromOtherInstances;
66
+ /**
67
+ * Before the document is stored, make sure to set a lock in Redis.
68
+ * That’s meant to avoid conflicts with other instances trying to store the document.
69
+ */
70
+ onStoreDocument({ documentName }: onStoreDocumentPayload): Promise<unknown>;
71
+ /**
72
+ * Release the Redis lock, so other instances can store documents.
73
+ */
74
+ afterStoreDocument({ documentName }: afterStoreDocumentPayload): Promise<void>;
75
+ /**
76
+ * Handle awareness update messages received directly by this Hocuspocus instance.
77
+ */
78
+ onAwarenessUpdate({ documentName, awareness }: onAwarenessUpdatePayload): Promise<number>;
79
+ /**
80
+ * Handle incoming messages published on all subscribed document channels.
81
+ * Note that this will also include messages from ourselves as it is not possible
82
+ * in Redis to filter these.
83
+ */
84
+ private handleIncomingMessage;
85
+ /**
86
+ * if the ydoc changed, we'll need to inform other Hocuspocus servers about it.
87
+ */
88
+ onChange(data: onChangePayload): Promise<any>;
89
+ /**
90
+ * Make sure to *not* listen for further changes, when there’s
91
+ * noone connected anymore.
92
+ */
93
+ onDisconnect: ({ documentName, clientsCount }: onDisconnectPayload) => Promise<void>;
9
94
  /**
10
- * Constructor
95
+ * Kill the Redlock connection immediately.
11
96
  */
12
- constructor(configuration?: Partial<Configuration>);
13
- onLoadDocument(data: onLoadDocumentPayload): Promise<import("yjs").Doc | undefined>;
14
- onConnect(data: onConnectPayload): Promise<void>;
15
- onDisconnect(data: onDisconnectPayload): Promise<void>;
97
+ onDestroy(): Promise<void>;
16
98
  }
@@ -1,2 +1 @@
1
1
  export * from './Redis';
2
- export * from './RedisCluster';
@@ -110,6 +110,7 @@ export declare class HocuspocusProvider extends EventEmitter {
110
110
  shouldConnect: boolean;
111
111
  status: WebSocketStatus;
112
112
  isSynced: boolean;
113
+ unsyncedChanges: number;
113
114
  isAuthenticated: boolean;
114
115
  lastMessageReceived: number;
115
116
  mux: mutex.mutex;
@@ -120,6 +121,7 @@ export declare class HocuspocusProvider extends EventEmitter {
120
121
  } | null;
121
122
  constructor(configuration: HocuspocusProviderConfiguration);
122
123
  setConfiguration(configuration?: Partial<HocuspocusProviderConfiguration>): void;
124
+ boundConnect: () => Promise<void>;
123
125
  connect(): Promise<void>;
124
126
  createWebSocketConnection(): Promise<unknown>;
125
127
  resolveConnectionAttempt(): void;
@@ -127,8 +129,11 @@ export declare class HocuspocusProvider extends EventEmitter {
127
129
  rejectConnectionAttempt(): void;
128
130
  get document(): Y.Doc;
129
131
  get awareness(): Awareness;
132
+ get hasUnsyncedChanges(): boolean;
130
133
  checkConnection(): void;
131
134
  forceSync(): void;
135
+ boundBeforeUnload: () => void;
136
+ beforeUnload(): void;
132
137
  registerEventListeners(): void;
133
138
  documentUpdateHandler(update: Uint8Array, origin: any): void;
134
139
  awarenessUpdateHandler({ added, updated, removed }: any, origin: any): void;
@@ -148,6 +153,7 @@ export declare class HocuspocusProvider extends EventEmitter {
148
153
  onClose(event: CloseEvent): void;
149
154
  destroy(): void;
150
155
  get broadcastChannel(): string;
156
+ boundBroadcastChannelSubscriber: (data: ArrayBuffer) => void;
151
157
  broadcastChannelSubscriber(data: ArrayBuffer): void;
152
158
  subscribeToBroadcastChannel(): void;
153
159
  disconnectBroadcastChannel(): void;
@@ -19,7 +19,7 @@ export declare class Document extends Doc {
19
19
  /**
20
20
  * Constructor.
21
21
  */
22
- constructor(name: string, logger: Debugger);
22
+ constructor(name: string, logger: Debugger, yDocOptions: {});
23
23
  /**
24
24
  * Check if the Document is empty
25
25
  */
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  import WebSocket, { AddressInfo, WebSocketServer } from 'ws';
3
3
  import { IncomingMessage, Server as HTTPServer } from 'http';
4
- import { Configuration, Hook } from './types';
4
+ import { Configuration, HookName, HookPayload } from './types';
5
5
  import Document from './Document';
6
6
  import { Debugger } from './Debugger';
7
7
  import { onListenPayload } from '.';
@@ -12,6 +12,10 @@ export declare const defaultConfiguration: {
12
12
  debounce: number;
13
13
  maxDebounce: number;
14
14
  quiet: boolean;
15
+ yDocOptions: {
16
+ gc: boolean;
17
+ gcFilter: () => boolean;
18
+ };
15
19
  };
16
20
  /**
17
21
  * Hocuspocus Server
@@ -88,7 +92,7 @@ export declare class Hocuspocus {
88
92
  * Run the given hook on all configured extensions.
89
93
  * Runs the given callback after each hook.
90
94
  */
91
- hooks(name: Hook, payload: any, callback?: Function | null): Promise<any>;
95
+ hooks(name: HookName, payload: HookPayload, callback?: Function | null): Promise<any>;
92
96
  /**
93
97
  * Get parameters by the given request
94
98
  */
@@ -8,6 +8,6 @@ export declare class MessageReceiver {
8
8
  logger: Debugger;
9
9
  constructor(message: IncomingMessage, logger: Debugger);
10
10
  apply(document: Document, connection?: Connection, reply?: (message: Uint8Array) => void): void;
11
- readSyncMessage(message: IncomingMessage, document: Document, connection?: Connection, reply?: (message: Uint8Array) => void): 0 | 2 | 1;
11
+ readSyncMessage(message: IncomingMessage, document: Document, connection?: Connection, reply?: (message: Uint8Array) => void, requestFirstSync?: boolean): 0 | 2 | 1;
12
12
  applyQueryAwarenessMessage(awareness: Awareness, reply?: (message: Uint8Array) => void): void;
13
13
  }
@@ -7,6 +7,7 @@ export declare class OutgoingMessage {
7
7
  category?: string;
8
8
  constructor();
9
9
  createSyncMessage(): OutgoingMessage;
10
+ createSyncReplyMessage(): OutgoingMessage;
10
11
  createAwarenessUpdateMessage(awareness: Awareness, changedClients?: Array<any>): OutgoingMessage;
11
12
  writeQueryAwareness(): OutgoingMessage;
12
13
  writeAuthenticated(): OutgoingMessage;
@@ -1,9 +1,8 @@
1
- export * from './Hocuspocus';
2
1
  export * from './Connection';
2
+ export * from './Debugger';
3
3
  export * from './Document';
4
+ export * from './Hocuspocus';
4
5
  export * from './IncomingMessage';
6
+ export * from './MessageReceiver';
5
7
  export * from './OutgoingMessage';
6
8
  export * from './types';
7
- export * from './MessageReceiver';
8
- export * from './Document';
9
- export * from './Connection';
@@ -1,7 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'http';
3
3
  import { URLSearchParams } from 'url';
4
- import { Socket } from 'net';
5
4
  import { Awareness } from 'y-protocols/awareness';
6
5
  import Document from './Document';
7
6
  import { Hocuspocus } from './Hocuspocus';
@@ -10,7 +9,8 @@ export declare enum MessageType {
10
9
  Sync = 0,
11
10
  Awareness = 1,
12
11
  Auth = 2,
13
- QueryAwareness = 3
12
+ QueryAwareness = 3,
13
+ SyncReply = 4
14
14
  }
15
15
  export interface AwarenessUpdate {
16
16
  added: Array<any>;
@@ -44,11 +44,12 @@ export interface Extension {
44
44
  onDisconnect?(data: onDisconnectPayload): Promise<any>;
45
45
  onDestroy?(data: onDestroyPayload): Promise<any>;
46
46
  }
47
- export declare type Hook = 'onConfigure' | 'onListen' | 'onUpgrade' | 'onConnect' | 'connected' | 'onAuthenticate' |
47
+ export declare type HookName = 'onConfigure' | 'onListen' | 'onUpgrade' | 'onConnect' | 'connected' | 'onAuthenticate' |
48
48
  /**
49
49
  * @deprecated onCreateDocument is deprecated, use onLoadDocument instead
50
50
  */
51
51
  'onCreateDocument' | 'onLoadDocument' | 'afterLoadDocument' | 'onChange' | 'onStoreDocument' | 'afterStoreDocument' | 'onAwarenessUpdate' | 'onRequest' | 'onDisconnect' | 'onDestroy';
52
+ export declare type HookPayload = onConfigurePayload | onListenPayload | onUpgradePayload | onConnectPayload | connectedPayload | onAuthenticatePayload | onLoadDocumentPayload | onChangePayload | onStoreDocumentPayload | afterStoreDocumentPayload | onAwarenessUpdatePayload | onRequestPayload | onDisconnectPayload | onDestroyPayload;
52
53
  export interface Configuration extends Extension {
53
54
  /**
54
55
  * A name for the instance, used for logging.
@@ -79,6 +80,13 @@ export interface Configuration extends Extension {
79
80
  * By default, the servers show a start screen. If passed false, the server will start quietly.
80
81
  */
81
82
  quiet: boolean;
83
+ /**
84
+ * options to pass to the ydoc document
85
+ */
86
+ yDocOptions: {
87
+ gc: boolean;
88
+ gcFilter: () => boolean;
89
+ };
82
90
  /**
83
91
  * Function which returns the (customized) document name based on the request
84
92
  */
@@ -179,6 +187,16 @@ export declare type StatesArray = {
179
187
  clientId: number;
180
188
  [key: string | number]: any;
181
189
  }[];
190
+ export interface fetchPayload {
191
+ context: any;
192
+ document: Document;
193
+ documentName: string;
194
+ instance: Hocuspocus;
195
+ requestHeaders: IncomingHttpHeaders;
196
+ requestParameters: URLSearchParams;
197
+ socketId: string;
198
+ connection: ConnectionConfiguration;
199
+ }
182
200
  export interface storePayload extends onStoreDocumentPayload {
183
201
  state: Buffer;
184
202
  }
@@ -198,19 +216,21 @@ export interface onRequestPayload {
198
216
  instance: Hocuspocus;
199
217
  }
200
218
  export interface onUpgradePayload {
201
- head: any;
202
219
  request: IncomingMessage;
203
- socket: Socket;
220
+ socket: any;
221
+ head: any;
204
222
  instance: Hocuspocus;
205
223
  }
206
224
  export interface onListenPayload {
225
+ instance: Hocuspocus;
226
+ configuration: Configuration;
207
227
  port: number;
208
228
  }
209
229
  export interface onDestroyPayload {
210
230
  instance: Hocuspocus;
211
231
  }
212
232
  export interface onConfigurePayload {
233
+ instance: Hocuspocus;
213
234
  configuration: Configuration;
214
235
  version: string;
215
- instance: Hocuspocus;
216
236
  }
@@ -2,6 +2,7 @@ export * from './createDirectory';
2
2
  export * from './flushRedis';
3
3
  export * from './newHocuspocus';
4
4
  export * from './newHocuspocusProvider';
5
+ export * from './randomInteger';
5
6
  export * from './redisConnectionSettings';
6
7
  export * from './removeDirectory';
7
8
  export * from './sleep';
@@ -0,0 +1 @@
1
+ export declare const randomInteger: (min: number, max: number) => number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hocuspocus/provider",
3
- "version": "1.0.0-alpha.35",
3
+ "version": "1.0.0-alpha.38",
4
4
  "description": "hocuspocus provider",
5
5
  "homepage": "https://hocuspocus.dev",
6
6
  "keywords": [
@@ -11,7 +11,7 @@
11
11
  ],
12
12
  "license": "MIT",
13
13
  "type": "module",
14
- "main": "dist/hocuspocus-provider.esm.js",
14
+ "main": "dist/hocuspocus-provider.cjs",
15
15
  "module": "dist/hocuspocus-provider.esm.js",
16
16
  "types": "dist/packages/provider/src/index.d.ts",
17
17
  "exports": {
@@ -28,11 +28,11 @@
28
28
  "dist"
29
29
  ],
30
30
  "dependencies": {
31
- "@hocuspocus/common": "^1.0.0-alpha.10",
31
+ "@hocuspocus/common": "^1.0.0-alpha.11",
32
32
  "@lifeomic/attempt": "^3.0.2",
33
33
  "lib0": "^0.2.46",
34
34
  "y-protocols": "^1.0.5",
35
35
  "yjs": "^13.5.29"
36
36
  },
37
- "gitHead": "1fc2a6cff1b5fd626b8dd7c486755111965da20d"
37
+ "gitHead": "fe784d26fb1b281ab6d0bc7b5fca500be3b62684"
38
38
  }
@@ -182,6 +182,8 @@ export class HocuspocusProvider extends EventEmitter {
182
182
 
183
183
  isSynced = false
184
184
 
185
+ unsyncedChanges = 0
186
+
185
187
  isAuthenticated = false
186
188
 
187
189
  lastMessageReceived = 0
@@ -259,11 +261,14 @@ export class HocuspocusProvider extends EventEmitter {
259
261
  this.configuration = { ...this.configuration, ...configuration }
260
262
  }
261
263
 
264
+ boundConnect = this.connect.bind(this)
265
+
262
266
  async connect() {
263
267
  if (this.status === WebSocketStatus.Connected) {
264
268
  return
265
269
  }
266
270
 
271
+ this.unsyncedChanges = 0 // set to 0 in case we got reconnected
267
272
  this.shouldConnect = true
268
273
  this.subscribeToBroadcastChannel()
269
274
 
@@ -344,6 +349,10 @@ export class HocuspocusProvider extends EventEmitter {
344
349
  return this.configuration.awareness
345
350
  }
346
351
 
352
+ get hasUnsyncedChanges() {
353
+ return this.unsyncedChanges > 0
354
+ }
355
+
347
356
  checkConnection() {
348
357
  // Don’t check the connection when it’s not even established
349
358
  if (this.status !== WebSocketStatus.Connected) {
@@ -373,15 +382,19 @@ export class HocuspocusProvider extends EventEmitter {
373
382
  this.send(SyncStepOneMessage, { document: this.document })
374
383
  }
375
384
 
385
+ boundBeforeUnload = this.beforeUnload.bind(this)
386
+
387
+ beforeUnload() {
388
+ removeAwarenessStates(this.awareness, [this.document.clientID], 'window unload')
389
+ }
390
+
376
391
  registerEventListeners() {
377
392
  if (typeof window === 'undefined') {
378
393
  return
379
394
  }
380
395
 
381
- window.addEventListener('online', this.connect.bind(this))
382
- window.addEventListener('beforeunload', () => {
383
- removeAwarenessStates(this.awareness, [this.document.clientID], 'window unload')
384
- })
396
+ window.addEventListener('online', this.boundConnect)
397
+ window.addEventListener('beforeunload', this.boundBeforeUnload)
385
398
  }
386
399
 
387
400
  documentUpdateHandler(update: Uint8Array, origin: any) {
@@ -389,6 +402,7 @@ export class HocuspocusProvider extends EventEmitter {
389
402
  return
390
403
  }
391
404
 
405
+ this.unsyncedChanges += 1
392
406
  this.send(UpdateMessage, { update }, true)
393
407
  }
394
408
 
@@ -605,13 +619,16 @@ export class HocuspocusProvider extends EventEmitter {
605
619
  return
606
620
  }
607
621
 
608
- window.removeEventListener('online', this.connect.bind(this))
622
+ window.removeEventListener('online', this.boundConnect)
623
+ window.removeEventListener('beforeunload', this.boundBeforeUnload)
609
624
  }
610
625
 
611
626
  get broadcastChannel() {
612
627
  return `${this.serverUrl}/${this.configuration.name}`
613
628
  }
614
629
 
630
+ boundBroadcastChannelSubscriber = this.broadcastChannelSubscriber.bind(this)
631
+
615
632
  broadcastChannelSubscriber(data: ArrayBuffer) {
616
633
  this.mux(() => {
617
634
  const message = new IncomingMessage(data)
@@ -623,7 +640,7 @@ export class HocuspocusProvider extends EventEmitter {
623
640
 
624
641
  subscribeToBroadcastChannel() {
625
642
  if (!this.subscribedToBroadcastChannel) {
626
- bc.subscribe(this.broadcastChannel, this.broadcastChannelSubscriber.bind(this))
643
+ bc.subscribe(this.broadcastChannel, this.boundBroadcastChannelSubscriber)
627
644
  this.subscribedToBroadcastChannel = true
628
645
  }
629
646
 
@@ -644,7 +661,7 @@ export class HocuspocusProvider extends EventEmitter {
644
661
  }, true)
645
662
 
646
663
  if (this.subscribedToBroadcastChannel) {
647
- bc.unsubscribe(this.broadcastChannel, this.broadcastChannelSubscriber.bind(this))
664
+ bc.unsubscribe(this.broadcastChannel, this.boundBroadcastChannelSubscriber)
648
665
  this.subscribedToBroadcastChannel = false
649
666
  }
650
667
  }
@@ -1,5 +1,5 @@
1
1
  import * as awarenessProtocol from 'y-protocols/awareness'
2
- import { readSyncMessage, messageYjsSyncStep2 } from 'y-protocols/sync'
2
+ import { readSyncMessage, messageYjsSyncStep2, messageYjsUpdate } from 'y-protocols/sync'
3
3
  import { readAuthMessage } from '@hocuspocus/common'
4
4
  import { MessageType } from './types'
5
5
  import { HocuspocusProvider } from './HocuspocusProvider'
@@ -75,9 +75,15 @@ export class MessageReceiver {
75
75
  )
76
76
 
77
77
  // Synced once we receive Step2
78
- if (emitSynced && syncMessageType === messageYjsSyncStep2) {
78
+ if (emitSynced && (syncMessageType === messageYjsSyncStep2)) {
79
79
  provider.synced = true
80
80
  }
81
+
82
+ if (syncMessageType === messageYjsUpdate || syncMessageType === messageYjsSyncStep2) {
83
+ if (provider.unsyncedChanges > 0) {
84
+ provider.unsyncedChanges -= 1
85
+ }
86
+ }
81
87
  }
82
88
 
83
89
  private applyAwarenessMessage(provider: HocuspocusProvider) {
@@ -1,4 +0,0 @@
1
- import { Redis } from './Redis';
2
- export declare class RedisCluster extends Redis {
3
- cluster: boolean;
4
- }
@@ -1 +0,0 @@
1
- export {};