@hocuspocus/provider 4.2.0 → 4.4.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.
@@ -538,7 +538,7 @@ var MessageSender = class {
538
538
 
539
539
  //#endregion
540
540
  //#region packages/provider/src/version.ts
541
- const version = "4.2.0";
541
+ const version = "4.4.0";
542
542
 
543
543
  //#endregion
544
544
  //#region packages/provider/src/OutgoingMessages/AuthenticationMessage.ts
@@ -654,6 +654,7 @@ var HocuspocusProvider = class extends EventEmitter {
654
654
  token: null,
655
655
  sessionAwareness: false,
656
656
  forceSyncInterval: false,
657
+ flushDelay: false,
657
658
  onAuthenticated: () => null,
658
659
  onAuthenticationFailed: () => null,
659
660
  onOpen: () => null,
@@ -676,6 +677,9 @@ var HocuspocusProvider = class extends EventEmitter {
676
677
  this.authorizedScope = void 0;
677
678
  this.manageSocket = false;
678
679
  this._isAttached = false;
680
+ this.pendingUpdates = [];
681
+ this.pendingAwarenessClients = /* @__PURE__ */ new Set();
682
+ this.flushTimeout = null;
679
683
  this.sessionId = Math.random().toString(36).slice(2);
680
684
  this.intervals = { forceSync: null };
681
685
  this.boundDocumentUpdateHandler = this.documentUpdateHandler.bind(this);
@@ -782,21 +786,71 @@ var HocuspocusProvider = class extends EventEmitter {
782
786
  documentName: this.effectiveName
783
787
  });
784
788
  }
789
+ get batchingEnabled() {
790
+ return !!this.configuration.flushDelay && typeof this.configuration.flushDelay === "number";
791
+ }
785
792
  documentUpdateHandler(update, origin) {
786
793
  if (origin === this) return;
787
- this.incrementUnsyncedChanges();
788
- this.send(UpdateMessage, {
789
- update,
790
- documentName: this.effectiveName
791
- });
794
+ if (!this.batchingEnabled) {
795
+ this.incrementUnsyncedChanges();
796
+ this.send(UpdateMessage, {
797
+ update,
798
+ documentName: this.effectiveName
799
+ });
800
+ return;
801
+ }
802
+ if (this.pendingUpdates.length === 0) this.incrementUnsyncedChanges();
803
+ this.pendingUpdates.push(update);
804
+ this.scheduleFlush();
792
805
  }
793
806
  awarenessUpdateHandler({ added, updated, removed }, origin) {
794
807
  const changedClients = added.concat(updated).concat(removed);
795
- this.send(AwarenessMessage, {
796
- awareness: this.awareness,
797
- clients: changedClients,
798
- documentName: this.effectiveName
799
- });
808
+ if (!this.batchingEnabled) {
809
+ this.send(AwarenessMessage, {
810
+ awareness: this.awareness,
811
+ clients: changedClients,
812
+ documentName: this.effectiveName
813
+ });
814
+ return;
815
+ }
816
+ for (const client of changedClients) this.pendingAwarenessClients.add(client);
817
+ this.scheduleFlush();
818
+ }
819
+ scheduleFlush() {
820
+ if (this.flushTimeout !== null) return;
821
+ this.flushTimeout = setTimeout(() => {
822
+ this.flushTimeout = null;
823
+ this.flushPendingUpdates();
824
+ }, this.configuration.flushDelay);
825
+ }
826
+ /**
827
+ * Send everything buffered for the current `flushDelay` window right away.
828
+ * Buffered document updates are merged into a single message and awareness
829
+ * collapses to the latest state of each changed client. Safe to call when
830
+ * nothing is pending.
831
+ */
832
+ flushPendingUpdates() {
833
+ if (this.flushTimeout !== null) {
834
+ clearTimeout(this.flushTimeout);
835
+ this.flushTimeout = null;
836
+ }
837
+ if (this.pendingUpdates.length > 0) {
838
+ const update = this.pendingUpdates.length === 1 ? this.pendingUpdates[0] : yjs.mergeUpdates(this.pendingUpdates);
839
+ this.pendingUpdates = [];
840
+ this.send(UpdateMessage, {
841
+ update,
842
+ documentName: this.effectiveName
843
+ });
844
+ }
845
+ if (this.pendingAwarenessClients.size > 0) {
846
+ const clients = Array.from(this.pendingAwarenessClients);
847
+ this.pendingAwarenessClients.clear();
848
+ this.send(AwarenessMessage, {
849
+ awareness: this.awareness,
850
+ clients,
851
+ documentName: this.effectiveName
852
+ });
853
+ }
800
854
  }
801
855
  /**
802
856
  * Indicates whether a first handshake with the server has been established
@@ -864,6 +918,12 @@ var HocuspocusProvider = class extends EventEmitter {
864
918
  onClose() {
865
919
  this.isAuthenticated = false;
866
920
  this.synced = false;
921
+ if (this.flushTimeout !== null) {
922
+ clearTimeout(this.flushTimeout);
923
+ this.flushTimeout = null;
924
+ }
925
+ this.pendingUpdates = [];
926
+ this.pendingAwarenessClients.clear();
867
927
  if (this.awareness) (0, y_protocols_awareness.removeAwarenessStates)(this.awareness, Array.from(this.awareness.getStates().keys()).filter((client) => client !== this.document.clientID), this);
868
928
  }
869
929
  destroy() {
@@ -874,6 +934,7 @@ var HocuspocusProvider = class extends EventEmitter {
874
934
  this.awareness.off("update", this.boundAwarenessUpdateHandler);
875
935
  this.awareness.destroy();
876
936
  }
937
+ this.flushPendingUpdates();
877
938
  this.document.off("update", this.boundDocumentUpdateHandler);
878
939
  this.removeAllListeners();
879
940
  this.detach();
@@ -1 +1 @@
1
- {"version":3,"file":"hocuspocus-provider.cjs","names":["time","encoding","WsReadyStates","messageYjsSyncStep2","awarenessProtocol","Y","Awareness"],"sources":["../src/EventEmitter.ts","../src/IncomingMessage.ts","../src/types.ts","../src/OutgoingMessage.ts","../src/OutgoingMessages/CloseMessage.ts","../src/HocuspocusProviderWebsocket.ts","../src/MessageReceiver.ts","../src/MessageSender.ts","../src/version.ts","../src/OutgoingMessages/AuthenticationMessage.ts","../src/OutgoingMessages/AwarenessMessage.ts","../src/OutgoingMessages/StatelessMessage.ts","../src/OutgoingMessages/SyncStepOneMessage.ts","../src/OutgoingMessages/UpdateMessage.ts","../src/HocuspocusProvider.ts"],"sourcesContent":["export default class EventEmitter {\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tpublic callbacks: { [key: string]: Function[] } = {};\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tpublic on(event: string, fn: Function): this {\n\t\tif (!this.callbacks[event]) {\n\t\t\tthis.callbacks[event] = [];\n\t\t}\n\n\t\tthis.callbacks[event].push(fn);\n\n\t\treturn this;\n\t}\n\n\tprotected emit(event: string, ...args: any): this {\n\t\tconst callbacks = this.callbacks[event];\n\n\t\tif (callbacks) {\n\t\t\tcallbacks.forEach((callback) => callback.apply(this, args));\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tpublic off(event: string, fn?: Function): this {\n\t\tconst callbacks = this.callbacks[event];\n\n\t\tif (callbacks) {\n\t\t\tif (fn) {\n\t\t\t\tthis.callbacks[event] = callbacks.filter((callback) => callback !== fn);\n\t\t\t} else {\n\t\t\t\tdelete this.callbacks[event];\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n\n\tremoveAllListeners(): void {\n\t\tthis.callbacks = {};\n\t}\n}\n","import type { Decoder } from \"lib0/decoding\";\nimport {\n\tcreateDecoder,\n\tpeekVarString,\n\treadVarUint,\n\treadVarUint8Array,\n\treadVarString,\n} from \"lib0/decoding\";\nimport type { Encoder } from \"lib0/encoding\";\nimport {\n\tcreateEncoder,\n\twriteVarUint,\n\twriteVarUint8Array,\n\twriteVarString,\n\tlength,\n} from \"lib0/encoding\";\nimport type { MessageType } from \"./types.ts\";\n\nexport class IncomingMessage {\n\tdata: any;\n\n\tencoder: Encoder;\n\n\tdecoder: Decoder;\n\n\tconstructor(data: any) {\n\t\tthis.data = data;\n\t\tthis.encoder = createEncoder();\n\t\tthis.decoder = createDecoder(new Uint8Array(this.data));\n\t}\n\n\tpeekVarString(): string {\n\t\treturn peekVarString(this.decoder);\n\t}\n\n\treadVarUint(): MessageType {\n\t\treturn readVarUint(this.decoder);\n\t}\n\n\treadVarString(): string {\n\t\treturn readVarString(this.decoder);\n\t}\n\n\treadVarUint8Array() {\n\t\treturn readVarUint8Array(this.decoder);\n\t}\n\n\twriteVarUint(type: MessageType) {\n\t\treturn writeVarUint(this.encoder, type);\n\t}\n\n\twriteVarString(string: string) {\n\t\treturn writeVarString(this.encoder, string);\n\t}\n\n\twriteVarUint8Array(data: Uint8Array) {\n\t\treturn writeVarUint8Array(this.encoder, data);\n\t}\n\n\tlength() {\n\t\treturn length(this.encoder);\n\t}\n}\n","import type { Encoder } from \"lib0/encoding\";\nimport type { Awareness } from \"y-protocols/awareness\";\nimport type * as Y from \"yjs\";\nimport type { CloseEvent } from \"@hocuspocus/common\";\nimport type { IncomingMessage } from \"./IncomingMessage.ts\";\nimport type { OutgoingMessage } from \"./OutgoingMessage.ts\";\nimport type { AuthenticationMessage } from \"./OutgoingMessages/AuthenticationMessage.ts\";\nimport type { AwarenessMessage } from \"./OutgoingMessages/AwarenessMessage.ts\";\nimport type { QueryAwarenessMessage } from \"./OutgoingMessages/QueryAwarenessMessage.ts\";\nimport type { SyncStepOneMessage } from \"./OutgoingMessages/SyncStepOneMessage.ts\";\nimport type { SyncStepTwoMessage } from \"./OutgoingMessages/SyncStepTwoMessage.ts\";\nimport type { UpdateMessage } from \"./OutgoingMessages/UpdateMessage.ts\";\n\nexport enum MessageType {\n\tSync = 0,\n\tAwareness = 1,\n\tAuth = 2,\n\tQueryAwareness = 3,\n\tStateless = 5,\n\tCLOSE = 7,\n\tSyncStatus = 8,\n\tPing = 9,\n\tPong = 10,\n}\n\nexport enum WebSocketStatus {\n\tConnecting = \"connecting\",\n\tConnected = \"connected\",\n\tDisconnected = \"disconnected\",\n}\n\nexport type AuthorizedScope = \"read-write\" | \"readonly\";\n\nexport interface OutgoingMessageInterface {\n\tencoder: Encoder;\n\ttype?: MessageType;\n}\n\nexport interface OutgoingMessageArguments {\n\tdocumentName: string;\n\ttoken: string;\n\tdocument: Y.Doc;\n\tawareness: Awareness;\n\tclients: number[];\n\tstates: Map<number, { [key: string]: any }>;\n\tupdate: any;\n\tpayload: string;\n\tencoder: Encoder;\n}\n\nexport interface Constructable<T> {\n\tnew (...args: any): T;\n}\n\nexport type ConstructableOutgoingMessage =\n\t| Constructable<AuthenticationMessage>\n\t| Constructable<AwarenessMessage>\n\t| Constructable<QueryAwarenessMessage>\n\t| Constructable<SyncStepOneMessage>\n\t| Constructable<SyncStepTwoMessage>\n\t| Constructable<UpdateMessage>;\n\nexport type onAuthenticationFailedParameters = {\n\treason: string;\n};\n\nexport type onAuthenticatedParameters = {\n\tscope: AuthorizedScope;\n};\n\nexport type onOpenParameters = {\n\tevent: Event;\n};\n\nexport type onMessageParameters = {\n\tevent: MessageEvent;\n\tmessage: IncomingMessage;\n};\n\nexport type onOutgoingMessageParameters = {\n\tmessage: OutgoingMessage;\n};\n\nexport type onStatusParameters = {\n\tstatus: WebSocketStatus;\n};\n\nexport type onSyncedParameters = {\n\tstate: boolean;\n};\n\nexport type onUnsyncedChangesParameters = {\n\tnumber: number;\n};\n\nexport type onDisconnectParameters = {\n\tevent: CloseEvent;\n};\n\nexport type onCloseParameters = {\n\tevent: CloseEvent;\n};\n\nexport type onAwarenessUpdateParameters = {\n\tstates: StatesArray;\n};\n\nexport type onAwarenessChangeParameters = {\n\tstates: StatesArray;\n};\n\nexport type onStatelessParameters = {\n\tpayload: string;\n};\n\nexport type StatesArray = { clientId: number; [key: string | number]: any }[];\n","import type { Encoder } from \"lib0/encoding\";\nimport { createEncoder, toUint8Array } from \"lib0/encoding\";\nimport type {\n\tMessageType,\n\tOutgoingMessageArguments,\n\tOutgoingMessageInterface,\n} from \"./types.ts\";\n\nexport class OutgoingMessage implements OutgoingMessageInterface {\n\tencoder: Encoder;\n\n\ttype?: MessageType;\n\n\tconstructor() {\n\t\tthis.encoder = createEncoder();\n\t}\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\treturn args.encoder;\n\t}\n\n\ttoUint8Array() {\n\t\treturn toUint8Array(this.encoder);\n\t}\n}\n","import * as encoding from \"lib0/encoding\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class CloseMessage extends OutgoingMessage {\n\ttype = MessageType.CLOSE;\n\n\tdescription = \"Ask the server to close the connection\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tencoding.writeVarString(this.encoder, args.documentName!);\n\t\tencoding.writeVarUint(this.encoder, this.type);\n\n\t\treturn this.encoder;\n\t}\n}\n","import { WsReadyStates } from \"@hocuspocus/common\";\nimport { retry } from \"@lifeomic/attempt\";\nimport { createDecoder, readVarString, readVarUint } from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport * as time from \"lib0/time\";\nimport EventEmitter from \"./EventEmitter.ts\";\nimport type { HocuspocusProvider } from \"./HocuspocusProvider.ts\";\nimport { IncomingMessage } from \"./IncomingMessage.ts\";\nimport { CloseMessage } from \"./OutgoingMessages/CloseMessage.ts\";\nimport {\n\tMessageType,\n\ttype onAwarenessChangeParameters,\n\ttype onAwarenessUpdateParameters,\n\ttype onCloseParameters,\n\ttype onDisconnectParameters,\n\ttype onMessageParameters,\n\ttype onOpenParameters,\n\ttype onOutgoingMessageParameters,\n\ttype onStatusParameters,\n\tWebSocketStatus,\n} from \"./types.ts\";\n\nexport type HocuspocusWebSocket = WebSocket & { identifier: string };\nexport type HocusPocusWebSocket = HocuspocusWebSocket;\n\nexport type HocuspocusProviderWebsocketConfiguration = Required<\n\tPick<CompleteHocuspocusProviderWebsocketConfiguration, \"url\">\n> &\n\tPartial<CompleteHocuspocusProviderWebsocketConfiguration>;\n\nexport interface CompleteHocuspocusProviderWebsocketConfiguration {\n\t/**\n\t * Whether to connect automatically when creating the provider instance. Default=true\n\t */\n\tautoConnect: boolean;\n\n\t/**\n\t * URL of your @hocuspocus/server instance\n\t */\n\turl: string;\n\n\t/**\n\t * By default, trailing slashes are removed from the URL. Set this to true\n\t * to preserve trailing slashes if your server configuration requires them.\n\t */\n\tpreserveTrailingSlash: boolean;\n\n\t/**\n\t * An optional WebSocket polyfill, for example for Node.js\n\t */\n\tWebSocketPolyfill: any;\n\n\t/**\n\t * Disconnect when no message is received for the defined amount of milliseconds.\n\t */\n\tmessageReconnectTimeout: number;\n\t/**\n\t * The delay between each attempt in milliseconds. You can provide a factor to have the delay grow exponentially.\n\t */\n\tdelay: number;\n\t/**\n\t * The initialDelay is the amount of time to wait before making the first attempt. This option should typically be 0 since you typically want the first attempt to happen immediately.\n\t */\n\tinitialDelay: number;\n\t/**\n\t * The factor option is used to grow the delay exponentially.\n\t */\n\tfactor: number;\n\t/**\n\t * The maximum number of attempts or 0 if there is no limit on number of attempts.\n\t */\n\tmaxAttempts: number;\n\t/**\n\t * minDelay is used to set a lower bound of delay when jitter is enabled. This property has no effect if jitter is disabled.\n\t */\n\tminDelay: number;\n\t/**\n\t * The maxDelay option is used to set an upper bound for the delay when factor is enabled. A value of 0 can be provided if there should be no upper bound when calculating delay.\n\t */\n\tmaxDelay: number;\n\t/**\n\t * If jitter is true then the calculated delay will be a random integer value between minDelay and the calculated delay for the current iteration.\n\t */\n\tjitter: boolean;\n\t/**\n\t * A timeout in milliseconds. If timeout is non-zero then a timer is set using setTimeout. If the timeout is triggered then future attempts will be aborted.\n\t */\n\ttimeout: number;\n\thandleTimeout: (() => Promise<unknown>) | null;\n\tonOpen: (data: onOpenParameters) => void;\n\tonConnect: () => void;\n\tonMessage: (data: onMessageParameters) => void;\n\tonOutgoingMessage: (data: onOutgoingMessageParameters) => void;\n\tonStatus: (data: onStatusParameters) => void;\n\tonDisconnect: (data: onDisconnectParameters) => void;\n\tonClose: (data: onCloseParameters) => void;\n\tonDestroy: () => void;\n\tonAwarenessUpdate: (data: onAwarenessUpdateParameters) => void;\n\tonAwarenessChange: (data: onAwarenessChangeParameters) => void;\n\n\t/**\n\t * Map of attached providers keyed by documentName.\n\t */\n\tproviderMap: Map<string, HocuspocusProvider>;\n}\n\nexport class HocuspocusProviderWebsocket extends EventEmitter {\n\tprivate static readonly DEDUPLICATABLE_TYPES = new Set([\n\t\tMessageType.Awareness,\n\t\tMessageType.QueryAwareness,\n\t]);\n\n\tprivate messageQueue: any[] = [];\n\n\tpublic configuration: CompleteHocuspocusProviderWebsocketConfiguration = {\n\t\turl: \"\",\n\t\tautoConnect: true,\n\t\tpreserveTrailingSlash: false,\n\t\t// @ts-expect-error\n\t\tdocument: undefined,\n\t\tWebSocketPolyfill: undefined,\n\t\t// TODO: this should depend on awareness.outdatedTime\n\t\tmessageReconnectTimeout: 30000,\n\t\t// 1 second\n\t\tdelay: 1000,\n\t\t// instant\n\t\tinitialDelay: 0,\n\t\t// double the delay each time\n\t\tfactor: 2,\n\t\t// unlimited retries\n\t\tmaxAttempts: 0,\n\t\t// wait at least 1 second\n\t\tminDelay: 1000,\n\t\t// at least every 30 seconds\n\t\tmaxDelay: 30000,\n\t\t// randomize\n\t\tjitter: true,\n\t\t// retry forever\n\t\ttimeout: 0,\n\t\tonOpen: () => null,\n\t\tonConnect: () => null,\n\t\tonMessage: () => null,\n\t\tonOutgoingMessage: () => null,\n\t\tonStatus: () => null,\n\t\tonDisconnect: () => null,\n\t\tonClose: () => null,\n\t\tonDestroy: () => null,\n\t\tonAwarenessUpdate: () => null,\n\t\tonAwarenessChange: () => null,\n\t\thandleTimeout: null,\n\t\tproviderMap: new Map(),\n\t};\n\n\twebSocket: HocusPocusWebSocket | null = null;\n\n\twebSocketHandlers: { [key: string]: any } = {};\n\n\tshouldConnect = true;\n\n\tstatus = WebSocketStatus.Disconnected;\n\n\tlastMessageReceived = 0;\n\n\tidentifier = 0;\n\n\tintervals: any = {\n\t\tconnectionChecker: null,\n\t};\n\n\tconnectionAttempt: {\n\t\tresolve: (value?: any) => void;\n\t\treject: (reason?: any) => void;\n\t} | null = null;\n\n\tconstructor(configuration: HocuspocusProviderWebsocketConfiguration) {\n\t\tsuper();\n\t\tthis.setConfiguration(configuration);\n\n\t\tthis.configuration.WebSocketPolyfill = configuration.WebSocketPolyfill\n\t\t\t? configuration.WebSocketPolyfill\n\t\t\t: WebSocket;\n\n\t\tthis.on(\"open\", this.configuration.onOpen);\n\t\tthis.on(\"open\", this.onOpen.bind(this));\n\t\tthis.on(\"connect\", this.configuration.onConnect);\n\t\tthis.on(\"message\", this.configuration.onMessage);\n\t\tthis.on(\"outgoingMessage\", this.configuration.onOutgoingMessage);\n\t\tthis.on(\"status\", this.configuration.onStatus);\n\t\tthis.on(\"disconnect\", this.configuration.onDisconnect);\n\t\tthis.on(\"close\", this.configuration.onClose);\n\t\tthis.on(\"destroy\", this.configuration.onDestroy);\n\t\tthis.on(\"awarenessUpdate\", this.configuration.onAwarenessUpdate);\n\t\tthis.on(\"awarenessChange\", this.configuration.onAwarenessChange);\n\n\t\tthis.on(\"close\", this.onClose.bind(this));\n\t\tthis.on(\"message\", this.onMessage.bind(this));\n\n\t\tthis.intervals.connectionChecker = setInterval(\n\t\t\tthis.checkConnection.bind(this),\n\t\t\tthis.configuration.messageReconnectTimeout / 10,\n\t\t);\n\n\t\tif (this.shouldConnect) {\n\t\t\tthis.connect();\n\t\t}\n\t}\n\n\treceivedOnOpenPayload?: Event | undefined = undefined;\n\n\tasync onOpen(event: Event) {\n\t\tthis.status = WebSocketStatus.Connected;\n\t\tthis.emit(\"status\", { status: WebSocketStatus.Connected });\n\n\t\tthis.cancelWebsocketRetry = undefined;\n\t\tthis.receivedOnOpenPayload = event;\n\t}\n\n\tattach(provider: HocuspocusProvider) {\n\t\tconst key = provider.effectiveName;\n\t\tconst existing = this.configuration.providerMap.get(key);\n\n\t\tif (existing && existing !== provider) {\n\t\t\t// Allow replacing a provider that hasn't authenticated (e.g., after auth failure retry)\n\t\t\tif (existing.isAuthenticated) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot attach two providers with the same effective name \"${key}\". ` +\n\t\t\t\t\t\t\"Use sessionAwareness: true to multiplex providers with the same document name.\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis.configuration.providerMap.set(key, provider);\n\n\t\tif (this.status === WebSocketStatus.Disconnected && this.shouldConnect) {\n\t\t\tthis.connect();\n\t\t}\n\n\t\tif (\n\t\t\tthis.receivedOnOpenPayload &&\n\t\t\tthis.status === WebSocketStatus.Connected\n\t\t) {\n\t\t\tprovider.onOpen(this.receivedOnOpenPayload);\n\t\t}\n\t}\n\n\tdetach(provider: HocuspocusProvider) {\n\t\tconst key = provider.effectiveName;\n\t\tif (this.configuration.providerMap.has(key)) {\n\t\t\tprovider.send(CloseMessage, {\n\t\t\t\tdocumentName: key,\n\t\t\t});\n\t\t\tthis.configuration.providerMap.delete(key);\n\t\t}\n\t}\n\n\tpublic setConfiguration(\n\t\tconfiguration: Partial<HocuspocusProviderWebsocketConfiguration> = {},\n\t): void {\n\t\tthis.configuration = { ...this.configuration, ...configuration };\n\n\t\tif (!this.configuration.autoConnect) {\n\t\t\tthis.shouldConnect = false;\n\t\t}\n\t}\n\n\tcancelWebsocketRetry?: () => void;\n\n\tasync connect() {\n\t\tif (this.status === WebSocketStatus.Connected) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Always cancel any previously initiated connection retryer instances\n\t\tif (this.cancelWebsocketRetry) {\n\t\t\tthis.cancelWebsocketRetry();\n\t\t\tthis.cancelWebsocketRetry = undefined;\n\t\t}\n\n\t\tthis.receivedOnOpenPayload = undefined;\n\t\tthis.shouldConnect = true;\n\n\t\tconst abortableRetry = () => {\n\t\t\tlet cancelAttempt = false;\n\n\t\t\tconst retryPromise = retry(this.createWebSocketConnection.bind(this), {\n\t\t\t\tdelay: this.configuration.delay,\n\t\t\t\tinitialDelay: this.configuration.initialDelay,\n\t\t\t\tfactor: this.configuration.factor,\n\t\t\t\tmaxAttempts: this.configuration.maxAttempts,\n\t\t\t\tminDelay: this.configuration.minDelay,\n\t\t\t\tmaxDelay: this.configuration.maxDelay,\n\t\t\t\tjitter: this.configuration.jitter,\n\t\t\t\ttimeout: this.configuration.timeout,\n\t\t\t\thandleTimeout: this.configuration.handleTimeout,\n\t\t\t\tbeforeAttempt: (context) => {\n\t\t\t\t\tif (!this.shouldConnect || cancelAttempt) {\n\t\t\t\t\t\tcontext.abort();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t}).catch((error: any) => {\n\t\t\t\t// If we aborted the connection attempt then don’t throw an error\n\t\t\t\t// ref: https://github.com/lifeomic/attempt/blob/master/src/index.ts#L136\n\t\t\t\tif (error && error.code !== \"ATTEMPT_ABORTED\") {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tretryPromise,\n\t\t\t\tcancelFunc: () => {\n\t\t\t\t\tcancelAttempt = true;\n\t\t\t\t},\n\t\t\t};\n\t\t};\n\n\t\tconst { retryPromise, cancelFunc } = abortableRetry();\n\t\tthis.cancelWebsocketRetry = cancelFunc;\n\n\t\treturn retryPromise;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tattachWebSocketListeners(ws: HocusPocusWebSocket, reject: Function) {\n\t\tconst { identifier } = ws;\n\t\tconst onMessageHandler = (payload: any) => this.emit(\"message\", payload);\n\t\tconst onCloseHandler = (payload: any) =>\n\t\t\tthis.emit(\"close\", { event: payload });\n\t\tconst onOpenHandler = (payload: any) => this.emit(\"open\", payload);\n\t\tconst onErrorHandler = (err: any) => {\n\t\t\treject(err);\n\t\t};\n\n\t\tthis.webSocketHandlers[identifier] = {\n\t\t\tmessage: onMessageHandler,\n\t\t\tclose: onCloseHandler,\n\t\t\topen: onOpenHandler,\n\t\t\terror: onErrorHandler,\n\t\t};\n\n\t\tconst handlers = this.webSocketHandlers[ws.identifier];\n\n\t\tObject.keys(handlers).forEach((name) => {\n\t\t\tws.addEventListener(name, handlers[name]);\n\t\t});\n\t}\n\n\tcleanupWebSocket() {\n\t\tif (!this.webSocket) {\n\t\t\treturn;\n\t\t}\n\t\tconst { identifier } = this.webSocket;\n\t\tconst handlers = this.webSocketHandlers[identifier];\n\n\t\tObject.keys(handlers).forEach((name) => {\n\t\t\tthis.webSocket?.removeEventListener(name, handlers[name]);\n\t\t\tdelete this.webSocketHandlers[identifier];\n\t\t});\n\t\tthis.webSocket.close();\n\t\tthis.webSocket = null;\n\t}\n\n\tcreateWebSocketConnection() {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tif (this.webSocket) {\n\t\t\t\tthis.messageQueue = [];\n\t\t\t\tthis.cleanupWebSocket();\n\t\t\t}\n\t\t\tthis.lastMessageReceived = 0;\n\t\t\tthis.identifier += 1;\n\n\t\t\t// Init the WebSocket connection\n\t\t\tconst ws = new this.configuration.WebSocketPolyfill(this.url);\n\t\t\tws.binaryType = \"arraybuffer\";\n\t\t\tws.identifier = this.identifier;\n\n\t\t\tthis.attachWebSocketListeners(ws, reject);\n\n\t\t\tthis.webSocket = ws;\n\n\t\t\t// Reset the status\n\t\t\tthis.status = WebSocketStatus.Connecting;\n\t\t\tthis.emit(\"status\", { status: WebSocketStatus.Connecting });\n\n\t\t\t// Store resolve/reject for later use\n\t\t\tthis.connectionAttempt = {\n\t\t\t\tresolve,\n\t\t\t\treject,\n\t\t\t};\n\t\t});\n\t}\n\n\tonMessage(event: MessageEvent) {\n\t\tthis.resolveConnectionAttempt();\n\n\t\tthis.lastMessageReceived = time.getUnixTime();\n\n\t\tconst data = new Uint8Array(event.data as ArrayBuffer);\n\n\t\t// Check for connection-level Ping message (no document name prefix)\n\t\t// Ping messages are sent as just the message type byte (length 1)\n\t\t// We check length to avoid confusing with regular messages that happen to have\n\t\t// a document name length of 9 as the first byte\n\t\tif (data.length === 1 && data[0] === MessageType.Ping) {\n\t\t\tthis.sendPong();\n\t\t\treturn;\n\t\t}\n\n\t\tconst message = new IncomingMessage(data);\n\t\tconst rawKey = message.peekVarString();\n\n\t\tconst provider = this.configuration.providerMap.get(rawKey);\n\t\tprovider?.onMessage(event);\n\t}\n\n\t/**\n\t * Send application-level Pong response to server Ping\n\t */\n\tprivate sendPong() {\n\t\tconst encoder = encoding.createEncoder();\n\t\tencoding.writeVarUint(encoder, MessageType.Pong);\n\t\tthis.send(encoding.toUint8Array(encoder));\n\t}\n\n\tresolveConnectionAttempt() {\n\t\tif (this.connectionAttempt) {\n\t\t\tthis.connectionAttempt.resolve();\n\t\t\tthis.connectionAttempt = null;\n\n\t\t\tthis.status = WebSocketStatus.Connected;\n\t\t\tthis.emit(\"status\", { status: WebSocketStatus.Connected });\n\t\t\tthis.emit(\"connect\");\n\t\t\tthis.messageQueue.forEach((message) => this.send(message));\n\t\t\tthis.messageQueue = [];\n\t\t}\n\t}\n\n\tstopConnectionAttempt() {\n\t\tthis.connectionAttempt = null;\n\t}\n\n\trejectConnectionAttempt() {\n\t\tthis.connectionAttempt?.reject();\n\t\tthis.connectionAttempt = null;\n\t}\n\n\tcloseTries = 0;\n\n\tcheckConnection() {\n\t\t// Don’t check the connection when it’s not even established\n\t\tif (this.status !== WebSocketStatus.Connected) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Don’t close the connection while waiting for the first message\n\t\tif (!this.lastMessageReceived) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Don’t close the connection when a message was received recently\n\t\tif (\n\t\t\tthis.configuration.messageReconnectTimeout >=\n\t\t\ttime.getUnixTime() - this.lastMessageReceived\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// No message received in a long time, not even your own\n\t\t// Awareness updates, which are updated every 15 seconds\n\t\t// if awareness is enabled.\n\t\tthis.closeTries += 1;\n\t\t// https://bugs.webkit.org/show_bug.cgi?id=247943\n\t\tif (this.closeTries > 2) {\n\t\t\tthis.onClose({\n\t\t\t\tevent: {\n\t\t\t\t\tcode: 4408,\n\t\t\t\t\treason: \"forced\",\n\t\t\t\t},\n\t\t\t});\n\t\t\tthis.closeTries = 0;\n\t\t} else {\n\t\t\tthis.webSocket?.close();\n\t\t\tthis.messageQueue = [];\n\t\t}\n\t}\n\n\tget serverUrl() {\n\t\tif (this.configuration.preserveTrailingSlash) {\n\t\t\treturn this.configuration.url;\n\t\t}\n\n\t\t// By default, ensure that the URL never ends with /\n\t\tlet url = this.configuration.url;\n\t\twhile (url[url.length - 1] === \"/\") {\n\t\t\turl = url.slice(0, url.length - 1);\n\t\t}\n\n\t\treturn url;\n\t}\n\n\tget url() {\n\t\treturn this.serverUrl;\n\t}\n\n\tdisconnect() {\n\t\tthis.shouldConnect = false;\n\n\t\tif (this.webSocket === null) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.webSocket.close();\n\t\t\tthis.messageQueue = [];\n\t\t} catch (e) {\n\t\t\tconsole.error(e);\n\t\t}\n\t}\n\n\tprivate parseQueuedMessage(\n\t\tmessage: Uint8Array,\n\t): { documentName: string; messageType: number } | null {\n\t\ttry {\n\t\t\tconst decoder = createDecoder(message);\n\t\t\tconst documentName = readVarString(decoder);\n\t\t\tconst messageType = readVarUint(decoder);\n\t\t\treturn { documentName, messageType };\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate addToQueue(message: any) {\n\t\tif (message instanceof Uint8Array) {\n\t\t\tconst parsed = this.parseQueuedMessage(message);\n\t\t\tif (\n\t\t\t\tparsed &&\n\t\t\t\tHocuspocusProviderWebsocket.DEDUPLICATABLE_TYPES.has(parsed.messageType)\n\t\t\t) {\n\t\t\t\tthis.messageQueue = this.messageQueue.filter((queued) => {\n\t\t\t\t\tif (!(queued instanceof Uint8Array)) return true;\n\t\t\t\t\tconst queuedParsed = this.parseQueuedMessage(queued);\n\t\t\t\t\tif (!queuedParsed) return true;\n\t\t\t\t\treturn !(\n\t\t\t\t\t\tqueuedParsed.documentName === parsed.documentName &&\n\t\t\t\t\t\tqueuedParsed.messageType === parsed.messageType\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthis.messageQueue.push(message);\n\t}\n\n\tsend(message: any) {\n\t\tif (this.webSocket?.readyState === WsReadyStates.Open) {\n\t\t\tthis.webSocket.send(message);\n\t\t} else {\n\t\t\tthis.addToQueue(message);\n\t\t}\n\t}\n\n\tonClose({ event }: onCloseParameters) {\n\t\tthis.closeTries = 0;\n\t\tthis.cleanupWebSocket();\n\n\t\tif (this.connectionAttempt) {\n\t\t\t// That connection attempt failed.\n\t\t\tthis.rejectConnectionAttempt();\n\t\t}\n\n\t\t// Let’s update the connection status.\n\t\tthis.status = WebSocketStatus.Disconnected;\n\t\tthis.emit(\"status\", { status: WebSocketStatus.Disconnected });\n\t\tthis.emit(\"disconnect\", { event });\n\n\t\t// trigger connect if no retry is running and we want to have a connection\n\t\tif (!this.cancelWebsocketRetry && this.shouldConnect) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.connect();\n\t\t\t}, this.configuration.delay);\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tthis.emit(\"destroy\");\n\n\t\tclearInterval(this.intervals.connectionChecker);\n\n\t\t// If there is still a connection attempt outstanding then we should stop\n\t\t// it before calling disconnect, otherwise it will be rejected in the onClose\n\t\t// handler and trigger a retry\n\t\tthis.stopConnectionAttempt();\n\n\t\tthis.disconnect();\n\n\t\tthis.removeAllListeners();\n\n\t\tthis.cleanupWebSocket();\n\t}\n}\n","import { type CloseEvent, readAuthMessage } from \"@hocuspocus/common\";\nimport { readVarInt, readVarString } from \"lib0/decoding\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport { messageYjsSyncStep2, readSyncMessage } from \"y-protocols/sync\";\nimport type { HocuspocusProvider } from \"./HocuspocusProvider.ts\";\nimport type { IncomingMessage } from \"./IncomingMessage.ts\";\nimport { OutgoingMessage } from \"./OutgoingMessage.ts\";\nimport { MessageType } from \"./types.ts\";\n\nexport class MessageReceiver {\n\tmessage: IncomingMessage;\n\n\tconstructor(message: IncomingMessage) {\n\t\tthis.message = message;\n\t}\n\n\tpublic apply(provider: HocuspocusProvider, emitSynced: boolean) {\n\t\tconst { message } = this;\n\t\tconst type = message.readVarUint();\n\n\t\tconst emptyMessageLength = message.length();\n\n\t\tswitch (type) {\n\t\t\tcase MessageType.Sync:\n\t\t\t\tthis.applySyncMessage(provider, emitSynced);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.Awareness:\n\t\t\t\tthis.applyAwarenessMessage(provider);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.Auth:\n\t\t\t\tthis.applyAuthMessage(provider);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.QueryAwareness:\n\t\t\t\tthis.applyQueryAwarenessMessage(provider);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.Stateless:\n\t\t\t\tprovider.receiveStateless(readVarString(message.decoder));\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.SyncStatus:\n\t\t\t\tthis.applySyncStatusMessage(\n\t\t\t\t\tprovider,\n\t\t\t\t\treadVarInt(message.decoder) === 1,\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.CLOSE: {\n\t\t\t\t// eslint-disable-next-line no-case-declarations\n\t\t\t\tconst event: CloseEvent = {\n\t\t\t\t\tcode: 1000,\n\t\t\t\t\treason: readVarString(message.decoder),\n\t\t\t\t};\n\t\t\t\tprovider.onClose();\n\t\t\t\tprovider.configuration.onClose({ event });\n\t\t\t\tprovider.forwardClose({ event });\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tconsole.error(`Can’t apply message of unknown type: ${type}`);\n\t\t}\n\n\t\t// Reply\n\t\tif (message.length() > emptyMessageLength + 1) {\n\t\t\t// length of documentName (considered in emptyMessageLength plus length of yjs sync type, set in applySyncMessage)\n\t\t\t// @ts-expect-error\n\t\t\tprovider.send(OutgoingMessage, { encoder: message.encoder });\n\t\t}\n\t}\n\n\tprivate applySyncMessage(provider: HocuspocusProvider, emitSynced: boolean) {\n\t\tconst { message } = this;\n\n\t\tmessage.writeVarUint(MessageType.Sync);\n\n\t\t// Apply update\n\t\tconst syncMessageType = readSyncMessage(\n\t\t\tmessage.decoder,\n\t\t\tmessage.encoder,\n\t\t\tprovider.document,\n\t\t\tprovider,\n\t\t);\n\n\t\t// Synced once we receive Step2\n\t\tif (emitSynced && syncMessageType === messageYjsSyncStep2) {\n\t\t\tprovider.synced = true;\n\t\t}\n\t}\n\n\tapplySyncStatusMessage(provider: HocuspocusProvider, applied: boolean) {\n\t\tif (applied) {\n\t\t\tprovider.decrementUnsyncedChanges();\n\t\t}\n\t}\n\n\tprivate applyAwarenessMessage(provider: HocuspocusProvider) {\n\t\tif (!provider.awareness) return;\n\n\t\tconst { message } = this;\n\n\t\tawarenessProtocol.applyAwarenessUpdate(\n\t\t\tprovider.awareness,\n\t\t\tmessage.readVarUint8Array(),\n\t\t\tprovider,\n\t\t);\n\t}\n\n\tprivate applyAuthMessage(provider: HocuspocusProvider) {\n\t\tconst { message } = this;\n\n\t\treadAuthMessage(\n\t\t\tmessage.decoder,\n\t\t\tprovider.sendToken.bind(provider),\n\t\t\tprovider.permissionDeniedHandler.bind(provider),\n\t\t\tprovider.authenticatedHandler.bind(provider),\n\t\t);\n\t}\n\n\tprivate applyQueryAwarenessMessage(provider: HocuspocusProvider) {\n\t\tif (!provider.awareness) return;\n\n\t\tconst { message } = this;\n\n\t\tmessage.writeVarUint(MessageType.Awareness);\n\t\tmessage.writeVarUint8Array(\n\t\t\tawarenessProtocol.encodeAwarenessUpdate(\n\t\t\t\tprovider.awareness,\n\t\t\t\tArray.from(provider.awareness.getStates().keys()),\n\t\t\t),\n\t\t);\n\t}\n}\n","import type { Encoder } from \"lib0/encoding\";\nimport { toUint8Array } from \"lib0/encoding\";\nimport type { ConstructableOutgoingMessage } from \"./types.ts\";\n\nexport class MessageSender {\n\tencoder: Encoder;\n\n\tmessage: any;\n\n\tconstructor(Message: ConstructableOutgoingMessage, args: any = {}) {\n\t\tthis.message = new Message();\n\t\tthis.encoder = this.message.get(args);\n\t}\n\n\tcreate() {\n\t\treturn toUint8Array(this.encoder);\n\t}\n\n\tsend(webSocket: any) {\n\t\twebSocket?.send(this.create());\n\t}\n}\n","export const version: string =\n\t// @ts-expect-error - __HOCUSPOCUS_VERSION__ is replaced at build time by rolldown\n\ttypeof __HOCUSPOCUS_VERSION__ !== \"undefined\"\n\t\t? // @ts-expect-error - __HOCUSPOCUS_VERSION__ is replaced at build time by rolldown\n\t\t\t__HOCUSPOCUS_VERSION__\n\t\t: \"unknown\";\n","import { writeVarString, writeVarUint } from \"lib0/encoding\";\nimport { writeAuthentication } from \"@hocuspocus/common\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\nimport { version } from \"../version.ts\";\n\nexport class AuthenticationMessage extends OutgoingMessage {\n\ttype = MessageType.Auth;\n\n\tdescription = \"Authentication\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tif (typeof args.token === \"undefined\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"The authentication message requires `token` as an argument.\",\n\t\t\t);\n\t\t}\n\n\t\twriteVarString(this.encoder, args.documentName!);\n\t\twriteVarUint(this.encoder, this.type);\n\t\twriteAuthentication(this.encoder, args.token);\n\t\twriteVarString(this.encoder, version);\n\n\t\treturn this.encoder;\n\t}\n}\n","import * as encoding from \"lib0/encoding\";\nimport { encodeAwarenessUpdate } from \"y-protocols/awareness\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class AwarenessMessage extends OutgoingMessage {\n\ttype = MessageType.Awareness;\n\n\tdescription = \"Awareness states update\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tif (typeof args.awareness === \"undefined\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"The awareness message requires awareness as an argument\",\n\t\t\t);\n\t\t}\n\n\t\tif (typeof args.clients === \"undefined\") {\n\t\t\tthrow new Error(\"The awareness message requires clients as an argument\");\n\t\t}\n\n\t\tencoding.writeVarString(this.encoder, args.documentName!);\n\t\tencoding.writeVarUint(this.encoder, this.type);\n\n\t\tlet awarenessUpdate;\n\t\tif (args.states === undefined) {\n\t\t\tawarenessUpdate = encodeAwarenessUpdate(args.awareness, args.clients);\n\t\t} else {\n\t\t\tawarenessUpdate = encodeAwarenessUpdate(\n\t\t\t\targs.awareness,\n\t\t\t\targs.clients,\n\t\t\t\targs.states,\n\t\t\t);\n\t\t}\n\n\t\tencoding.writeVarUint8Array(this.encoder, awarenessUpdate);\n\n\t\treturn this.encoder;\n\t}\n}\n","import { writeVarString, writeVarUint } from \"lib0/encoding\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class StatelessMessage extends OutgoingMessage {\n\ttype = MessageType.Stateless;\n\n\tdescription = \"A stateless message\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\twriteVarString(this.encoder, args.documentName!);\n\t\twriteVarUint(this.encoder, this.type);\n\t\twriteVarString(this.encoder, args.payload ?? \"\");\n\n\t\treturn this.encoder;\n\t}\n}\n","import * as encoding from \"lib0/encoding\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class SyncStepOneMessage extends OutgoingMessage {\n\ttype = MessageType.Sync;\n\n\tdescription = \"First sync step\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tif (typeof args.document === \"undefined\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"The sync step one message requires document as an argument\",\n\t\t\t);\n\t\t}\n\n\t\tencoding.writeVarString(this.encoder, args.documentName!);\n\t\tencoding.writeVarUint(this.encoder, this.type);\n\t\tsyncProtocol.writeSyncStep1(this.encoder, args.document);\n\n\t\treturn this.encoder;\n\t}\n}\n","import { writeVarString, writeVarUint } from \"lib0/encoding\";\nimport { writeUpdate } from \"y-protocols/sync\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class UpdateMessage extends OutgoingMessage {\n\ttype = MessageType.Sync;\n\n\tdescription = \"A document update\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\twriteVarString(this.encoder, args.documentName!);\n\t\twriteVarUint(this.encoder, this.type);\n\n\t\twriteUpdate(this.encoder, args.update);\n\n\t\treturn this.encoder;\n\t}\n}\n","import { awarenessStatesToArray, makeRoutingKey, parseRoutingKey } from \"@hocuspocus/common\";\nimport { Awareness, removeAwarenessStates } from \"y-protocols/awareness\";\nimport * as Y from \"yjs\";\nimport EventEmitter from \"./EventEmitter.ts\";\nimport type { CompleteHocuspocusProviderWebsocketConfiguration } from \"./HocuspocusProviderWebsocket.ts\";\nimport { HocuspocusProviderWebsocket } from \"./HocuspocusProviderWebsocket.ts\";\nimport { IncomingMessage } from \"./IncomingMessage.ts\";\nimport { MessageReceiver } from \"./MessageReceiver.ts\";\nimport { MessageSender } from \"./MessageSender.ts\";\nimport { AuthenticationMessage } from \"./OutgoingMessages/AuthenticationMessage.ts\";\nimport { AwarenessMessage } from \"./OutgoingMessages/AwarenessMessage.ts\";\nimport { StatelessMessage } from \"./OutgoingMessages/StatelessMessage.ts\";\nimport { SyncStepOneMessage } from \"./OutgoingMessages/SyncStepOneMessage.ts\";\nimport { UpdateMessage } from \"./OutgoingMessages/UpdateMessage.ts\";\nimport type {\n\tAuthorizedScope,\n\tConstructableOutgoingMessage,\n\tonAuthenticatedParameters,\n\tonAuthenticationFailedParameters,\n\tonAwarenessChangeParameters,\n\tonAwarenessUpdateParameters,\n\tonCloseParameters,\n\tonDisconnectParameters,\n\tonMessageParameters,\n\tonOpenParameters,\n\tonOutgoingMessageParameters,\n\tonStatelessParameters,\n\tonStatusParameters,\n\tonSyncedParameters,\n\tonUnsyncedChangesParameters,\n} from \"./types.ts\";\n\nexport type HocuspocusProviderConfiguration = Required<\n\tPick<CompleteHocuspocusProviderConfiguration, \"name\">\n> &\n\tPartial<CompleteHocuspocusProviderConfiguration> &\n\t(\n\t\t| (Required<Pick<CompleteHocuspocusProviderWebsocketConfiguration, \"url\">> &\n\t\t\t\tPartial<\n\t\t\t\t\tPick<\n\t\t\t\t\t\tCompleteHocuspocusProviderWebsocketConfiguration,\n\t\t\t\t\t\t\"preserveTrailingSlash\"\n\t\t\t\t\t>\n\t\t\t\t>)\n\t\t| Required<\n\t\t\t\tPick<CompleteHocuspocusProviderConfiguration, \"websocketProvider\">\n\t\t >\n\t);\n\nexport interface CompleteHocuspocusProviderConfiguration {\n\t/**\n\t * The identifier/name of your document\n\t */\n\tname: string;\n\t/**\n\t * The actual Y.js document\n\t */\n\tdocument: Y.Doc;\n\n\t/**\n\t * An Awareness instance to keep the presence state of all clients.\n\t *\n\t * You can disable sharing awareness information by passing `null`.\n\t * Note that having no awareness information shared across all connections will break our ping checks\n\t * and thus trigger reconnects. You should always have at least one Provider with enabled awareness per\n\t * socket connection, or ensure that the Provider receives messages before running into `HocuspocusProviderWebsocket.messageReconnectTimeout`.\n\t */\n\tawareness: Awareness | null;\n\n\t/**\n\t * A token that’s sent to the backend for authentication purposes.\n\t */\n\ttoken: string | (() => string) | (() => Promise<string>) | null;\n\n\t/**\n\t * Hocuspocus websocket provider\n\t */\n\twebsocketProvider: HocuspocusProviderWebsocket;\n\n\t/**\n\t * Enable session-aware multiplexing. When true, the provider embeds a unique\n\t * sessionId in the documentName field of every message, allowing multiple\n\t * providers with the same document name on a single WebSocket connection.\n\t *\n\t * Only set this to `true` when connecting to a v4 server that does \n\t * support session awareness.\n\t *\n\t * Default: false\n\t */\n\tsessionAwareness: boolean;\n\n\t/**\n\t * Force syncing the document in the defined interval.\n\t */\n\tforceSyncInterval: false | number;\n\n\tonAuthenticated: (data: onAuthenticatedParameters) => void;\n\tonAuthenticationFailed: (data: onAuthenticationFailedParameters) => void;\n\tonOpen: (data: onOpenParameters) => void;\n\tonConnect: () => void;\n\tonStatus: (data: onStatusParameters) => void;\n\tonMessage: (data: onMessageParameters) => void;\n\tonOutgoingMessage: (data: onOutgoingMessageParameters) => void;\n\tonSynced: (data: onSyncedParameters) => void;\n\tonDisconnect: (data: onDisconnectParameters) => void;\n\tonClose: (data: onCloseParameters) => void;\n\tonDestroy: () => void;\n\tonAwarenessUpdate: (data: onAwarenessUpdateParameters) => void;\n\tonAwarenessChange: (data: onAwarenessChangeParameters) => void;\n\tonStateless: (data: onStatelessParameters) => void;\n\tonUnsyncedChanges: (data: onUnsyncedChangesParameters) => void;\n}\n\nexport class AwarenessError extends Error {\n\tcode = 1001;\n}\n\nexport class HocuspocusProvider extends EventEmitter {\n\tpublic configuration: CompleteHocuspocusProviderConfiguration = {\n\t\tname: \"\",\n\t\t// @ts-expect-error\n\t\tdocument: undefined,\n\t\t// @ts-expect-error\n\t\tawareness: undefined,\n\t\ttoken: null,\n\t\tsessionAwareness: false,\n\t\tforceSyncInterval: false,\n\t\tonAuthenticated: () => null,\n\t\tonAuthenticationFailed: () => null,\n\t\tonOpen: () => null,\n\t\tonConnect: () => null,\n\t\tonMessage: () => null,\n\t\tonOutgoingMessage: () => null,\n\t\tonSynced: () => null,\n\t\tonStatus: () => null,\n\t\tonDisconnect: () => null,\n\t\tonClose: () => null,\n\t\tonDestroy: () => null,\n\t\tonAwarenessUpdate: () => null,\n\t\tonAwarenessChange: () => null,\n\t\tonStateless: () => null,\n\t\tonUnsyncedChanges: () => null,\n\t};\n\n\tisSynced = false;\n\n\tunsyncedChanges = 0;\n\n\tisAuthenticated = false;\n\n\tauthorizedScope: AuthorizedScope | undefined = undefined;\n\n\t// @internal\n\tmanageSocket = false;\n\n\tprivate _isAttached = false;\n\n\t/**\n\t * Unique session identifier for this provider instance.\n\t * Used for multiplexing multiple providers with the same document name on a single WebSocket.\n\t */\n\tsessionId: string = Math.random().toString(36).slice(2);\n\n\t/**\n\t * The effective name used as the first VarString in messages.\n\t * When `sessionAwareness` is enabled, returns a composite key (documentName\\0sessionId).\n\t * Otherwise, returns the plain document name.\n\t */\n\tget effectiveName(): string {\n\t\treturn this.configuration.sessionAwareness\n\t\t\t? makeRoutingKey(this.configuration.name, this.sessionId)\n\t\t\t: this.configuration.name;\n\t}\n\n\tintervals: any = {\n\t\tforceSync: null,\n\t};\n\n\tconstructor(configuration: HocuspocusProviderConfiguration) {\n\t\tsuper();\n\t\tthis.setConfiguration(configuration);\n\n\t\tthis.configuration.document = configuration.document\n\t\t\t? configuration.document\n\t\t\t: new Y.Doc();\n\t\tthis.configuration.awareness =\n\t\t\tconfiguration.awareness !== undefined\n\t\t\t\t? configuration.awareness\n\t\t\t\t: new Awareness(this.document);\n\n\t\tthis.on(\"open\", this.configuration.onOpen);\n\t\tthis.on(\"message\", this.configuration.onMessage);\n\t\tthis.on(\"outgoingMessage\", this.configuration.onOutgoingMessage);\n\t\tthis.on(\"synced\", this.configuration.onSynced);\n\t\tthis.on(\"destroy\", this.configuration.onDestroy);\n\t\tthis.on(\"awarenessUpdate\", this.configuration.onAwarenessUpdate);\n\t\tthis.on(\"awarenessChange\", this.configuration.onAwarenessChange);\n\t\tthis.on(\"stateless\", this.configuration.onStateless);\n\t\tthis.on(\"unsyncedChanges\", this.configuration.onUnsyncedChanges);\n\n\t\tthis.on(\"authenticated\", this.configuration.onAuthenticated);\n\t\tthis.on(\"authenticationFailed\", this.configuration.onAuthenticationFailed);\n\n\t\tthis.awareness?.on(\"update\", () => {\n\t\t\tthis.emit(\"awarenessUpdate\", {\n\t\t\t\tstates: awarenessStatesToArray(this.awareness!.getStates()),\n\t\t\t});\n\t\t});\n\n\t\tthis.awareness?.on(\"change\", () => {\n\t\t\tthis.emit(\"awarenessChange\", {\n\t\t\t\tstates: awarenessStatesToArray(this.awareness!.getStates()),\n\t\t\t});\n\t\t});\n\n\t\tthis.document.on(\"update\", this.boundDocumentUpdateHandler);\n\t\tthis.awareness?.on(\"update\", this.boundAwarenessUpdateHandler);\n\n\t\tthis.registerEventListeners();\n\n\t\tif (\n\t\t\tthis.configuration.forceSyncInterval &&\n\t\t\ttypeof this.configuration.forceSyncInterval === \"number\"\n\t\t) {\n\t\t\tthis.intervals.forceSync = setInterval(\n\t\t\t\tthis.forceSync.bind(this),\n\t\t\t\tthis.configuration.forceSyncInterval,\n\t\t\t);\n\t\t}\n\n\t\tif (this.manageSocket) {\n\t\t\tthis.attach();\n\t\t}\n\t}\n\n\tboundDocumentUpdateHandler = this.documentUpdateHandler.bind(this);\n\n\tboundAwarenessUpdateHandler = this.awarenessUpdateHandler.bind(this);\n\n\tboundPageHide = this.pageHide.bind(this);\n\n\tboundOnOpen = this.onOpen.bind(this);\n\n\tboundOnClose = this.onClose.bind(this);\n\n\tforwardConnect = () => this.emit(\"connect\");\n\n\tforwardStatus = (e: onStatusParameters) => this.emit(\"status\", e);\n\n\tforwardClose = (e: onCloseParameters) => this.emit(\"close\", e);\n\n\tforwardDisconnect = (e: onDisconnectParameters) => this.emit(\"disconnect\", e);\n\n\tforwardDestroy = () => this.emit(\"destroy\");\n\n\tpublic setConfiguration(\n\t\tconfiguration: Partial<HocuspocusProviderConfiguration> = {},\n\t): void {\n\t\tif (!configuration.websocketProvider) {\n\t\t\tthis.manageSocket = true;\n\t\t\tthis.configuration.websocketProvider = new HocuspocusProviderWebsocket(\n\t\t\t\tconfiguration as CompleteHocuspocusProviderWebsocketConfiguration,\n\t\t\t);\n\t\t}\n\n\t\tthis.configuration = { ...this.configuration, ...configuration };\n\t}\n\n\tget document() {\n\t\treturn this.configuration.document;\n\t}\n\n\tpublic get isAttached() {\n\t\treturn this._isAttached;\n\t}\n\n\tget awareness() {\n\t\treturn this.configuration.awareness;\n\t}\n\n\tget hasUnsyncedChanges(): boolean {\n\t\treturn this.unsyncedChanges > 0;\n\t}\n\n\tprivate resetUnsyncedChanges() {\n\t\tthis.unsyncedChanges = 1;\n\t\tthis.emit(\"unsyncedChanges\", { number: this.unsyncedChanges });\n\t}\n\n\tincrementUnsyncedChanges() {\n\t\tthis.unsyncedChanges += 1;\n\t\tthis.emit(\"unsyncedChanges\", { number: this.unsyncedChanges });\n\t}\n\n\tdecrementUnsyncedChanges() {\n\t\tif (this.unsyncedChanges > 0) {\n\t\t\tthis.unsyncedChanges -= 1;\n\t\t}\n\n\t\tif (this.unsyncedChanges === 0) {\n\t\t\tthis.synced = true;\n\t\t}\n\n\t\tthis.emit(\"unsyncedChanges\", { number: this.unsyncedChanges });\n\t}\n\n\tforceSync() {\n\t\tthis.resetUnsyncedChanges();\n\n\t\tthis.send(SyncStepOneMessage, {\n\t\t\tdocument: this.document,\n\t\t\tdocumentName: this.effectiveName,\n\t\t});\n\t}\n\n\tpageHide() {\n\t\tif (this.awareness) {\n\t\t\tremoveAwarenessStates(\n\t\t\t\tthis.awareness,\n\t\t\t\t[this.document.clientID],\n\t\t\t\t\"page hide\",\n\t\t\t);\n\t\t}\n\t}\n\n\tregisterEventListeners() {\n\t\tif (typeof window === \"undefined\" || !(\"addEventListener\" in window)) {\n\t\t\treturn;\n\t\t}\n\n\t\twindow.addEventListener(\"pagehide\", this.boundPageHide);\n\t}\n\n\tsendStateless(payload: string) {\n\t\tthis.send(StatelessMessage, {\n\t\t\tdocumentName: this.effectiveName,\n\t\t\tpayload,\n\t\t});\n\t}\n\n\tasync sendToken() {\n\t\tlet token: string | null;\n\t\ttry {\n\t\t\ttoken = await this.getToken();\n\t\t} catch (error) {\n\t\t\tthis.permissionDeniedHandler(\n\t\t\t\t`Failed to get token during sendToken(): ${error}`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.send(AuthenticationMessage, {\n\t\t\ttoken: token ?? \"\",\n\t\t\tdocumentName: this.effectiveName,\n\t\t});\n\t}\n\n\tdocumentUpdateHandler(update: Uint8Array, origin: any) {\n\t\tif (origin === this) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.incrementUnsyncedChanges();\n\t\tthis.send(UpdateMessage, { update, documentName: this.effectiveName });\n\t}\n\n\tawarenessUpdateHandler({ added, updated, removed }: any, origin: any) {\n\t\tconst changedClients = added.concat(updated).concat(removed);\n\n\t\tthis.send(AwarenessMessage, {\n\t\t\tawareness: this.awareness,\n\t\t\tclients: changedClients,\n\t\t\tdocumentName: this.effectiveName,\n\t\t});\n\t}\n\n\t/**\n\t * Indicates whether a first handshake with the server has been established\n\t *\n\t * Note: this does not mean all updates from the client have been persisted to the backend. For this,\n\t * use `hasUnsyncedChanges`.\n\t */\n\tget synced(): boolean {\n\t\treturn this.isSynced;\n\t}\n\n\tset synced(state) {\n\t\tif (this.isSynced === state) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.isSynced = state;\n\n\t\tif (state) {\n\t\t\tthis.emit(\"synced\", { state });\n\t\t}\n\t}\n\n\treceiveStateless(payload: string) {\n\t\tthis.emit(\"stateless\", { payload });\n\t}\n\n\t// not needed, but provides backward compatibility with e.g. lexical/yjs\n\tasync connect() {\n\t\tif (this.manageSocket) {\n\t\t\treturn this.configuration.websocketProvider.connect();\n\t\t}\n\n\t\tconsole.warn(\n\t\t\t\"HocuspocusProvider::connect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.\",\n\t\t);\n\t}\n\n\tdisconnect() {\n\t\tif (this.manageSocket) {\n\t\t\treturn this.configuration.websocketProvider.disconnect();\n\t\t}\n\n\t\tconsole.warn(\n\t\t\t\"HocuspocusProvider::disconnect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.\",\n\t\t);\n\t}\n\n\tasync onOpen(event: Event) {\n\t\tthis.isAuthenticated = false;\n\n\t\tthis.emit(\"open\", { event });\n\t\tawait this.sendToken();\n\t\tthis.startSync();\n\t}\n\n\tasync getToken() {\n\t\tif (typeof this.configuration.token === \"function\") {\n\t\t\tconst token = await this.configuration.token();\n\t\t\treturn token;\n\t\t}\n\n\t\treturn this.configuration.token;\n\t}\n\n\tstartSync() {\n\t\tthis.resetUnsyncedChanges();\n\n\t\tthis.send(SyncStepOneMessage, {\n\t\t\tdocument: this.document,\n\t\t\tdocumentName: this.effectiveName,\n\t\t});\n\n\t\tif (this.awareness && this.awareness.getLocalState() !== null) {\n\t\t\tthis.send(AwarenessMessage, {\n\t\t\t\tawareness: this.awareness,\n\t\t\t\tclients: [this.document.clientID],\n\t\t\t\tdocumentName: this.effectiveName,\n\t\t\t});\n\t\t}\n\t}\n\n\tsend(message: ConstructableOutgoingMessage, args: any) {\n\t\tif (!this._isAttached) return;\n\n\t\tconst messageSender = new MessageSender(message, args);\n\n\t\tthis.emit(\"outgoingMessage\", { message: messageSender.message });\n\t\tmessageSender.send(this.configuration.websocketProvider);\n\t}\n\n\tonMessage(event: MessageEvent) {\n\t\tconst message = new IncomingMessage(event.data);\n\n\t\tconst rawKey = message.readVarString();\n\t\t// Extract actual documentName from potentially composite routing key\n\t\tconst { documentName } = parseRoutingKey(rawKey);\n\n\t\tmessage.writeVarString(this.effectiveName);\n\n\t\tthis.emit(\"message\", { event, message: new IncomingMessage(event.data) });\n\n\t\tnew MessageReceiver(message).apply(this, true);\n\t}\n\n\tonClose() {\n\t\tthis.isAuthenticated = false;\n\t\tthis.synced = false;\n\n\t\t// update awareness (all users except local left)\n\t\tif (this.awareness) {\n\t\t\tremoveAwarenessStates(\n\t\t\t\tthis.awareness,\n\t\t\t\tArray.from(this.awareness.getStates().keys()).filter(\n\t\t\t\t\t(client) => client !== this.document.clientID,\n\t\t\t\t),\n\t\t\t\tthis,\n\t\t\t);\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tthis.emit(\"destroy\");\n\n\t\tif (this.intervals.forceSync) {\n\t\t\tclearInterval(this.intervals.forceSync);\n\t\t}\n\n\t\tif (this.awareness) {\n\t\t\tremoveAwarenessStates(\n\t\t\t\tthis.awareness,\n\t\t\t\t[this.document.clientID],\n\t\t\t\t\"provider destroy\",\n\t\t\t);\n\t\t\tthis.awareness.off(\"update\", this.boundAwarenessUpdateHandler);\n\t\t\tthis.awareness.destroy();\n\t\t}\n\n\t\tthis.document.off(\"update\", this.boundDocumentUpdateHandler);\n\n\t\tthis.removeAllListeners();\n\n\t\tthis.detach();\n\n\t\tif (this.manageSocket) {\n\t\t\tthis.configuration.websocketProvider.destroy();\n\t\t}\n\n\t\tif (typeof window === \"undefined\" || !(\"removeEventListener\" in window)) {\n\t\t\treturn;\n\t\t}\n\n\t\twindow.removeEventListener(\"pagehide\", this.boundPageHide);\n\t}\n\n\tdetach() {\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"connect\",\n\t\t\tthis.configuration.onConnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\"connect\", this.forwardConnect);\n\n\t\tthis.configuration.websocketProvider.off(\"status\", this.forwardStatus);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"status\",\n\t\t\tthis.configuration.onStatus,\n\t\t);\n\n\t\tthis.configuration.websocketProvider.off(\"open\", this.boundOnOpen);\n\t\tthis.configuration.websocketProvider.off(\"close\", this.boundOnClose);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"close\",\n\t\t\tthis.configuration.onClose,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\"close\", this.forwardClose);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"disconnect\",\n\t\t\tthis.configuration.onDisconnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"disconnect\",\n\t\t\tthis.forwardDisconnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"destroy\",\n\t\t\tthis.configuration.onDestroy,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\"destroy\", this.forwardDestroy);\n\n\t\tthis.configuration.websocketProvider.detach(this);\n\n\t\tthis._isAttached = false;\n\t}\n\n\tattach() {\n\t\tif (this._isAttached) return;\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"connect\",\n\t\t\tthis.configuration.onConnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"connect\", this.forwardConnect);\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"status\",\n\t\t\tthis.configuration.onStatus,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"status\", this.forwardStatus);\n\n\t\tthis.configuration.websocketProvider.on(\"open\", this.boundOnOpen);\n\n\t\tthis.configuration.websocketProvider.on(\"close\", this.boundOnClose);\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"close\",\n\t\t\tthis.configuration.onClose,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"close\", this.forwardClose);\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"disconnect\",\n\t\t\tthis.configuration.onDisconnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"disconnect\",\n\t\t\tthis.forwardDisconnect,\n\t\t);\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"destroy\",\n\t\t\tthis.configuration.onDestroy,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"destroy\", this.forwardDestroy);\n\n\t\tthis.configuration.websocketProvider.attach(this);\n\n\t\tthis._isAttached = true;\n\t}\n\n\tpermissionDeniedHandler(reason: string) {\n\t\tthis.emit(\"authenticationFailed\", { reason });\n\t\tthis.isAuthenticated = false;\n\t}\n\n\tauthenticatedHandler(scope: string) {\n\t\tthis.isAuthenticated = true;\n\t\tthis.authorizedScope = scope as AuthorizedScope;\n\n\t\tthis.emit(\"authenticated\", { scope });\n\t}\n\n\tsetAwarenessField(key: string, value: any) {\n\t\tif (!this.awareness) {\n\t\t\tthrow new AwarenessError(\n\t\t\t\t`Cannot set awareness field \"${key}\" to ${JSON.stringify(value)}. You have disabled Awareness for this provider by explicitly passing awareness: null in the provider configuration.`,\n\t\t\t);\n\t\t}\n\t\tthis.awareness.setLocalStateField(key, value);\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"hocuspocus-provider.cjs","names":["time","encoding","WsReadyStates","messageYjsSyncStep2","awarenessProtocol","Y","Awareness"],"sources":["../src/EventEmitter.ts","../src/IncomingMessage.ts","../src/types.ts","../src/OutgoingMessage.ts","../src/OutgoingMessages/CloseMessage.ts","../src/HocuspocusProviderWebsocket.ts","../src/MessageReceiver.ts","../src/MessageSender.ts","../src/version.ts","../src/OutgoingMessages/AuthenticationMessage.ts","../src/OutgoingMessages/AwarenessMessage.ts","../src/OutgoingMessages/StatelessMessage.ts","../src/OutgoingMessages/SyncStepOneMessage.ts","../src/OutgoingMessages/UpdateMessage.ts","../src/HocuspocusProvider.ts"],"sourcesContent":["export default class EventEmitter {\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tpublic callbacks: { [key: string]: Function[] } = {};\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tpublic on(event: string, fn: Function): this {\n\t\tif (!this.callbacks[event]) {\n\t\t\tthis.callbacks[event] = [];\n\t\t}\n\n\t\tthis.callbacks[event].push(fn);\n\n\t\treturn this;\n\t}\n\n\tprotected emit(event: string, ...args: any): this {\n\t\tconst callbacks = this.callbacks[event];\n\n\t\tif (callbacks) {\n\t\t\tcallbacks.forEach((callback) => callback.apply(this, args));\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tpublic off(event: string, fn?: Function): this {\n\t\tconst callbacks = this.callbacks[event];\n\n\t\tif (callbacks) {\n\t\t\tif (fn) {\n\t\t\t\tthis.callbacks[event] = callbacks.filter((callback) => callback !== fn);\n\t\t\t} else {\n\t\t\t\tdelete this.callbacks[event];\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n\n\tremoveAllListeners(): void {\n\t\tthis.callbacks = {};\n\t}\n}\n","import type { Decoder } from \"lib0/decoding\";\nimport {\n\tcreateDecoder,\n\tpeekVarString,\n\treadVarUint,\n\treadVarUint8Array,\n\treadVarString,\n} from \"lib0/decoding\";\nimport type { Encoder } from \"lib0/encoding\";\nimport {\n\tcreateEncoder,\n\twriteVarUint,\n\twriteVarUint8Array,\n\twriteVarString,\n\tlength,\n} from \"lib0/encoding\";\nimport type { MessageType } from \"./types.ts\";\n\nexport class IncomingMessage {\n\tdata: any;\n\n\tencoder: Encoder;\n\n\tdecoder: Decoder;\n\n\tconstructor(data: any) {\n\t\tthis.data = data;\n\t\tthis.encoder = createEncoder();\n\t\tthis.decoder = createDecoder(new Uint8Array(this.data));\n\t}\n\n\tpeekVarString(): string {\n\t\treturn peekVarString(this.decoder);\n\t}\n\n\treadVarUint(): MessageType {\n\t\treturn readVarUint(this.decoder);\n\t}\n\n\treadVarString(): string {\n\t\treturn readVarString(this.decoder);\n\t}\n\n\treadVarUint8Array() {\n\t\treturn readVarUint8Array(this.decoder);\n\t}\n\n\twriteVarUint(type: MessageType) {\n\t\treturn writeVarUint(this.encoder, type);\n\t}\n\n\twriteVarString(string: string) {\n\t\treturn writeVarString(this.encoder, string);\n\t}\n\n\twriteVarUint8Array(data: Uint8Array) {\n\t\treturn writeVarUint8Array(this.encoder, data);\n\t}\n\n\tlength() {\n\t\treturn length(this.encoder);\n\t}\n}\n","import type { Encoder } from \"lib0/encoding\";\nimport type { Awareness } from \"y-protocols/awareness\";\nimport type * as Y from \"yjs\";\nimport type { CloseEvent } from \"@hocuspocus/common\";\nimport type { IncomingMessage } from \"./IncomingMessage.ts\";\nimport type { OutgoingMessage } from \"./OutgoingMessage.ts\";\nimport type { AuthenticationMessage } from \"./OutgoingMessages/AuthenticationMessage.ts\";\nimport type { AwarenessMessage } from \"./OutgoingMessages/AwarenessMessage.ts\";\nimport type { QueryAwarenessMessage } from \"./OutgoingMessages/QueryAwarenessMessage.ts\";\nimport type { SyncStepOneMessage } from \"./OutgoingMessages/SyncStepOneMessage.ts\";\nimport type { SyncStepTwoMessage } from \"./OutgoingMessages/SyncStepTwoMessage.ts\";\nimport type { UpdateMessage } from \"./OutgoingMessages/UpdateMessage.ts\";\n\nexport enum MessageType {\n\tSync = 0,\n\tAwareness = 1,\n\tAuth = 2,\n\tQueryAwareness = 3,\n\tStateless = 5,\n\tCLOSE = 7,\n\tSyncStatus = 8,\n\tPing = 9,\n\tPong = 10,\n}\n\nexport enum WebSocketStatus {\n\tConnecting = \"connecting\",\n\tConnected = \"connected\",\n\tDisconnected = \"disconnected\",\n}\n\nexport type AuthorizedScope = \"read-write\" | \"readonly\";\n\nexport interface OutgoingMessageInterface {\n\tencoder: Encoder;\n\ttype?: MessageType;\n}\n\nexport interface OutgoingMessageArguments {\n\tdocumentName: string;\n\ttoken: string;\n\tdocument: Y.Doc;\n\tawareness: Awareness;\n\tclients: number[];\n\tstates: Map<number, { [key: string]: any }>;\n\tupdate: any;\n\tpayload: string;\n\tencoder: Encoder;\n}\n\nexport interface Constructable<T> {\n\tnew (...args: any): T;\n}\n\nexport type ConstructableOutgoingMessage =\n\t| Constructable<AuthenticationMessage>\n\t| Constructable<AwarenessMessage>\n\t| Constructable<QueryAwarenessMessage>\n\t| Constructable<SyncStepOneMessage>\n\t| Constructable<SyncStepTwoMessage>\n\t| Constructable<UpdateMessage>;\n\nexport type onAuthenticationFailedParameters = {\n\treason: string;\n};\n\nexport type onAuthenticatedParameters = {\n\tscope: AuthorizedScope;\n};\n\nexport type onOpenParameters = {\n\tevent: Event;\n};\n\nexport type onMessageParameters = {\n\tevent: MessageEvent;\n\tmessage: IncomingMessage;\n};\n\nexport type onOutgoingMessageParameters = {\n\tmessage: OutgoingMessage;\n};\n\nexport type onStatusParameters = {\n\tstatus: WebSocketStatus;\n};\n\nexport type onSyncedParameters = {\n\tstate: boolean;\n};\n\nexport type onUnsyncedChangesParameters = {\n\tnumber: number;\n};\n\nexport type onDisconnectParameters = {\n\tevent: CloseEvent;\n};\n\nexport type onCloseParameters = {\n\tevent: CloseEvent;\n};\n\nexport type onAwarenessUpdateParameters = {\n\tstates: StatesArray;\n};\n\nexport type onAwarenessChangeParameters = {\n\tstates: StatesArray;\n};\n\nexport type onStatelessParameters = {\n\tpayload: string;\n};\n\nexport type StatesArray = { clientId: number; [key: string | number]: any }[];\n","import type { Encoder } from \"lib0/encoding\";\nimport { createEncoder, toUint8Array } from \"lib0/encoding\";\nimport type {\n\tMessageType,\n\tOutgoingMessageArguments,\n\tOutgoingMessageInterface,\n} from \"./types.ts\";\n\nexport class OutgoingMessage implements OutgoingMessageInterface {\n\tencoder: Encoder;\n\n\ttype?: MessageType;\n\n\tconstructor() {\n\t\tthis.encoder = createEncoder();\n\t}\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\treturn args.encoder;\n\t}\n\n\ttoUint8Array() {\n\t\treturn toUint8Array(this.encoder);\n\t}\n}\n","import * as encoding from \"lib0/encoding\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class CloseMessage extends OutgoingMessage {\n\ttype = MessageType.CLOSE;\n\n\tdescription = \"Ask the server to close the connection\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tencoding.writeVarString(this.encoder, args.documentName!);\n\t\tencoding.writeVarUint(this.encoder, this.type);\n\n\t\treturn this.encoder;\n\t}\n}\n","import { WsReadyStates } from \"@hocuspocus/common\";\nimport { retry } from \"@lifeomic/attempt\";\nimport { createDecoder, readVarString, readVarUint } from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport * as time from \"lib0/time\";\nimport EventEmitter from \"./EventEmitter.ts\";\nimport type { HocuspocusProvider } from \"./HocuspocusProvider.ts\";\nimport { IncomingMessage } from \"./IncomingMessage.ts\";\nimport { CloseMessage } from \"./OutgoingMessages/CloseMessage.ts\";\nimport {\n\tMessageType,\n\ttype onAwarenessChangeParameters,\n\ttype onAwarenessUpdateParameters,\n\ttype onCloseParameters,\n\ttype onDisconnectParameters,\n\ttype onMessageParameters,\n\ttype onOpenParameters,\n\ttype onOutgoingMessageParameters,\n\ttype onStatusParameters,\n\tWebSocketStatus,\n} from \"./types.ts\";\n\nexport type HocuspocusWebSocket = WebSocket & { identifier: string };\nexport type HocusPocusWebSocket = HocuspocusWebSocket;\n\nexport type HocuspocusProviderWebsocketConfiguration = Required<\n\tPick<CompleteHocuspocusProviderWebsocketConfiguration, \"url\">\n> &\n\tPartial<CompleteHocuspocusProviderWebsocketConfiguration>;\n\nexport interface CompleteHocuspocusProviderWebsocketConfiguration {\n\t/**\n\t * Whether to connect automatically when creating the provider instance. Default=true\n\t */\n\tautoConnect: boolean;\n\n\t/**\n\t * URL of your @hocuspocus/server instance\n\t */\n\turl: string;\n\n\t/**\n\t * By default, trailing slashes are removed from the URL. Set this to true\n\t * to preserve trailing slashes if your server configuration requires them.\n\t */\n\tpreserveTrailingSlash: boolean;\n\n\t/**\n\t * An optional WebSocket polyfill, for example for Node.js\n\t */\n\tWebSocketPolyfill: any;\n\n\t/**\n\t * Disconnect when no message is received for the defined amount of milliseconds.\n\t */\n\tmessageReconnectTimeout: number;\n\t/**\n\t * The delay between each attempt in milliseconds. You can provide a factor to have the delay grow exponentially.\n\t */\n\tdelay: number;\n\t/**\n\t * The initialDelay is the amount of time to wait before making the first attempt. This option should typically be 0 since you typically want the first attempt to happen immediately.\n\t */\n\tinitialDelay: number;\n\t/**\n\t * The factor option is used to grow the delay exponentially.\n\t */\n\tfactor: number;\n\t/**\n\t * The maximum number of attempts or 0 if there is no limit on number of attempts.\n\t */\n\tmaxAttempts: number;\n\t/**\n\t * minDelay is used to set a lower bound of delay when jitter is enabled. This property has no effect if jitter is disabled.\n\t */\n\tminDelay: number;\n\t/**\n\t * The maxDelay option is used to set an upper bound for the delay when factor is enabled. A value of 0 can be provided if there should be no upper bound when calculating delay.\n\t */\n\tmaxDelay: number;\n\t/**\n\t * If jitter is true then the calculated delay will be a random integer value between minDelay and the calculated delay for the current iteration.\n\t */\n\tjitter: boolean;\n\t/**\n\t * A timeout in milliseconds. If timeout is non-zero then a timer is set using setTimeout. If the timeout is triggered then future attempts will be aborted.\n\t */\n\ttimeout: number;\n\thandleTimeout: (() => Promise<unknown>) | null;\n\tonOpen: (data: onOpenParameters) => void;\n\tonConnect: () => void;\n\tonMessage: (data: onMessageParameters) => void;\n\tonOutgoingMessage: (data: onOutgoingMessageParameters) => void;\n\tonStatus: (data: onStatusParameters) => void;\n\tonDisconnect: (data: onDisconnectParameters) => void;\n\tonClose: (data: onCloseParameters) => void;\n\tonDestroy: () => void;\n\tonAwarenessUpdate: (data: onAwarenessUpdateParameters) => void;\n\tonAwarenessChange: (data: onAwarenessChangeParameters) => void;\n\n\t/**\n\t * Map of attached providers keyed by documentName.\n\t */\n\tproviderMap: Map<string, HocuspocusProvider>;\n}\n\nexport class HocuspocusProviderWebsocket extends EventEmitter {\n\tprivate static readonly DEDUPLICATABLE_TYPES = new Set([\n\t\tMessageType.Awareness,\n\t\tMessageType.QueryAwareness,\n\t]);\n\n\tprivate messageQueue: any[] = [];\n\n\tpublic configuration: CompleteHocuspocusProviderWebsocketConfiguration = {\n\t\turl: \"\",\n\t\tautoConnect: true,\n\t\tpreserveTrailingSlash: false,\n\t\t// @ts-expect-error\n\t\tdocument: undefined,\n\t\tWebSocketPolyfill: undefined,\n\t\t// TODO: this should depend on awareness.outdatedTime\n\t\tmessageReconnectTimeout: 30000,\n\t\t// 1 second\n\t\tdelay: 1000,\n\t\t// instant\n\t\tinitialDelay: 0,\n\t\t// double the delay each time\n\t\tfactor: 2,\n\t\t// unlimited retries\n\t\tmaxAttempts: 0,\n\t\t// wait at least 1 second\n\t\tminDelay: 1000,\n\t\t// at least every 30 seconds\n\t\tmaxDelay: 30000,\n\t\t// randomize\n\t\tjitter: true,\n\t\t// retry forever\n\t\ttimeout: 0,\n\t\tonOpen: () => null,\n\t\tonConnect: () => null,\n\t\tonMessage: () => null,\n\t\tonOutgoingMessage: () => null,\n\t\tonStatus: () => null,\n\t\tonDisconnect: () => null,\n\t\tonClose: () => null,\n\t\tonDestroy: () => null,\n\t\tonAwarenessUpdate: () => null,\n\t\tonAwarenessChange: () => null,\n\t\thandleTimeout: null,\n\t\tproviderMap: new Map(),\n\t};\n\n\twebSocket: HocusPocusWebSocket | null = null;\n\n\twebSocketHandlers: { [key: string]: any } = {};\n\n\tshouldConnect = true;\n\n\tstatus = WebSocketStatus.Disconnected;\n\n\tlastMessageReceived = 0;\n\n\tidentifier = 0;\n\n\tintervals: any = {\n\t\tconnectionChecker: null,\n\t};\n\n\tconnectionAttempt: {\n\t\tresolve: (value?: any) => void;\n\t\treject: (reason?: any) => void;\n\t} | null = null;\n\n\tconstructor(configuration: HocuspocusProviderWebsocketConfiguration) {\n\t\tsuper();\n\t\tthis.setConfiguration(configuration);\n\n\t\tthis.configuration.WebSocketPolyfill = configuration.WebSocketPolyfill\n\t\t\t? configuration.WebSocketPolyfill\n\t\t\t: WebSocket;\n\n\t\tthis.on(\"open\", this.configuration.onOpen);\n\t\tthis.on(\"open\", this.onOpen.bind(this));\n\t\tthis.on(\"connect\", this.configuration.onConnect);\n\t\tthis.on(\"message\", this.configuration.onMessage);\n\t\tthis.on(\"outgoingMessage\", this.configuration.onOutgoingMessage);\n\t\tthis.on(\"status\", this.configuration.onStatus);\n\t\tthis.on(\"disconnect\", this.configuration.onDisconnect);\n\t\tthis.on(\"close\", this.configuration.onClose);\n\t\tthis.on(\"destroy\", this.configuration.onDestroy);\n\t\tthis.on(\"awarenessUpdate\", this.configuration.onAwarenessUpdate);\n\t\tthis.on(\"awarenessChange\", this.configuration.onAwarenessChange);\n\n\t\tthis.on(\"close\", this.onClose.bind(this));\n\t\tthis.on(\"message\", this.onMessage.bind(this));\n\n\t\tthis.intervals.connectionChecker = setInterval(\n\t\t\tthis.checkConnection.bind(this),\n\t\t\tthis.configuration.messageReconnectTimeout / 10,\n\t\t);\n\n\t\tif (this.shouldConnect) {\n\t\t\tthis.connect();\n\t\t}\n\t}\n\n\treceivedOnOpenPayload?: Event | undefined = undefined;\n\n\tasync onOpen(event: Event) {\n\t\tthis.status = WebSocketStatus.Connected;\n\t\tthis.emit(\"status\", { status: WebSocketStatus.Connected });\n\n\t\tthis.cancelWebsocketRetry = undefined;\n\t\tthis.receivedOnOpenPayload = event;\n\t}\n\n\tattach(provider: HocuspocusProvider) {\n\t\tconst key = provider.effectiveName;\n\t\tconst existing = this.configuration.providerMap.get(key);\n\n\t\tif (existing && existing !== provider) {\n\t\t\t// Allow replacing a provider that hasn't authenticated (e.g., after auth failure retry)\n\t\t\tif (existing.isAuthenticated) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot attach two providers with the same effective name \"${key}\". ` +\n\t\t\t\t\t\t\"Use sessionAwareness: true to multiplex providers with the same document name.\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis.configuration.providerMap.set(key, provider);\n\n\t\tif (this.status === WebSocketStatus.Disconnected && this.shouldConnect) {\n\t\t\tthis.connect();\n\t\t}\n\n\t\tif (\n\t\t\tthis.receivedOnOpenPayload &&\n\t\t\tthis.status === WebSocketStatus.Connected\n\t\t) {\n\t\t\tprovider.onOpen(this.receivedOnOpenPayload);\n\t\t}\n\t}\n\n\tdetach(provider: HocuspocusProvider) {\n\t\tconst key = provider.effectiveName;\n\t\tif (this.configuration.providerMap.has(key)) {\n\t\t\tprovider.send(CloseMessage, {\n\t\t\t\tdocumentName: key,\n\t\t\t});\n\t\t\tthis.configuration.providerMap.delete(key);\n\t\t}\n\t}\n\n\tpublic setConfiguration(\n\t\tconfiguration: Partial<HocuspocusProviderWebsocketConfiguration> = {},\n\t): void {\n\t\tthis.configuration = { ...this.configuration, ...configuration };\n\n\t\tif (!this.configuration.autoConnect) {\n\t\t\tthis.shouldConnect = false;\n\t\t}\n\t}\n\n\tcancelWebsocketRetry?: () => void;\n\n\tasync connect() {\n\t\tif (this.status === WebSocketStatus.Connected) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Always cancel any previously initiated connection retryer instances\n\t\tif (this.cancelWebsocketRetry) {\n\t\t\tthis.cancelWebsocketRetry();\n\t\t\tthis.cancelWebsocketRetry = undefined;\n\t\t}\n\n\t\tthis.receivedOnOpenPayload = undefined;\n\t\tthis.shouldConnect = true;\n\n\t\tconst abortableRetry = () => {\n\t\t\tlet cancelAttempt = false;\n\n\t\t\tconst retryPromise = retry(this.createWebSocketConnection.bind(this), {\n\t\t\t\tdelay: this.configuration.delay,\n\t\t\t\tinitialDelay: this.configuration.initialDelay,\n\t\t\t\tfactor: this.configuration.factor,\n\t\t\t\tmaxAttempts: this.configuration.maxAttempts,\n\t\t\t\tminDelay: this.configuration.minDelay,\n\t\t\t\tmaxDelay: this.configuration.maxDelay,\n\t\t\t\tjitter: this.configuration.jitter,\n\t\t\t\ttimeout: this.configuration.timeout,\n\t\t\t\thandleTimeout: this.configuration.handleTimeout,\n\t\t\t\tbeforeAttempt: (context) => {\n\t\t\t\t\tif (!this.shouldConnect || cancelAttempt) {\n\t\t\t\t\t\tcontext.abort();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t}).catch((error: any) => {\n\t\t\t\t// If we aborted the connection attempt then don’t throw an error\n\t\t\t\t// ref: https://github.com/lifeomic/attempt/blob/master/src/index.ts#L136\n\t\t\t\tif (error && error.code !== \"ATTEMPT_ABORTED\") {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tretryPromise,\n\t\t\t\tcancelFunc: () => {\n\t\t\t\t\tcancelAttempt = true;\n\t\t\t\t},\n\t\t\t};\n\t\t};\n\n\t\tconst { retryPromise, cancelFunc } = abortableRetry();\n\t\tthis.cancelWebsocketRetry = cancelFunc;\n\n\t\treturn retryPromise;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tattachWebSocketListeners(ws: HocusPocusWebSocket, reject: Function) {\n\t\tconst { identifier } = ws;\n\t\tconst onMessageHandler = (payload: any) => this.emit(\"message\", payload);\n\t\tconst onCloseHandler = (payload: any) =>\n\t\t\tthis.emit(\"close\", { event: payload });\n\t\tconst onOpenHandler = (payload: any) => this.emit(\"open\", payload);\n\t\tconst onErrorHandler = (err: any) => {\n\t\t\treject(err);\n\t\t};\n\n\t\tthis.webSocketHandlers[identifier] = {\n\t\t\tmessage: onMessageHandler,\n\t\t\tclose: onCloseHandler,\n\t\t\topen: onOpenHandler,\n\t\t\terror: onErrorHandler,\n\t\t};\n\n\t\tconst handlers = this.webSocketHandlers[ws.identifier];\n\n\t\tObject.keys(handlers).forEach((name) => {\n\t\t\tws.addEventListener(name, handlers[name]);\n\t\t});\n\t}\n\n\tcleanupWebSocket() {\n\t\tif (!this.webSocket) {\n\t\t\treturn;\n\t\t}\n\t\tconst { identifier } = this.webSocket;\n\t\tconst handlers = this.webSocketHandlers[identifier];\n\n\t\tObject.keys(handlers).forEach((name) => {\n\t\t\tthis.webSocket?.removeEventListener(name, handlers[name]);\n\t\t\tdelete this.webSocketHandlers[identifier];\n\t\t});\n\t\tthis.webSocket.close();\n\t\tthis.webSocket = null;\n\t}\n\n\tcreateWebSocketConnection() {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tif (this.webSocket) {\n\t\t\t\tthis.messageQueue = [];\n\t\t\t\tthis.cleanupWebSocket();\n\t\t\t}\n\t\t\tthis.lastMessageReceived = 0;\n\t\t\tthis.identifier += 1;\n\n\t\t\t// Init the WebSocket connection\n\t\t\tconst ws = new this.configuration.WebSocketPolyfill(this.url);\n\t\t\tws.binaryType = \"arraybuffer\";\n\t\t\tws.identifier = this.identifier;\n\n\t\t\tthis.attachWebSocketListeners(ws, reject);\n\n\t\t\tthis.webSocket = ws;\n\n\t\t\t// Reset the status\n\t\t\tthis.status = WebSocketStatus.Connecting;\n\t\t\tthis.emit(\"status\", { status: WebSocketStatus.Connecting });\n\n\t\t\t// Store resolve/reject for later use\n\t\t\tthis.connectionAttempt = {\n\t\t\t\tresolve,\n\t\t\t\treject,\n\t\t\t};\n\t\t});\n\t}\n\n\tonMessage(event: MessageEvent) {\n\t\tthis.resolveConnectionAttempt();\n\n\t\tthis.lastMessageReceived = time.getUnixTime();\n\n\t\tconst data = new Uint8Array(event.data as ArrayBuffer);\n\n\t\t// Check for connection-level Ping message (no document name prefix)\n\t\t// Ping messages are sent as just the message type byte (length 1)\n\t\t// We check length to avoid confusing with regular messages that happen to have\n\t\t// a document name length of 9 as the first byte\n\t\tif (data.length === 1 && data[0] === MessageType.Ping) {\n\t\t\tthis.sendPong();\n\t\t\treturn;\n\t\t}\n\n\t\tconst message = new IncomingMessage(data);\n\t\tconst rawKey = message.peekVarString();\n\n\t\tconst provider = this.configuration.providerMap.get(rawKey);\n\t\tprovider?.onMessage(event);\n\t}\n\n\t/**\n\t * Send application-level Pong response to server Ping\n\t */\n\tprivate sendPong() {\n\t\tconst encoder = encoding.createEncoder();\n\t\tencoding.writeVarUint(encoder, MessageType.Pong);\n\t\tthis.send(encoding.toUint8Array(encoder));\n\t}\n\n\tresolveConnectionAttempt() {\n\t\tif (this.connectionAttempt) {\n\t\t\tthis.connectionAttempt.resolve();\n\t\t\tthis.connectionAttempt = null;\n\n\t\t\tthis.status = WebSocketStatus.Connected;\n\t\t\tthis.emit(\"status\", { status: WebSocketStatus.Connected });\n\t\t\tthis.emit(\"connect\");\n\t\t\tthis.messageQueue.forEach((message) => this.send(message));\n\t\t\tthis.messageQueue = [];\n\t\t}\n\t}\n\n\tstopConnectionAttempt() {\n\t\tthis.connectionAttempt = null;\n\t}\n\n\trejectConnectionAttempt() {\n\t\tthis.connectionAttempt?.reject();\n\t\tthis.connectionAttempt = null;\n\t}\n\n\tcloseTries = 0;\n\n\tcheckConnection() {\n\t\t// Don’t check the connection when it’s not even established\n\t\tif (this.status !== WebSocketStatus.Connected) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Don’t close the connection while waiting for the first message\n\t\tif (!this.lastMessageReceived) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Don’t close the connection when a message was received recently\n\t\tif (\n\t\t\tthis.configuration.messageReconnectTimeout >=\n\t\t\ttime.getUnixTime() - this.lastMessageReceived\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// No message received in a long time, not even your own\n\t\t// Awareness updates, which are updated every 15 seconds\n\t\t// if awareness is enabled.\n\t\tthis.closeTries += 1;\n\t\t// https://bugs.webkit.org/show_bug.cgi?id=247943\n\t\tif (this.closeTries > 2) {\n\t\t\tthis.onClose({\n\t\t\t\tevent: {\n\t\t\t\t\tcode: 4408,\n\t\t\t\t\treason: \"forced\",\n\t\t\t\t},\n\t\t\t});\n\t\t\tthis.closeTries = 0;\n\t\t} else {\n\t\t\tthis.webSocket?.close();\n\t\t\tthis.messageQueue = [];\n\t\t}\n\t}\n\n\tget serverUrl() {\n\t\tif (this.configuration.preserveTrailingSlash) {\n\t\t\treturn this.configuration.url;\n\t\t}\n\n\t\t// By default, ensure that the URL never ends with /\n\t\tlet url = this.configuration.url;\n\t\twhile (url[url.length - 1] === \"/\") {\n\t\t\turl = url.slice(0, url.length - 1);\n\t\t}\n\n\t\treturn url;\n\t}\n\n\tget url() {\n\t\treturn this.serverUrl;\n\t}\n\n\tdisconnect() {\n\t\tthis.shouldConnect = false;\n\n\t\tif (this.webSocket === null) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.webSocket.close();\n\t\t\tthis.messageQueue = [];\n\t\t} catch (e) {\n\t\t\tconsole.error(e);\n\t\t}\n\t}\n\n\tprivate parseQueuedMessage(\n\t\tmessage: Uint8Array,\n\t): { documentName: string; messageType: number } | null {\n\t\ttry {\n\t\t\tconst decoder = createDecoder(message);\n\t\t\tconst documentName = readVarString(decoder);\n\t\t\tconst messageType = readVarUint(decoder);\n\t\t\treturn { documentName, messageType };\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate addToQueue(message: any) {\n\t\tif (message instanceof Uint8Array) {\n\t\t\tconst parsed = this.parseQueuedMessage(message);\n\t\t\tif (\n\t\t\t\tparsed &&\n\t\t\t\tHocuspocusProviderWebsocket.DEDUPLICATABLE_TYPES.has(parsed.messageType)\n\t\t\t) {\n\t\t\t\tthis.messageQueue = this.messageQueue.filter((queued) => {\n\t\t\t\t\tif (!(queued instanceof Uint8Array)) return true;\n\t\t\t\t\tconst queuedParsed = this.parseQueuedMessage(queued);\n\t\t\t\t\tif (!queuedParsed) return true;\n\t\t\t\t\treturn !(\n\t\t\t\t\t\tqueuedParsed.documentName === parsed.documentName &&\n\t\t\t\t\t\tqueuedParsed.messageType === parsed.messageType\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthis.messageQueue.push(message);\n\t}\n\n\tsend(message: any) {\n\t\tif (this.webSocket?.readyState === WsReadyStates.Open) {\n\t\t\tthis.webSocket.send(message);\n\t\t} else {\n\t\t\tthis.addToQueue(message);\n\t\t}\n\t}\n\n\tonClose({ event }: onCloseParameters) {\n\t\tthis.closeTries = 0;\n\t\tthis.cleanupWebSocket();\n\n\t\tif (this.connectionAttempt) {\n\t\t\t// That connection attempt failed.\n\t\t\tthis.rejectConnectionAttempt();\n\t\t}\n\n\t\t// Let’s update the connection status.\n\t\tthis.status = WebSocketStatus.Disconnected;\n\t\tthis.emit(\"status\", { status: WebSocketStatus.Disconnected });\n\t\tthis.emit(\"disconnect\", { event });\n\n\t\t// trigger connect if no retry is running and we want to have a connection\n\t\tif (!this.cancelWebsocketRetry && this.shouldConnect) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.connect();\n\t\t\t}, this.configuration.delay);\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tthis.emit(\"destroy\");\n\n\t\tclearInterval(this.intervals.connectionChecker);\n\n\t\t// If there is still a connection attempt outstanding then we should stop\n\t\t// it before calling disconnect, otherwise it will be rejected in the onClose\n\t\t// handler and trigger a retry\n\t\tthis.stopConnectionAttempt();\n\n\t\tthis.disconnect();\n\n\t\tthis.removeAllListeners();\n\n\t\tthis.cleanupWebSocket();\n\t}\n}\n","import { type CloseEvent, readAuthMessage } from \"@hocuspocus/common\";\nimport { readVarInt, readVarString } from \"lib0/decoding\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport { messageYjsSyncStep2, readSyncMessage } from \"y-protocols/sync\";\nimport type { HocuspocusProvider } from \"./HocuspocusProvider.ts\";\nimport type { IncomingMessage } from \"./IncomingMessage.ts\";\nimport { OutgoingMessage } from \"./OutgoingMessage.ts\";\nimport { MessageType } from \"./types.ts\";\n\nexport class MessageReceiver {\n\tmessage: IncomingMessage;\n\n\tconstructor(message: IncomingMessage) {\n\t\tthis.message = message;\n\t}\n\n\tpublic apply(provider: HocuspocusProvider, emitSynced: boolean) {\n\t\tconst { message } = this;\n\t\tconst type = message.readVarUint();\n\n\t\tconst emptyMessageLength = message.length();\n\n\t\tswitch (type) {\n\t\t\tcase MessageType.Sync:\n\t\t\t\tthis.applySyncMessage(provider, emitSynced);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.Awareness:\n\t\t\t\tthis.applyAwarenessMessage(provider);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.Auth:\n\t\t\t\tthis.applyAuthMessage(provider);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.QueryAwareness:\n\t\t\t\tthis.applyQueryAwarenessMessage(provider);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.Stateless:\n\t\t\t\tprovider.receiveStateless(readVarString(message.decoder));\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.SyncStatus:\n\t\t\t\tthis.applySyncStatusMessage(\n\t\t\t\t\tprovider,\n\t\t\t\t\treadVarInt(message.decoder) === 1,\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.CLOSE: {\n\t\t\t\t// eslint-disable-next-line no-case-declarations\n\t\t\t\tconst event: CloseEvent = {\n\t\t\t\t\tcode: 1000,\n\t\t\t\t\treason: readVarString(message.decoder),\n\t\t\t\t};\n\t\t\t\tprovider.onClose();\n\t\t\t\tprovider.configuration.onClose({ event });\n\t\t\t\tprovider.forwardClose({ event });\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tconsole.error(`Can’t apply message of unknown type: ${type}`);\n\t\t}\n\n\t\t// Reply\n\t\tif (message.length() > emptyMessageLength + 1) {\n\t\t\t// length of documentName (considered in emptyMessageLength plus length of yjs sync type, set in applySyncMessage)\n\t\t\t// @ts-expect-error\n\t\t\tprovider.send(OutgoingMessage, { encoder: message.encoder });\n\t\t}\n\t}\n\n\tprivate applySyncMessage(provider: HocuspocusProvider, emitSynced: boolean) {\n\t\tconst { message } = this;\n\n\t\tmessage.writeVarUint(MessageType.Sync);\n\n\t\t// Apply update\n\t\tconst syncMessageType = readSyncMessage(\n\t\t\tmessage.decoder,\n\t\t\tmessage.encoder,\n\t\t\tprovider.document,\n\t\t\tprovider,\n\t\t);\n\n\t\t// Synced once we receive Step2\n\t\tif (emitSynced && syncMessageType === messageYjsSyncStep2) {\n\t\t\tprovider.synced = true;\n\t\t}\n\t}\n\n\tapplySyncStatusMessage(provider: HocuspocusProvider, applied: boolean) {\n\t\tif (applied) {\n\t\t\tprovider.decrementUnsyncedChanges();\n\t\t}\n\t}\n\n\tprivate applyAwarenessMessage(provider: HocuspocusProvider) {\n\t\tif (!provider.awareness) return;\n\n\t\tconst { message } = this;\n\n\t\tawarenessProtocol.applyAwarenessUpdate(\n\t\t\tprovider.awareness,\n\t\t\tmessage.readVarUint8Array(),\n\t\t\tprovider,\n\t\t);\n\t}\n\n\tprivate applyAuthMessage(provider: HocuspocusProvider) {\n\t\tconst { message } = this;\n\n\t\treadAuthMessage(\n\t\t\tmessage.decoder,\n\t\t\tprovider.sendToken.bind(provider),\n\t\t\tprovider.permissionDeniedHandler.bind(provider),\n\t\t\tprovider.authenticatedHandler.bind(provider),\n\t\t);\n\t}\n\n\tprivate applyQueryAwarenessMessage(provider: HocuspocusProvider) {\n\t\tif (!provider.awareness) return;\n\n\t\tconst { message } = this;\n\n\t\tmessage.writeVarUint(MessageType.Awareness);\n\t\tmessage.writeVarUint8Array(\n\t\t\tawarenessProtocol.encodeAwarenessUpdate(\n\t\t\t\tprovider.awareness,\n\t\t\t\tArray.from(provider.awareness.getStates().keys()),\n\t\t\t),\n\t\t);\n\t}\n}\n","import type { Encoder } from \"lib0/encoding\";\nimport { toUint8Array } from \"lib0/encoding\";\nimport type { ConstructableOutgoingMessage } from \"./types.ts\";\n\nexport class MessageSender {\n\tencoder: Encoder;\n\n\tmessage: any;\n\n\tconstructor(Message: ConstructableOutgoingMessage, args: any = {}) {\n\t\tthis.message = new Message();\n\t\tthis.encoder = this.message.get(args);\n\t}\n\n\tcreate() {\n\t\treturn toUint8Array(this.encoder);\n\t}\n\n\tsend(webSocket: any) {\n\t\twebSocket?.send(this.create());\n\t}\n}\n","export const version: string =\n\t// @ts-expect-error - __HOCUSPOCUS_VERSION__ is replaced at build time by rolldown\n\ttypeof __HOCUSPOCUS_VERSION__ !== \"undefined\"\n\t\t? // @ts-expect-error - __HOCUSPOCUS_VERSION__ is replaced at build time by rolldown\n\t\t\t__HOCUSPOCUS_VERSION__\n\t\t: \"unknown\";\n","import { writeVarString, writeVarUint } from \"lib0/encoding\";\nimport { writeAuthentication } from \"@hocuspocus/common\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\nimport { version } from \"../version.ts\";\n\nexport class AuthenticationMessage extends OutgoingMessage {\n\ttype = MessageType.Auth;\n\n\tdescription = \"Authentication\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tif (typeof args.token === \"undefined\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"The authentication message requires `token` as an argument.\",\n\t\t\t);\n\t\t}\n\n\t\twriteVarString(this.encoder, args.documentName!);\n\t\twriteVarUint(this.encoder, this.type);\n\t\twriteAuthentication(this.encoder, args.token);\n\t\twriteVarString(this.encoder, version);\n\n\t\treturn this.encoder;\n\t}\n}\n","import * as encoding from \"lib0/encoding\";\nimport { encodeAwarenessUpdate } from \"y-protocols/awareness\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class AwarenessMessage extends OutgoingMessage {\n\ttype = MessageType.Awareness;\n\n\tdescription = \"Awareness states update\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tif (typeof args.awareness === \"undefined\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"The awareness message requires awareness as an argument\",\n\t\t\t);\n\t\t}\n\n\t\tif (typeof args.clients === \"undefined\") {\n\t\t\tthrow new Error(\"The awareness message requires clients as an argument\");\n\t\t}\n\n\t\tencoding.writeVarString(this.encoder, args.documentName!);\n\t\tencoding.writeVarUint(this.encoder, this.type);\n\n\t\tlet awarenessUpdate;\n\t\tif (args.states === undefined) {\n\t\t\tawarenessUpdate = encodeAwarenessUpdate(args.awareness, args.clients);\n\t\t} else {\n\t\t\tawarenessUpdate = encodeAwarenessUpdate(\n\t\t\t\targs.awareness,\n\t\t\t\targs.clients,\n\t\t\t\targs.states,\n\t\t\t);\n\t\t}\n\n\t\tencoding.writeVarUint8Array(this.encoder, awarenessUpdate);\n\n\t\treturn this.encoder;\n\t}\n}\n","import { writeVarString, writeVarUint } from \"lib0/encoding\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class StatelessMessage extends OutgoingMessage {\n\ttype = MessageType.Stateless;\n\n\tdescription = \"A stateless message\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\twriteVarString(this.encoder, args.documentName!);\n\t\twriteVarUint(this.encoder, this.type);\n\t\twriteVarString(this.encoder, args.payload ?? \"\");\n\n\t\treturn this.encoder;\n\t}\n}\n","import * as encoding from \"lib0/encoding\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class SyncStepOneMessage extends OutgoingMessage {\n\ttype = MessageType.Sync;\n\n\tdescription = \"First sync step\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tif (typeof args.document === \"undefined\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"The sync step one message requires document as an argument\",\n\t\t\t);\n\t\t}\n\n\t\tencoding.writeVarString(this.encoder, args.documentName!);\n\t\tencoding.writeVarUint(this.encoder, this.type);\n\t\tsyncProtocol.writeSyncStep1(this.encoder, args.document);\n\n\t\treturn this.encoder;\n\t}\n}\n","import { writeVarString, writeVarUint } from \"lib0/encoding\";\nimport { writeUpdate } from \"y-protocols/sync\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class UpdateMessage extends OutgoingMessage {\n\ttype = MessageType.Sync;\n\n\tdescription = \"A document update\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\twriteVarString(this.encoder, args.documentName!);\n\t\twriteVarUint(this.encoder, this.type);\n\n\t\twriteUpdate(this.encoder, args.update);\n\n\t\treturn this.encoder;\n\t}\n}\n","import {\n\tawarenessStatesToArray,\n\tmakeRoutingKey,\n\tparseRoutingKey,\n} from \"@hocuspocus/common\";\nimport { Awareness, removeAwarenessStates } from \"y-protocols/awareness\";\nimport * as Y from \"yjs\";\nimport EventEmitter from \"./EventEmitter.ts\";\nimport type { CompleteHocuspocusProviderWebsocketConfiguration } from \"./HocuspocusProviderWebsocket.ts\";\nimport { HocuspocusProviderWebsocket } from \"./HocuspocusProviderWebsocket.ts\";\nimport { IncomingMessage } from \"./IncomingMessage.ts\";\nimport { MessageReceiver } from \"./MessageReceiver.ts\";\nimport { MessageSender } from \"./MessageSender.ts\";\nimport { AuthenticationMessage } from \"./OutgoingMessages/AuthenticationMessage.ts\";\nimport { AwarenessMessage } from \"./OutgoingMessages/AwarenessMessage.ts\";\nimport { StatelessMessage } from \"./OutgoingMessages/StatelessMessage.ts\";\nimport { SyncStepOneMessage } from \"./OutgoingMessages/SyncStepOneMessage.ts\";\nimport { UpdateMessage } from \"./OutgoingMessages/UpdateMessage.ts\";\nimport type {\n\tAuthorizedScope,\n\tConstructableOutgoingMessage,\n\tonAuthenticatedParameters,\n\tonAuthenticationFailedParameters,\n\tonAwarenessChangeParameters,\n\tonAwarenessUpdateParameters,\n\tonCloseParameters,\n\tonDisconnectParameters,\n\tonMessageParameters,\n\tonOpenParameters,\n\tonOutgoingMessageParameters,\n\tonStatelessParameters,\n\tonStatusParameters,\n\tonSyncedParameters,\n\tonUnsyncedChangesParameters,\n} from \"./types.ts\";\n\nexport type HocuspocusProviderConfiguration = Required<\n\tPick<CompleteHocuspocusProviderConfiguration, \"name\">\n> &\n\tPartial<CompleteHocuspocusProviderConfiguration> &\n\t(\n\t\t| (Required<Pick<CompleteHocuspocusProviderWebsocketConfiguration, \"url\">> &\n\t\t\t\tPartial<\n\t\t\t\t\tPick<\n\t\t\t\t\t\tCompleteHocuspocusProviderWebsocketConfiguration,\n\t\t\t\t\t\t\"preserveTrailingSlash\"\n\t\t\t\t\t>\n\t\t\t\t>)\n\t\t| Required<\n\t\t\t\tPick<CompleteHocuspocusProviderConfiguration, \"websocketProvider\">\n\t\t >\n\t);\n\nexport interface CompleteHocuspocusProviderConfiguration {\n\t/**\n\t * The identifier/name of your document\n\t */\n\tname: string;\n\t/**\n\t * The actual Y.js document\n\t */\n\tdocument: Y.Doc;\n\n\t/**\n\t * An Awareness instance to keep the presence state of all clients.\n\t *\n\t * You can disable sharing awareness information by passing `null`.\n\t * Note that having no awareness information shared across all connections will break our ping checks\n\t * and thus trigger reconnects. You should always have at least one Provider with enabled awareness per\n\t * socket connection, or ensure that the Provider receives messages before running into `HocuspocusProviderWebsocket.messageReconnectTimeout`.\n\t */\n\tawareness: Awareness | null;\n\n\t/**\n\t * A token that’s sent to the backend for authentication purposes.\n\t */\n\ttoken: string | (() => string) | (() => Promise<string>) | null;\n\n\t/**\n\t * Hocuspocus websocket provider\n\t */\n\twebsocketProvider: HocuspocusProviderWebsocket;\n\n\t/**\n\t * Enable session-aware multiplexing. When true, the provider embeds a unique\n\t * sessionId in the documentName field of every message, allowing multiple\n\t * providers with the same document name on a single WebSocket connection.\n\t *\n\t * Only set this to `true` when connecting to a v4 server that does\n\t * support session awareness.\n\t *\n\t * Default: false\n\t */\n\tsessionAwareness: boolean;\n\n\t/**\n\t * Force syncing the document in the defined interval.\n\t */\n\tforceSyncInterval: false | number;\n\n\t/**\n\t * Batch outgoing document and awareness updates over a short window (in\n\t * milliseconds) instead of sending one message per change. During heavy\n\t * editing this drastically reduces the number of websocket messages: Yjs\n\t * updates collected in the window are merged with `Y.mergeUpdates` into a\n\t * single message, and awareness collapses to the latest state of each\n\t * changed client.\n\t *\n\t * The window is a fixed batch, not a resetting debounce, so the added\n\t * latency is capped at `flushDelay` even while the user keeps typing. Keep\n\t * it small (e.g. 500) to avoid delaying what other clients see.\n\t *\n\t * Set to `false` (the default) to send every change immediately.\n\t */\n\tflushDelay: false | number;\n\n\tonAuthenticated: (data: onAuthenticatedParameters) => void;\n\tonAuthenticationFailed: (data: onAuthenticationFailedParameters) => void;\n\tonOpen: (data: onOpenParameters) => void;\n\tonConnect: () => void;\n\tonStatus: (data: onStatusParameters) => void;\n\tonMessage: (data: onMessageParameters) => void;\n\tonOutgoingMessage: (data: onOutgoingMessageParameters) => void;\n\tonSynced: (data: onSyncedParameters) => void;\n\tonDisconnect: (data: onDisconnectParameters) => void;\n\tonClose: (data: onCloseParameters) => void;\n\tonDestroy: () => void;\n\tonAwarenessUpdate: (data: onAwarenessUpdateParameters) => void;\n\tonAwarenessChange: (data: onAwarenessChangeParameters) => void;\n\tonStateless: (data: onStatelessParameters) => void;\n\tonUnsyncedChanges: (data: onUnsyncedChangesParameters) => void;\n}\n\nexport class AwarenessError extends Error {\n\tcode = 1001;\n}\n\nexport class HocuspocusProvider extends EventEmitter {\n\tpublic configuration: CompleteHocuspocusProviderConfiguration = {\n\t\tname: \"\",\n\t\t// @ts-expect-error\n\t\tdocument: undefined,\n\t\t// @ts-expect-error\n\t\tawareness: undefined,\n\t\ttoken: null,\n\t\tsessionAwareness: false,\n\t\tforceSyncInterval: false,\n\t\tflushDelay: false,\n\t\tonAuthenticated: () => null,\n\t\tonAuthenticationFailed: () => null,\n\t\tonOpen: () => null,\n\t\tonConnect: () => null,\n\t\tonMessage: () => null,\n\t\tonOutgoingMessage: () => null,\n\t\tonSynced: () => null,\n\t\tonStatus: () => null,\n\t\tonDisconnect: () => null,\n\t\tonClose: () => null,\n\t\tonDestroy: () => null,\n\t\tonAwarenessUpdate: () => null,\n\t\tonAwarenessChange: () => null,\n\t\tonStateless: () => null,\n\t\tonUnsyncedChanges: () => null,\n\t};\n\n\tisSynced = false;\n\n\tunsyncedChanges = 0;\n\n\tisAuthenticated = false;\n\n\tauthorizedScope: AuthorizedScope | undefined = undefined;\n\n\t// @internal\n\tmanageSocket = false;\n\n\tprivate _isAttached = false;\n\n\t/**\n\t * Outgoing document updates buffered for the current `flushDelay` window.\n\t */\n\tprivate pendingUpdates: Uint8Array[] = [];\n\n\t/**\n\t * Awareness client ids whose latest state should be sent on the next flush.\n\t */\n\tprivate pendingAwarenessClients = new Set<number>();\n\n\tprivate flushTimeout: ReturnType<typeof setTimeout> | null = null;\n\n\t/**\n\t * Unique session identifier for this provider instance.\n\t * Used for multiplexing multiple providers with the same document name on a single WebSocket.\n\t */\n\tsessionId: string = Math.random().toString(36).slice(2);\n\n\t/**\n\t * The effective name used as the first VarString in messages.\n\t * When `sessionAwareness` is enabled, returns a composite key (documentName\\0sessionId).\n\t * Otherwise, returns the plain document name.\n\t */\n\tget effectiveName(): string {\n\t\treturn this.configuration.sessionAwareness\n\t\t\t? makeRoutingKey(this.configuration.name, this.sessionId)\n\t\t\t: this.configuration.name;\n\t}\n\n\tintervals: any = {\n\t\tforceSync: null,\n\t};\n\n\tconstructor(configuration: HocuspocusProviderConfiguration) {\n\t\tsuper();\n\t\tthis.setConfiguration(configuration);\n\n\t\tthis.configuration.document = configuration.document\n\t\t\t? configuration.document\n\t\t\t: new Y.Doc();\n\t\tthis.configuration.awareness =\n\t\t\tconfiguration.awareness !== undefined\n\t\t\t\t? configuration.awareness\n\t\t\t\t: new Awareness(this.document);\n\n\t\tthis.on(\"open\", this.configuration.onOpen);\n\t\tthis.on(\"message\", this.configuration.onMessage);\n\t\tthis.on(\"outgoingMessage\", this.configuration.onOutgoingMessage);\n\t\tthis.on(\"synced\", this.configuration.onSynced);\n\t\tthis.on(\"destroy\", this.configuration.onDestroy);\n\t\tthis.on(\"awarenessUpdate\", this.configuration.onAwarenessUpdate);\n\t\tthis.on(\"awarenessChange\", this.configuration.onAwarenessChange);\n\t\tthis.on(\"stateless\", this.configuration.onStateless);\n\t\tthis.on(\"unsyncedChanges\", this.configuration.onUnsyncedChanges);\n\n\t\tthis.on(\"authenticated\", this.configuration.onAuthenticated);\n\t\tthis.on(\"authenticationFailed\", this.configuration.onAuthenticationFailed);\n\n\t\tthis.awareness?.on(\"update\", () => {\n\t\t\tthis.emit(\"awarenessUpdate\", {\n\t\t\t\tstates: awarenessStatesToArray(this.awareness!.getStates()),\n\t\t\t});\n\t\t});\n\n\t\tthis.awareness?.on(\"change\", () => {\n\t\t\tthis.emit(\"awarenessChange\", {\n\t\t\t\tstates: awarenessStatesToArray(this.awareness!.getStates()),\n\t\t\t});\n\t\t});\n\n\t\tthis.document.on(\"update\", this.boundDocumentUpdateHandler);\n\t\tthis.awareness?.on(\"update\", this.boundAwarenessUpdateHandler);\n\n\t\tthis.registerEventListeners();\n\n\t\tif (\n\t\t\tthis.configuration.forceSyncInterval &&\n\t\t\ttypeof this.configuration.forceSyncInterval === \"number\"\n\t\t) {\n\t\t\tthis.intervals.forceSync = setInterval(\n\t\t\t\tthis.forceSync.bind(this),\n\t\t\t\tthis.configuration.forceSyncInterval,\n\t\t\t);\n\t\t}\n\n\t\tif (this.manageSocket) {\n\t\t\tthis.attach();\n\t\t}\n\t}\n\n\tboundDocumentUpdateHandler = this.documentUpdateHandler.bind(this);\n\n\tboundAwarenessUpdateHandler = this.awarenessUpdateHandler.bind(this);\n\n\tboundPageHide = this.pageHide.bind(this);\n\n\tboundOnOpen = this.onOpen.bind(this);\n\n\tboundOnClose = this.onClose.bind(this);\n\n\tforwardConnect = () => this.emit(\"connect\");\n\n\tforwardStatus = (e: onStatusParameters) => this.emit(\"status\", e);\n\n\tforwardClose = (e: onCloseParameters) => this.emit(\"close\", e);\n\n\tforwardDisconnect = (e: onDisconnectParameters) => this.emit(\"disconnect\", e);\n\n\tforwardDestroy = () => this.emit(\"destroy\");\n\n\tpublic setConfiguration(\n\t\tconfiguration: Partial<HocuspocusProviderConfiguration> = {},\n\t): void {\n\t\tif (!configuration.websocketProvider) {\n\t\t\tthis.manageSocket = true;\n\t\t\tthis.configuration.websocketProvider = new HocuspocusProviderWebsocket(\n\t\t\t\tconfiguration as CompleteHocuspocusProviderWebsocketConfiguration,\n\t\t\t);\n\t\t}\n\n\t\tthis.configuration = { ...this.configuration, ...configuration };\n\t}\n\n\tget document() {\n\t\treturn this.configuration.document;\n\t}\n\n\tpublic get isAttached() {\n\t\treturn this._isAttached;\n\t}\n\n\tget awareness() {\n\t\treturn this.configuration.awareness;\n\t}\n\n\tget hasUnsyncedChanges(): boolean {\n\t\treturn this.unsyncedChanges > 0;\n\t}\n\n\tprivate resetUnsyncedChanges() {\n\t\tthis.unsyncedChanges = 1;\n\t\tthis.emit(\"unsyncedChanges\", { number: this.unsyncedChanges });\n\t}\n\n\tincrementUnsyncedChanges() {\n\t\tthis.unsyncedChanges += 1;\n\t\tthis.emit(\"unsyncedChanges\", { number: this.unsyncedChanges });\n\t}\n\n\tdecrementUnsyncedChanges() {\n\t\tif (this.unsyncedChanges > 0) {\n\t\t\tthis.unsyncedChanges -= 1;\n\t\t}\n\n\t\tif (this.unsyncedChanges === 0) {\n\t\t\tthis.synced = true;\n\t\t}\n\n\t\tthis.emit(\"unsyncedChanges\", { number: this.unsyncedChanges });\n\t}\n\n\tforceSync() {\n\t\tthis.resetUnsyncedChanges();\n\n\t\tthis.send(SyncStepOneMessage, {\n\t\t\tdocument: this.document,\n\t\t\tdocumentName: this.effectiveName,\n\t\t});\n\t}\n\n\tpageHide() {\n\t\tif (this.awareness) {\n\t\t\tremoveAwarenessStates(\n\t\t\t\tthis.awareness,\n\t\t\t\t[this.document.clientID],\n\t\t\t\t\"page hide\",\n\t\t\t);\n\t\t}\n\t}\n\n\tregisterEventListeners() {\n\t\tif (typeof window === \"undefined\" || !(\"addEventListener\" in window)) {\n\t\t\treturn;\n\t\t}\n\n\t\twindow.addEventListener(\"pagehide\", this.boundPageHide);\n\t}\n\n\tsendStateless(payload: string) {\n\t\tthis.send(StatelessMessage, {\n\t\t\tdocumentName: this.effectiveName,\n\t\t\tpayload,\n\t\t});\n\t}\n\n\tasync sendToken() {\n\t\tlet token: string | null;\n\t\ttry {\n\t\t\ttoken = await this.getToken();\n\t\t} catch (error) {\n\t\t\tthis.permissionDeniedHandler(\n\t\t\t\t`Failed to get token during sendToken(): ${error}`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.send(AuthenticationMessage, {\n\t\t\ttoken: token ?? \"\",\n\t\t\tdocumentName: this.effectiveName,\n\t\t});\n\t}\n\n\tprivate get batchingEnabled(): boolean {\n\t\treturn (\n\t\t\t!!this.configuration.flushDelay &&\n\t\t\ttypeof this.configuration.flushDelay === \"number\"\n\t\t);\n\t}\n\n\tdocumentUpdateHandler(update: Uint8Array, origin: any) {\n\t\tif (origin === this) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.batchingEnabled) {\n\t\t\tthis.incrementUnsyncedChanges();\n\t\t\tthis.send(UpdateMessage, { update, documentName: this.effectiveName });\n\t\t\treturn;\n\t\t}\n\n\t\t// Count one outstanding change per batch: the server acks once per\n\t\t// merged message, so incrementing per buffered update would never balance.\n\t\tif (this.pendingUpdates.length === 0) {\n\t\t\tthis.incrementUnsyncedChanges();\n\t\t}\n\n\t\tthis.pendingUpdates.push(update);\n\t\tthis.scheduleFlush();\n\t}\n\n\tawarenessUpdateHandler({ added, updated, removed }: any, origin: any) {\n\t\tconst changedClients = added.concat(updated).concat(removed);\n\n\t\tif (!this.batchingEnabled) {\n\t\t\tthis.send(AwarenessMessage, {\n\t\t\t\tawareness: this.awareness,\n\t\t\t\tclients: changedClients,\n\t\t\t\tdocumentName: this.effectiveName,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const client of changedClients) {\n\t\t\tthis.pendingAwarenessClients.add(client);\n\t\t}\n\n\t\tthis.scheduleFlush();\n\t}\n\n\tprivate scheduleFlush() {\n\t\t// Fixed-window batching: the first pending change starts the timer and\n\t\t// everything until it fires is flushed together, so latency stays capped\n\t\t// at `flushDelay` instead of growing while the user keeps typing.\n\t\tif (this.flushTimeout !== null) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.flushTimeout = setTimeout(() => {\n\t\t\tthis.flushTimeout = null;\n\t\t\tthis.flushPendingUpdates();\n\t\t}, this.configuration.flushDelay as number);\n\t}\n\n\t/**\n\t * Send everything buffered for the current `flushDelay` window right away.\n\t * Buffered document updates are merged into a single message and awareness\n\t * collapses to the latest state of each changed client. Safe to call when\n\t * nothing is pending.\n\t */\n\tflushPendingUpdates() {\n\t\tif (this.flushTimeout !== null) {\n\t\t\tclearTimeout(this.flushTimeout);\n\t\t\tthis.flushTimeout = null;\n\t\t}\n\n\t\tif (this.pendingUpdates.length > 0) {\n\t\t\tconst update =\n\t\t\t\tthis.pendingUpdates.length === 1\n\t\t\t\t\t? this.pendingUpdates[0]\n\t\t\t\t\t: Y.mergeUpdates(this.pendingUpdates);\n\n\t\t\tthis.pendingUpdates = [];\n\t\t\tthis.send(UpdateMessage, { update, documentName: this.effectiveName });\n\t\t}\n\n\t\tif (this.pendingAwarenessClients.size > 0) {\n\t\t\tconst clients = Array.from(this.pendingAwarenessClients);\n\n\t\t\tthis.pendingAwarenessClients.clear();\n\t\t\tthis.send(AwarenessMessage, {\n\t\t\t\tawareness: this.awareness,\n\t\t\t\tclients,\n\t\t\t\tdocumentName: this.effectiveName,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Indicates whether a first handshake with the server has been established\n\t *\n\t * Note: this does not mean all updates from the client have been persisted to the backend. For this,\n\t * use `hasUnsyncedChanges`.\n\t */\n\tget synced(): boolean {\n\t\treturn this.isSynced;\n\t}\n\n\tset synced(state) {\n\t\tif (this.isSynced === state) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.isSynced = state;\n\n\t\tif (state) {\n\t\t\tthis.emit(\"synced\", { state });\n\t\t}\n\t}\n\n\treceiveStateless(payload: string) {\n\t\tthis.emit(\"stateless\", { payload });\n\t}\n\n\t// not needed, but provides backward compatibility with e.g. lexical/yjs\n\tasync connect() {\n\t\tif (this.manageSocket) {\n\t\t\treturn this.configuration.websocketProvider.connect();\n\t\t}\n\n\t\tconsole.warn(\n\t\t\t\"HocuspocusProvider::connect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.\",\n\t\t);\n\t}\n\n\tdisconnect() {\n\t\tif (this.manageSocket) {\n\t\t\treturn this.configuration.websocketProvider.disconnect();\n\t\t}\n\n\t\tconsole.warn(\n\t\t\t\"HocuspocusProvider::disconnect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.\",\n\t\t);\n\t}\n\n\tasync onOpen(event: Event) {\n\t\tthis.isAuthenticated = false;\n\n\t\tthis.emit(\"open\", { event });\n\t\tawait this.sendToken();\n\t\tthis.startSync();\n\t}\n\n\tasync getToken() {\n\t\tif (typeof this.configuration.token === \"function\") {\n\t\t\tconst token = await this.configuration.token();\n\t\t\treturn token;\n\t\t}\n\n\t\treturn this.configuration.token;\n\t}\n\n\tstartSync() {\n\t\tthis.resetUnsyncedChanges();\n\n\t\tthis.send(SyncStepOneMessage, {\n\t\t\tdocument: this.document,\n\t\t\tdocumentName: this.effectiveName,\n\t\t});\n\n\t\tif (this.awareness && this.awareness.getLocalState() !== null) {\n\t\t\tthis.send(AwarenessMessage, {\n\t\t\t\tawareness: this.awareness,\n\t\t\t\tclients: [this.document.clientID],\n\t\t\t\tdocumentName: this.effectiveName,\n\t\t\t});\n\t\t}\n\t}\n\n\tsend(message: ConstructableOutgoingMessage, args: any) {\n\t\tif (!this._isAttached) return;\n\n\t\tconst messageSender = new MessageSender(message, args);\n\n\t\tthis.emit(\"outgoingMessage\", { message: messageSender.message });\n\t\tmessageSender.send(this.configuration.websocketProvider);\n\t}\n\n\tonMessage(event: MessageEvent) {\n\t\tconst message = new IncomingMessage(event.data);\n\n\t\tconst rawKey = message.readVarString();\n\t\t// Extract actual documentName from potentially composite routing key\n\t\tconst { documentName } = parseRoutingKey(rawKey);\n\n\t\tmessage.writeVarString(this.effectiveName);\n\n\t\tthis.emit(\"message\", { event, message: new IncomingMessage(event.data) });\n\n\t\tnew MessageReceiver(message).apply(this, true);\n\t}\n\n\tonClose() {\n\t\tthis.isAuthenticated = false;\n\t\tthis.synced = false;\n\n\t\t// Drop anything buffered for batching; the reconnect sync handshake will\n\t\t// reconcile these changes from the document via state vectors.\n\t\tif (this.flushTimeout !== null) {\n\t\t\tclearTimeout(this.flushTimeout);\n\t\t\tthis.flushTimeout = null;\n\t\t}\n\t\tthis.pendingUpdates = [];\n\t\tthis.pendingAwarenessClients.clear();\n\n\t\t// update awareness (all users except local left)\n\t\tif (this.awareness) {\n\t\t\tremoveAwarenessStates(\n\t\t\t\tthis.awareness,\n\t\t\t\tArray.from(this.awareness.getStates().keys()).filter(\n\t\t\t\t\t(client) => client !== this.document.clientID,\n\t\t\t\t),\n\t\t\t\tthis,\n\t\t\t);\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tthis.emit(\"destroy\");\n\n\t\tif (this.intervals.forceSync) {\n\t\t\tclearInterval(this.intervals.forceSync);\n\t\t}\n\n\t\tif (this.awareness) {\n\t\t\tremoveAwarenessStates(\n\t\t\t\tthis.awareness,\n\t\t\t\t[this.document.clientID],\n\t\t\t\t\"provider destroy\",\n\t\t\t);\n\t\t\tthis.awareness.off(\"update\", this.boundAwarenessUpdateHandler);\n\t\t\tthis.awareness.destroy();\n\t\t}\n\n\t\t// Send any buffered updates before the socket is torn down. The websocket\n\t\t// safely queues the message if it is no longer open.\n\t\tthis.flushPendingUpdates();\n\n\t\tthis.document.off(\"update\", this.boundDocumentUpdateHandler);\n\n\t\tthis.removeAllListeners();\n\n\t\tthis.detach();\n\n\t\tif (this.manageSocket) {\n\t\t\tthis.configuration.websocketProvider.destroy();\n\t\t}\n\n\t\tif (typeof window === \"undefined\" || !(\"removeEventListener\" in window)) {\n\t\t\treturn;\n\t\t}\n\n\t\twindow.removeEventListener(\"pagehide\", this.boundPageHide);\n\t}\n\n\tdetach() {\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"connect\",\n\t\t\tthis.configuration.onConnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\"connect\", this.forwardConnect);\n\n\t\tthis.configuration.websocketProvider.off(\"status\", this.forwardStatus);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"status\",\n\t\t\tthis.configuration.onStatus,\n\t\t);\n\n\t\tthis.configuration.websocketProvider.off(\"open\", this.boundOnOpen);\n\t\tthis.configuration.websocketProvider.off(\"close\", this.boundOnClose);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"close\",\n\t\t\tthis.configuration.onClose,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\"close\", this.forwardClose);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"disconnect\",\n\t\t\tthis.configuration.onDisconnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"disconnect\",\n\t\t\tthis.forwardDisconnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"destroy\",\n\t\t\tthis.configuration.onDestroy,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\"destroy\", this.forwardDestroy);\n\n\t\tthis.configuration.websocketProvider.detach(this);\n\n\t\tthis._isAttached = false;\n\t}\n\n\tattach() {\n\t\tif (this._isAttached) return;\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"connect\",\n\t\t\tthis.configuration.onConnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"connect\", this.forwardConnect);\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"status\",\n\t\t\tthis.configuration.onStatus,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"status\", this.forwardStatus);\n\n\t\tthis.configuration.websocketProvider.on(\"open\", this.boundOnOpen);\n\n\t\tthis.configuration.websocketProvider.on(\"close\", this.boundOnClose);\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"close\",\n\t\t\tthis.configuration.onClose,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"close\", this.forwardClose);\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"disconnect\",\n\t\t\tthis.configuration.onDisconnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"disconnect\",\n\t\t\tthis.forwardDisconnect,\n\t\t);\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"destroy\",\n\t\t\tthis.configuration.onDestroy,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"destroy\", this.forwardDestroy);\n\n\t\tthis.configuration.websocketProvider.attach(this);\n\n\t\tthis._isAttached = true;\n\t}\n\n\tpermissionDeniedHandler(reason: string) {\n\t\tthis.emit(\"authenticationFailed\", { reason });\n\t\tthis.isAuthenticated = false;\n\t}\n\n\tauthenticatedHandler(scope: string) {\n\t\tthis.isAuthenticated = true;\n\t\tthis.authorizedScope = scope as AuthorizedScope;\n\n\t\tthis.emit(\"authenticated\", { scope });\n\t}\n\n\tsetAwarenessField(key: string, value: any) {\n\t\tif (!this.awareness) {\n\t\t\tthrow new AwarenessError(\n\t\t\t\t`Cannot set awareness field \"${key}\" to ${JSON.stringify(value)}. You have disabled Awareness for this provider by explicitly passing awareness: null in the provider configuration.`,\n\t\t\t);\n\t\t}\n\t\tthis.awareness.setLocalStateField(key, value);\n\t}\n}\n"],"mappings":"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"}
@@ -508,7 +508,7 @@ var MessageSender = class {
508
508
 
509
509
  //#endregion
510
510
  //#region packages/provider/src/version.ts
511
- const version = "4.2.0";
511
+ const version = "4.4.0";
512
512
 
513
513
  //#endregion
514
514
  //#region packages/provider/src/OutgoingMessages/AuthenticationMessage.ts
@@ -624,6 +624,7 @@ var HocuspocusProvider = class extends EventEmitter {
624
624
  token: null,
625
625
  sessionAwareness: false,
626
626
  forceSyncInterval: false,
627
+ flushDelay: false,
627
628
  onAuthenticated: () => null,
628
629
  onAuthenticationFailed: () => null,
629
630
  onOpen: () => null,
@@ -646,6 +647,9 @@ var HocuspocusProvider = class extends EventEmitter {
646
647
  this.authorizedScope = void 0;
647
648
  this.manageSocket = false;
648
649
  this._isAttached = false;
650
+ this.pendingUpdates = [];
651
+ this.pendingAwarenessClients = /* @__PURE__ */ new Set();
652
+ this.flushTimeout = null;
649
653
  this.sessionId = Math.random().toString(36).slice(2);
650
654
  this.intervals = { forceSync: null };
651
655
  this.boundDocumentUpdateHandler = this.documentUpdateHandler.bind(this);
@@ -752,21 +756,71 @@ var HocuspocusProvider = class extends EventEmitter {
752
756
  documentName: this.effectiveName
753
757
  });
754
758
  }
759
+ get batchingEnabled() {
760
+ return !!this.configuration.flushDelay && typeof this.configuration.flushDelay === "number";
761
+ }
755
762
  documentUpdateHandler(update, origin) {
756
763
  if (origin === this) return;
757
- this.incrementUnsyncedChanges();
758
- this.send(UpdateMessage, {
759
- update,
760
- documentName: this.effectiveName
761
- });
764
+ if (!this.batchingEnabled) {
765
+ this.incrementUnsyncedChanges();
766
+ this.send(UpdateMessage, {
767
+ update,
768
+ documentName: this.effectiveName
769
+ });
770
+ return;
771
+ }
772
+ if (this.pendingUpdates.length === 0) this.incrementUnsyncedChanges();
773
+ this.pendingUpdates.push(update);
774
+ this.scheduleFlush();
762
775
  }
763
776
  awarenessUpdateHandler({ added, updated, removed }, origin) {
764
777
  const changedClients = added.concat(updated).concat(removed);
765
- this.send(AwarenessMessage, {
766
- awareness: this.awareness,
767
- clients: changedClients,
768
- documentName: this.effectiveName
769
- });
778
+ if (!this.batchingEnabled) {
779
+ this.send(AwarenessMessage, {
780
+ awareness: this.awareness,
781
+ clients: changedClients,
782
+ documentName: this.effectiveName
783
+ });
784
+ return;
785
+ }
786
+ for (const client of changedClients) this.pendingAwarenessClients.add(client);
787
+ this.scheduleFlush();
788
+ }
789
+ scheduleFlush() {
790
+ if (this.flushTimeout !== null) return;
791
+ this.flushTimeout = setTimeout(() => {
792
+ this.flushTimeout = null;
793
+ this.flushPendingUpdates();
794
+ }, this.configuration.flushDelay);
795
+ }
796
+ /**
797
+ * Send everything buffered for the current `flushDelay` window right away.
798
+ * Buffered document updates are merged into a single message and awareness
799
+ * collapses to the latest state of each changed client. Safe to call when
800
+ * nothing is pending.
801
+ */
802
+ flushPendingUpdates() {
803
+ if (this.flushTimeout !== null) {
804
+ clearTimeout(this.flushTimeout);
805
+ this.flushTimeout = null;
806
+ }
807
+ if (this.pendingUpdates.length > 0) {
808
+ const update = this.pendingUpdates.length === 1 ? this.pendingUpdates[0] : Y.mergeUpdates(this.pendingUpdates);
809
+ this.pendingUpdates = [];
810
+ this.send(UpdateMessage, {
811
+ update,
812
+ documentName: this.effectiveName
813
+ });
814
+ }
815
+ if (this.pendingAwarenessClients.size > 0) {
816
+ const clients = Array.from(this.pendingAwarenessClients);
817
+ this.pendingAwarenessClients.clear();
818
+ this.send(AwarenessMessage, {
819
+ awareness: this.awareness,
820
+ clients,
821
+ documentName: this.effectiveName
822
+ });
823
+ }
770
824
  }
771
825
  /**
772
826
  * Indicates whether a first handshake with the server has been established
@@ -834,6 +888,12 @@ var HocuspocusProvider = class extends EventEmitter {
834
888
  onClose() {
835
889
  this.isAuthenticated = false;
836
890
  this.synced = false;
891
+ if (this.flushTimeout !== null) {
892
+ clearTimeout(this.flushTimeout);
893
+ this.flushTimeout = null;
894
+ }
895
+ this.pendingUpdates = [];
896
+ this.pendingAwarenessClients.clear();
837
897
  if (this.awareness) removeAwarenessStates(this.awareness, Array.from(this.awareness.getStates().keys()).filter((client) => client !== this.document.clientID), this);
838
898
  }
839
899
  destroy() {
@@ -844,6 +904,7 @@ var HocuspocusProvider = class extends EventEmitter {
844
904
  this.awareness.off("update", this.boundAwarenessUpdateHandler);
845
905
  this.awareness.destroy();
846
906
  }
907
+ this.flushPendingUpdates();
847
908
  this.document.off("update", this.boundDocumentUpdateHandler);
848
909
  this.removeAllListeners();
849
910
  this.detach();
@@ -1 +1 @@
1
- {"version":3,"file":"hocuspocus-provider.esm.js","names":[],"sources":["../src/EventEmitter.ts","../src/IncomingMessage.ts","../src/types.ts","../src/OutgoingMessage.ts","../src/OutgoingMessages/CloseMessage.ts","../src/HocuspocusProviderWebsocket.ts","../src/MessageReceiver.ts","../src/MessageSender.ts","../src/version.ts","../src/OutgoingMessages/AuthenticationMessage.ts","../src/OutgoingMessages/AwarenessMessage.ts","../src/OutgoingMessages/StatelessMessage.ts","../src/OutgoingMessages/SyncStepOneMessage.ts","../src/OutgoingMessages/UpdateMessage.ts","../src/HocuspocusProvider.ts"],"sourcesContent":["export default class EventEmitter {\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tpublic callbacks: { [key: string]: Function[] } = {};\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tpublic on(event: string, fn: Function): this {\n\t\tif (!this.callbacks[event]) {\n\t\t\tthis.callbacks[event] = [];\n\t\t}\n\n\t\tthis.callbacks[event].push(fn);\n\n\t\treturn this;\n\t}\n\n\tprotected emit(event: string, ...args: any): this {\n\t\tconst callbacks = this.callbacks[event];\n\n\t\tif (callbacks) {\n\t\t\tcallbacks.forEach((callback) => callback.apply(this, args));\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tpublic off(event: string, fn?: Function): this {\n\t\tconst callbacks = this.callbacks[event];\n\n\t\tif (callbacks) {\n\t\t\tif (fn) {\n\t\t\t\tthis.callbacks[event] = callbacks.filter((callback) => callback !== fn);\n\t\t\t} else {\n\t\t\t\tdelete this.callbacks[event];\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n\n\tremoveAllListeners(): void {\n\t\tthis.callbacks = {};\n\t}\n}\n","import type { Decoder } from \"lib0/decoding\";\nimport {\n\tcreateDecoder,\n\tpeekVarString,\n\treadVarUint,\n\treadVarUint8Array,\n\treadVarString,\n} from \"lib0/decoding\";\nimport type { Encoder } from \"lib0/encoding\";\nimport {\n\tcreateEncoder,\n\twriteVarUint,\n\twriteVarUint8Array,\n\twriteVarString,\n\tlength,\n} from \"lib0/encoding\";\nimport type { MessageType } from \"./types.ts\";\n\nexport class IncomingMessage {\n\tdata: any;\n\n\tencoder: Encoder;\n\n\tdecoder: Decoder;\n\n\tconstructor(data: any) {\n\t\tthis.data = data;\n\t\tthis.encoder = createEncoder();\n\t\tthis.decoder = createDecoder(new Uint8Array(this.data));\n\t}\n\n\tpeekVarString(): string {\n\t\treturn peekVarString(this.decoder);\n\t}\n\n\treadVarUint(): MessageType {\n\t\treturn readVarUint(this.decoder);\n\t}\n\n\treadVarString(): string {\n\t\treturn readVarString(this.decoder);\n\t}\n\n\treadVarUint8Array() {\n\t\treturn readVarUint8Array(this.decoder);\n\t}\n\n\twriteVarUint(type: MessageType) {\n\t\treturn writeVarUint(this.encoder, type);\n\t}\n\n\twriteVarString(string: string) {\n\t\treturn writeVarString(this.encoder, string);\n\t}\n\n\twriteVarUint8Array(data: Uint8Array) {\n\t\treturn writeVarUint8Array(this.encoder, data);\n\t}\n\n\tlength() {\n\t\treturn length(this.encoder);\n\t}\n}\n","import type { Encoder } from \"lib0/encoding\";\nimport type { Awareness } from \"y-protocols/awareness\";\nimport type * as Y from \"yjs\";\nimport type { CloseEvent } from \"@hocuspocus/common\";\nimport type { IncomingMessage } from \"./IncomingMessage.ts\";\nimport type { OutgoingMessage } from \"./OutgoingMessage.ts\";\nimport type { AuthenticationMessage } from \"./OutgoingMessages/AuthenticationMessage.ts\";\nimport type { AwarenessMessage } from \"./OutgoingMessages/AwarenessMessage.ts\";\nimport type { QueryAwarenessMessage } from \"./OutgoingMessages/QueryAwarenessMessage.ts\";\nimport type { SyncStepOneMessage } from \"./OutgoingMessages/SyncStepOneMessage.ts\";\nimport type { SyncStepTwoMessage } from \"./OutgoingMessages/SyncStepTwoMessage.ts\";\nimport type { UpdateMessage } from \"./OutgoingMessages/UpdateMessage.ts\";\n\nexport enum MessageType {\n\tSync = 0,\n\tAwareness = 1,\n\tAuth = 2,\n\tQueryAwareness = 3,\n\tStateless = 5,\n\tCLOSE = 7,\n\tSyncStatus = 8,\n\tPing = 9,\n\tPong = 10,\n}\n\nexport enum WebSocketStatus {\n\tConnecting = \"connecting\",\n\tConnected = \"connected\",\n\tDisconnected = \"disconnected\",\n}\n\nexport type AuthorizedScope = \"read-write\" | \"readonly\";\n\nexport interface OutgoingMessageInterface {\n\tencoder: Encoder;\n\ttype?: MessageType;\n}\n\nexport interface OutgoingMessageArguments {\n\tdocumentName: string;\n\ttoken: string;\n\tdocument: Y.Doc;\n\tawareness: Awareness;\n\tclients: number[];\n\tstates: Map<number, { [key: string]: any }>;\n\tupdate: any;\n\tpayload: string;\n\tencoder: Encoder;\n}\n\nexport interface Constructable<T> {\n\tnew (...args: any): T;\n}\n\nexport type ConstructableOutgoingMessage =\n\t| Constructable<AuthenticationMessage>\n\t| Constructable<AwarenessMessage>\n\t| Constructable<QueryAwarenessMessage>\n\t| Constructable<SyncStepOneMessage>\n\t| Constructable<SyncStepTwoMessage>\n\t| Constructable<UpdateMessage>;\n\nexport type onAuthenticationFailedParameters = {\n\treason: string;\n};\n\nexport type onAuthenticatedParameters = {\n\tscope: AuthorizedScope;\n};\n\nexport type onOpenParameters = {\n\tevent: Event;\n};\n\nexport type onMessageParameters = {\n\tevent: MessageEvent;\n\tmessage: IncomingMessage;\n};\n\nexport type onOutgoingMessageParameters = {\n\tmessage: OutgoingMessage;\n};\n\nexport type onStatusParameters = {\n\tstatus: WebSocketStatus;\n};\n\nexport type onSyncedParameters = {\n\tstate: boolean;\n};\n\nexport type onUnsyncedChangesParameters = {\n\tnumber: number;\n};\n\nexport type onDisconnectParameters = {\n\tevent: CloseEvent;\n};\n\nexport type onCloseParameters = {\n\tevent: CloseEvent;\n};\n\nexport type onAwarenessUpdateParameters = {\n\tstates: StatesArray;\n};\n\nexport type onAwarenessChangeParameters = {\n\tstates: StatesArray;\n};\n\nexport type onStatelessParameters = {\n\tpayload: string;\n};\n\nexport type StatesArray = { clientId: number; [key: string | number]: any }[];\n","import type { Encoder } from \"lib0/encoding\";\nimport { createEncoder, toUint8Array } from \"lib0/encoding\";\nimport type {\n\tMessageType,\n\tOutgoingMessageArguments,\n\tOutgoingMessageInterface,\n} from \"./types.ts\";\n\nexport class OutgoingMessage implements OutgoingMessageInterface {\n\tencoder: Encoder;\n\n\ttype?: MessageType;\n\n\tconstructor() {\n\t\tthis.encoder = createEncoder();\n\t}\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\treturn args.encoder;\n\t}\n\n\ttoUint8Array() {\n\t\treturn toUint8Array(this.encoder);\n\t}\n}\n","import * as encoding from \"lib0/encoding\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class CloseMessage extends OutgoingMessage {\n\ttype = MessageType.CLOSE;\n\n\tdescription = \"Ask the server to close the connection\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tencoding.writeVarString(this.encoder, args.documentName!);\n\t\tencoding.writeVarUint(this.encoder, this.type);\n\n\t\treturn this.encoder;\n\t}\n}\n","import { WsReadyStates } from \"@hocuspocus/common\";\nimport { retry } from \"@lifeomic/attempt\";\nimport { createDecoder, readVarString, readVarUint } from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport * as time from \"lib0/time\";\nimport EventEmitter from \"./EventEmitter.ts\";\nimport type { HocuspocusProvider } from \"./HocuspocusProvider.ts\";\nimport { IncomingMessage } from \"./IncomingMessage.ts\";\nimport { CloseMessage } from \"./OutgoingMessages/CloseMessage.ts\";\nimport {\n\tMessageType,\n\ttype onAwarenessChangeParameters,\n\ttype onAwarenessUpdateParameters,\n\ttype onCloseParameters,\n\ttype onDisconnectParameters,\n\ttype onMessageParameters,\n\ttype onOpenParameters,\n\ttype onOutgoingMessageParameters,\n\ttype onStatusParameters,\n\tWebSocketStatus,\n} from \"./types.ts\";\n\nexport type HocuspocusWebSocket = WebSocket & { identifier: string };\nexport type HocusPocusWebSocket = HocuspocusWebSocket;\n\nexport type HocuspocusProviderWebsocketConfiguration = Required<\n\tPick<CompleteHocuspocusProviderWebsocketConfiguration, \"url\">\n> &\n\tPartial<CompleteHocuspocusProviderWebsocketConfiguration>;\n\nexport interface CompleteHocuspocusProviderWebsocketConfiguration {\n\t/**\n\t * Whether to connect automatically when creating the provider instance. Default=true\n\t */\n\tautoConnect: boolean;\n\n\t/**\n\t * URL of your @hocuspocus/server instance\n\t */\n\turl: string;\n\n\t/**\n\t * By default, trailing slashes are removed from the URL. Set this to true\n\t * to preserve trailing slashes if your server configuration requires them.\n\t */\n\tpreserveTrailingSlash: boolean;\n\n\t/**\n\t * An optional WebSocket polyfill, for example for Node.js\n\t */\n\tWebSocketPolyfill: any;\n\n\t/**\n\t * Disconnect when no message is received for the defined amount of milliseconds.\n\t */\n\tmessageReconnectTimeout: number;\n\t/**\n\t * The delay between each attempt in milliseconds. You can provide a factor to have the delay grow exponentially.\n\t */\n\tdelay: number;\n\t/**\n\t * The initialDelay is the amount of time to wait before making the first attempt. This option should typically be 0 since you typically want the first attempt to happen immediately.\n\t */\n\tinitialDelay: number;\n\t/**\n\t * The factor option is used to grow the delay exponentially.\n\t */\n\tfactor: number;\n\t/**\n\t * The maximum number of attempts or 0 if there is no limit on number of attempts.\n\t */\n\tmaxAttempts: number;\n\t/**\n\t * minDelay is used to set a lower bound of delay when jitter is enabled. This property has no effect if jitter is disabled.\n\t */\n\tminDelay: number;\n\t/**\n\t * The maxDelay option is used to set an upper bound for the delay when factor is enabled. A value of 0 can be provided if there should be no upper bound when calculating delay.\n\t */\n\tmaxDelay: number;\n\t/**\n\t * If jitter is true then the calculated delay will be a random integer value between minDelay and the calculated delay for the current iteration.\n\t */\n\tjitter: boolean;\n\t/**\n\t * A timeout in milliseconds. If timeout is non-zero then a timer is set using setTimeout. If the timeout is triggered then future attempts will be aborted.\n\t */\n\ttimeout: number;\n\thandleTimeout: (() => Promise<unknown>) | null;\n\tonOpen: (data: onOpenParameters) => void;\n\tonConnect: () => void;\n\tonMessage: (data: onMessageParameters) => void;\n\tonOutgoingMessage: (data: onOutgoingMessageParameters) => void;\n\tonStatus: (data: onStatusParameters) => void;\n\tonDisconnect: (data: onDisconnectParameters) => void;\n\tonClose: (data: onCloseParameters) => void;\n\tonDestroy: () => void;\n\tonAwarenessUpdate: (data: onAwarenessUpdateParameters) => void;\n\tonAwarenessChange: (data: onAwarenessChangeParameters) => void;\n\n\t/**\n\t * Map of attached providers keyed by documentName.\n\t */\n\tproviderMap: Map<string, HocuspocusProvider>;\n}\n\nexport class HocuspocusProviderWebsocket extends EventEmitter {\n\tprivate static readonly DEDUPLICATABLE_TYPES = new Set([\n\t\tMessageType.Awareness,\n\t\tMessageType.QueryAwareness,\n\t]);\n\n\tprivate messageQueue: any[] = [];\n\n\tpublic configuration: CompleteHocuspocusProviderWebsocketConfiguration = {\n\t\turl: \"\",\n\t\tautoConnect: true,\n\t\tpreserveTrailingSlash: false,\n\t\t// @ts-expect-error\n\t\tdocument: undefined,\n\t\tWebSocketPolyfill: undefined,\n\t\t// TODO: this should depend on awareness.outdatedTime\n\t\tmessageReconnectTimeout: 30000,\n\t\t// 1 second\n\t\tdelay: 1000,\n\t\t// instant\n\t\tinitialDelay: 0,\n\t\t// double the delay each time\n\t\tfactor: 2,\n\t\t// unlimited retries\n\t\tmaxAttempts: 0,\n\t\t// wait at least 1 second\n\t\tminDelay: 1000,\n\t\t// at least every 30 seconds\n\t\tmaxDelay: 30000,\n\t\t// randomize\n\t\tjitter: true,\n\t\t// retry forever\n\t\ttimeout: 0,\n\t\tonOpen: () => null,\n\t\tonConnect: () => null,\n\t\tonMessage: () => null,\n\t\tonOutgoingMessage: () => null,\n\t\tonStatus: () => null,\n\t\tonDisconnect: () => null,\n\t\tonClose: () => null,\n\t\tonDestroy: () => null,\n\t\tonAwarenessUpdate: () => null,\n\t\tonAwarenessChange: () => null,\n\t\thandleTimeout: null,\n\t\tproviderMap: new Map(),\n\t};\n\n\twebSocket: HocusPocusWebSocket | null = null;\n\n\twebSocketHandlers: { [key: string]: any } = {};\n\n\tshouldConnect = true;\n\n\tstatus = WebSocketStatus.Disconnected;\n\n\tlastMessageReceived = 0;\n\n\tidentifier = 0;\n\n\tintervals: any = {\n\t\tconnectionChecker: null,\n\t};\n\n\tconnectionAttempt: {\n\t\tresolve: (value?: any) => void;\n\t\treject: (reason?: any) => void;\n\t} | null = null;\n\n\tconstructor(configuration: HocuspocusProviderWebsocketConfiguration) {\n\t\tsuper();\n\t\tthis.setConfiguration(configuration);\n\n\t\tthis.configuration.WebSocketPolyfill = configuration.WebSocketPolyfill\n\t\t\t? configuration.WebSocketPolyfill\n\t\t\t: WebSocket;\n\n\t\tthis.on(\"open\", this.configuration.onOpen);\n\t\tthis.on(\"open\", this.onOpen.bind(this));\n\t\tthis.on(\"connect\", this.configuration.onConnect);\n\t\tthis.on(\"message\", this.configuration.onMessage);\n\t\tthis.on(\"outgoingMessage\", this.configuration.onOutgoingMessage);\n\t\tthis.on(\"status\", this.configuration.onStatus);\n\t\tthis.on(\"disconnect\", this.configuration.onDisconnect);\n\t\tthis.on(\"close\", this.configuration.onClose);\n\t\tthis.on(\"destroy\", this.configuration.onDestroy);\n\t\tthis.on(\"awarenessUpdate\", this.configuration.onAwarenessUpdate);\n\t\tthis.on(\"awarenessChange\", this.configuration.onAwarenessChange);\n\n\t\tthis.on(\"close\", this.onClose.bind(this));\n\t\tthis.on(\"message\", this.onMessage.bind(this));\n\n\t\tthis.intervals.connectionChecker = setInterval(\n\t\t\tthis.checkConnection.bind(this),\n\t\t\tthis.configuration.messageReconnectTimeout / 10,\n\t\t);\n\n\t\tif (this.shouldConnect) {\n\t\t\tthis.connect();\n\t\t}\n\t}\n\n\treceivedOnOpenPayload?: Event | undefined = undefined;\n\n\tasync onOpen(event: Event) {\n\t\tthis.status = WebSocketStatus.Connected;\n\t\tthis.emit(\"status\", { status: WebSocketStatus.Connected });\n\n\t\tthis.cancelWebsocketRetry = undefined;\n\t\tthis.receivedOnOpenPayload = event;\n\t}\n\n\tattach(provider: HocuspocusProvider) {\n\t\tconst key = provider.effectiveName;\n\t\tconst existing = this.configuration.providerMap.get(key);\n\n\t\tif (existing && existing !== provider) {\n\t\t\t// Allow replacing a provider that hasn't authenticated (e.g., after auth failure retry)\n\t\t\tif (existing.isAuthenticated) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot attach two providers with the same effective name \"${key}\". ` +\n\t\t\t\t\t\t\"Use sessionAwareness: true to multiplex providers with the same document name.\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis.configuration.providerMap.set(key, provider);\n\n\t\tif (this.status === WebSocketStatus.Disconnected && this.shouldConnect) {\n\t\t\tthis.connect();\n\t\t}\n\n\t\tif (\n\t\t\tthis.receivedOnOpenPayload &&\n\t\t\tthis.status === WebSocketStatus.Connected\n\t\t) {\n\t\t\tprovider.onOpen(this.receivedOnOpenPayload);\n\t\t}\n\t}\n\n\tdetach(provider: HocuspocusProvider) {\n\t\tconst key = provider.effectiveName;\n\t\tif (this.configuration.providerMap.has(key)) {\n\t\t\tprovider.send(CloseMessage, {\n\t\t\t\tdocumentName: key,\n\t\t\t});\n\t\t\tthis.configuration.providerMap.delete(key);\n\t\t}\n\t}\n\n\tpublic setConfiguration(\n\t\tconfiguration: Partial<HocuspocusProviderWebsocketConfiguration> = {},\n\t): void {\n\t\tthis.configuration = { ...this.configuration, ...configuration };\n\n\t\tif (!this.configuration.autoConnect) {\n\t\t\tthis.shouldConnect = false;\n\t\t}\n\t}\n\n\tcancelWebsocketRetry?: () => void;\n\n\tasync connect() {\n\t\tif (this.status === WebSocketStatus.Connected) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Always cancel any previously initiated connection retryer instances\n\t\tif (this.cancelWebsocketRetry) {\n\t\t\tthis.cancelWebsocketRetry();\n\t\t\tthis.cancelWebsocketRetry = undefined;\n\t\t}\n\n\t\tthis.receivedOnOpenPayload = undefined;\n\t\tthis.shouldConnect = true;\n\n\t\tconst abortableRetry = () => {\n\t\t\tlet cancelAttempt = false;\n\n\t\t\tconst retryPromise = retry(this.createWebSocketConnection.bind(this), {\n\t\t\t\tdelay: this.configuration.delay,\n\t\t\t\tinitialDelay: this.configuration.initialDelay,\n\t\t\t\tfactor: this.configuration.factor,\n\t\t\t\tmaxAttempts: this.configuration.maxAttempts,\n\t\t\t\tminDelay: this.configuration.minDelay,\n\t\t\t\tmaxDelay: this.configuration.maxDelay,\n\t\t\t\tjitter: this.configuration.jitter,\n\t\t\t\ttimeout: this.configuration.timeout,\n\t\t\t\thandleTimeout: this.configuration.handleTimeout,\n\t\t\t\tbeforeAttempt: (context) => {\n\t\t\t\t\tif (!this.shouldConnect || cancelAttempt) {\n\t\t\t\t\t\tcontext.abort();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t}).catch((error: any) => {\n\t\t\t\t// If we aborted the connection attempt then don’t throw an error\n\t\t\t\t// ref: https://github.com/lifeomic/attempt/blob/master/src/index.ts#L136\n\t\t\t\tif (error && error.code !== \"ATTEMPT_ABORTED\") {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tretryPromise,\n\t\t\t\tcancelFunc: () => {\n\t\t\t\t\tcancelAttempt = true;\n\t\t\t\t},\n\t\t\t};\n\t\t};\n\n\t\tconst { retryPromise, cancelFunc } = abortableRetry();\n\t\tthis.cancelWebsocketRetry = cancelFunc;\n\n\t\treturn retryPromise;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tattachWebSocketListeners(ws: HocusPocusWebSocket, reject: Function) {\n\t\tconst { identifier } = ws;\n\t\tconst onMessageHandler = (payload: any) => this.emit(\"message\", payload);\n\t\tconst onCloseHandler = (payload: any) =>\n\t\t\tthis.emit(\"close\", { event: payload });\n\t\tconst onOpenHandler = (payload: any) => this.emit(\"open\", payload);\n\t\tconst onErrorHandler = (err: any) => {\n\t\t\treject(err);\n\t\t};\n\n\t\tthis.webSocketHandlers[identifier] = {\n\t\t\tmessage: onMessageHandler,\n\t\t\tclose: onCloseHandler,\n\t\t\topen: onOpenHandler,\n\t\t\terror: onErrorHandler,\n\t\t};\n\n\t\tconst handlers = this.webSocketHandlers[ws.identifier];\n\n\t\tObject.keys(handlers).forEach((name) => {\n\t\t\tws.addEventListener(name, handlers[name]);\n\t\t});\n\t}\n\n\tcleanupWebSocket() {\n\t\tif (!this.webSocket) {\n\t\t\treturn;\n\t\t}\n\t\tconst { identifier } = this.webSocket;\n\t\tconst handlers = this.webSocketHandlers[identifier];\n\n\t\tObject.keys(handlers).forEach((name) => {\n\t\t\tthis.webSocket?.removeEventListener(name, handlers[name]);\n\t\t\tdelete this.webSocketHandlers[identifier];\n\t\t});\n\t\tthis.webSocket.close();\n\t\tthis.webSocket = null;\n\t}\n\n\tcreateWebSocketConnection() {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tif (this.webSocket) {\n\t\t\t\tthis.messageQueue = [];\n\t\t\t\tthis.cleanupWebSocket();\n\t\t\t}\n\t\t\tthis.lastMessageReceived = 0;\n\t\t\tthis.identifier += 1;\n\n\t\t\t// Init the WebSocket connection\n\t\t\tconst ws = new this.configuration.WebSocketPolyfill(this.url);\n\t\t\tws.binaryType = \"arraybuffer\";\n\t\t\tws.identifier = this.identifier;\n\n\t\t\tthis.attachWebSocketListeners(ws, reject);\n\n\t\t\tthis.webSocket = ws;\n\n\t\t\t// Reset the status\n\t\t\tthis.status = WebSocketStatus.Connecting;\n\t\t\tthis.emit(\"status\", { status: WebSocketStatus.Connecting });\n\n\t\t\t// Store resolve/reject for later use\n\t\t\tthis.connectionAttempt = {\n\t\t\t\tresolve,\n\t\t\t\treject,\n\t\t\t};\n\t\t});\n\t}\n\n\tonMessage(event: MessageEvent) {\n\t\tthis.resolveConnectionAttempt();\n\n\t\tthis.lastMessageReceived = time.getUnixTime();\n\n\t\tconst data = new Uint8Array(event.data as ArrayBuffer);\n\n\t\t// Check for connection-level Ping message (no document name prefix)\n\t\t// Ping messages are sent as just the message type byte (length 1)\n\t\t// We check length to avoid confusing with regular messages that happen to have\n\t\t// a document name length of 9 as the first byte\n\t\tif (data.length === 1 && data[0] === MessageType.Ping) {\n\t\t\tthis.sendPong();\n\t\t\treturn;\n\t\t}\n\n\t\tconst message = new IncomingMessage(data);\n\t\tconst rawKey = message.peekVarString();\n\n\t\tconst provider = this.configuration.providerMap.get(rawKey);\n\t\tprovider?.onMessage(event);\n\t}\n\n\t/**\n\t * Send application-level Pong response to server Ping\n\t */\n\tprivate sendPong() {\n\t\tconst encoder = encoding.createEncoder();\n\t\tencoding.writeVarUint(encoder, MessageType.Pong);\n\t\tthis.send(encoding.toUint8Array(encoder));\n\t}\n\n\tresolveConnectionAttempt() {\n\t\tif (this.connectionAttempt) {\n\t\t\tthis.connectionAttempt.resolve();\n\t\t\tthis.connectionAttempt = null;\n\n\t\t\tthis.status = WebSocketStatus.Connected;\n\t\t\tthis.emit(\"status\", { status: WebSocketStatus.Connected });\n\t\t\tthis.emit(\"connect\");\n\t\t\tthis.messageQueue.forEach((message) => this.send(message));\n\t\t\tthis.messageQueue = [];\n\t\t}\n\t}\n\n\tstopConnectionAttempt() {\n\t\tthis.connectionAttempt = null;\n\t}\n\n\trejectConnectionAttempt() {\n\t\tthis.connectionAttempt?.reject();\n\t\tthis.connectionAttempt = null;\n\t}\n\n\tcloseTries = 0;\n\n\tcheckConnection() {\n\t\t// Don’t check the connection when it’s not even established\n\t\tif (this.status !== WebSocketStatus.Connected) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Don’t close the connection while waiting for the first message\n\t\tif (!this.lastMessageReceived) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Don’t close the connection when a message was received recently\n\t\tif (\n\t\t\tthis.configuration.messageReconnectTimeout >=\n\t\t\ttime.getUnixTime() - this.lastMessageReceived\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// No message received in a long time, not even your own\n\t\t// Awareness updates, which are updated every 15 seconds\n\t\t// if awareness is enabled.\n\t\tthis.closeTries += 1;\n\t\t// https://bugs.webkit.org/show_bug.cgi?id=247943\n\t\tif (this.closeTries > 2) {\n\t\t\tthis.onClose({\n\t\t\t\tevent: {\n\t\t\t\t\tcode: 4408,\n\t\t\t\t\treason: \"forced\",\n\t\t\t\t},\n\t\t\t});\n\t\t\tthis.closeTries = 0;\n\t\t} else {\n\t\t\tthis.webSocket?.close();\n\t\t\tthis.messageQueue = [];\n\t\t}\n\t}\n\n\tget serverUrl() {\n\t\tif (this.configuration.preserveTrailingSlash) {\n\t\t\treturn this.configuration.url;\n\t\t}\n\n\t\t// By default, ensure that the URL never ends with /\n\t\tlet url = this.configuration.url;\n\t\twhile (url[url.length - 1] === \"/\") {\n\t\t\turl = url.slice(0, url.length - 1);\n\t\t}\n\n\t\treturn url;\n\t}\n\n\tget url() {\n\t\treturn this.serverUrl;\n\t}\n\n\tdisconnect() {\n\t\tthis.shouldConnect = false;\n\n\t\tif (this.webSocket === null) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.webSocket.close();\n\t\t\tthis.messageQueue = [];\n\t\t} catch (e) {\n\t\t\tconsole.error(e);\n\t\t}\n\t}\n\n\tprivate parseQueuedMessage(\n\t\tmessage: Uint8Array,\n\t): { documentName: string; messageType: number } | null {\n\t\ttry {\n\t\t\tconst decoder = createDecoder(message);\n\t\t\tconst documentName = readVarString(decoder);\n\t\t\tconst messageType = readVarUint(decoder);\n\t\t\treturn { documentName, messageType };\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate addToQueue(message: any) {\n\t\tif (message instanceof Uint8Array) {\n\t\t\tconst parsed = this.parseQueuedMessage(message);\n\t\t\tif (\n\t\t\t\tparsed &&\n\t\t\t\tHocuspocusProviderWebsocket.DEDUPLICATABLE_TYPES.has(parsed.messageType)\n\t\t\t) {\n\t\t\t\tthis.messageQueue = this.messageQueue.filter((queued) => {\n\t\t\t\t\tif (!(queued instanceof Uint8Array)) return true;\n\t\t\t\t\tconst queuedParsed = this.parseQueuedMessage(queued);\n\t\t\t\t\tif (!queuedParsed) return true;\n\t\t\t\t\treturn !(\n\t\t\t\t\t\tqueuedParsed.documentName === parsed.documentName &&\n\t\t\t\t\t\tqueuedParsed.messageType === parsed.messageType\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthis.messageQueue.push(message);\n\t}\n\n\tsend(message: any) {\n\t\tif (this.webSocket?.readyState === WsReadyStates.Open) {\n\t\t\tthis.webSocket.send(message);\n\t\t} else {\n\t\t\tthis.addToQueue(message);\n\t\t}\n\t}\n\n\tonClose({ event }: onCloseParameters) {\n\t\tthis.closeTries = 0;\n\t\tthis.cleanupWebSocket();\n\n\t\tif (this.connectionAttempt) {\n\t\t\t// That connection attempt failed.\n\t\t\tthis.rejectConnectionAttempt();\n\t\t}\n\n\t\t// Let’s update the connection status.\n\t\tthis.status = WebSocketStatus.Disconnected;\n\t\tthis.emit(\"status\", { status: WebSocketStatus.Disconnected });\n\t\tthis.emit(\"disconnect\", { event });\n\n\t\t// trigger connect if no retry is running and we want to have a connection\n\t\tif (!this.cancelWebsocketRetry && this.shouldConnect) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.connect();\n\t\t\t}, this.configuration.delay);\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tthis.emit(\"destroy\");\n\n\t\tclearInterval(this.intervals.connectionChecker);\n\n\t\t// If there is still a connection attempt outstanding then we should stop\n\t\t// it before calling disconnect, otherwise it will be rejected in the onClose\n\t\t// handler and trigger a retry\n\t\tthis.stopConnectionAttempt();\n\n\t\tthis.disconnect();\n\n\t\tthis.removeAllListeners();\n\n\t\tthis.cleanupWebSocket();\n\t}\n}\n","import { type CloseEvent, readAuthMessage } from \"@hocuspocus/common\";\nimport { readVarInt, readVarString } from \"lib0/decoding\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport { messageYjsSyncStep2, readSyncMessage } from \"y-protocols/sync\";\nimport type { HocuspocusProvider } from \"./HocuspocusProvider.ts\";\nimport type { IncomingMessage } from \"./IncomingMessage.ts\";\nimport { OutgoingMessage } from \"./OutgoingMessage.ts\";\nimport { MessageType } from \"./types.ts\";\n\nexport class MessageReceiver {\n\tmessage: IncomingMessage;\n\n\tconstructor(message: IncomingMessage) {\n\t\tthis.message = message;\n\t}\n\n\tpublic apply(provider: HocuspocusProvider, emitSynced: boolean) {\n\t\tconst { message } = this;\n\t\tconst type = message.readVarUint();\n\n\t\tconst emptyMessageLength = message.length();\n\n\t\tswitch (type) {\n\t\t\tcase MessageType.Sync:\n\t\t\t\tthis.applySyncMessage(provider, emitSynced);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.Awareness:\n\t\t\t\tthis.applyAwarenessMessage(provider);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.Auth:\n\t\t\t\tthis.applyAuthMessage(provider);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.QueryAwareness:\n\t\t\t\tthis.applyQueryAwarenessMessage(provider);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.Stateless:\n\t\t\t\tprovider.receiveStateless(readVarString(message.decoder));\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.SyncStatus:\n\t\t\t\tthis.applySyncStatusMessage(\n\t\t\t\t\tprovider,\n\t\t\t\t\treadVarInt(message.decoder) === 1,\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.CLOSE: {\n\t\t\t\t// eslint-disable-next-line no-case-declarations\n\t\t\t\tconst event: CloseEvent = {\n\t\t\t\t\tcode: 1000,\n\t\t\t\t\treason: readVarString(message.decoder),\n\t\t\t\t};\n\t\t\t\tprovider.onClose();\n\t\t\t\tprovider.configuration.onClose({ event });\n\t\t\t\tprovider.forwardClose({ event });\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tconsole.error(`Can’t apply message of unknown type: ${type}`);\n\t\t}\n\n\t\t// Reply\n\t\tif (message.length() > emptyMessageLength + 1) {\n\t\t\t// length of documentName (considered in emptyMessageLength plus length of yjs sync type, set in applySyncMessage)\n\t\t\t// @ts-expect-error\n\t\t\tprovider.send(OutgoingMessage, { encoder: message.encoder });\n\t\t}\n\t}\n\n\tprivate applySyncMessage(provider: HocuspocusProvider, emitSynced: boolean) {\n\t\tconst { message } = this;\n\n\t\tmessage.writeVarUint(MessageType.Sync);\n\n\t\t// Apply update\n\t\tconst syncMessageType = readSyncMessage(\n\t\t\tmessage.decoder,\n\t\t\tmessage.encoder,\n\t\t\tprovider.document,\n\t\t\tprovider,\n\t\t);\n\n\t\t// Synced once we receive Step2\n\t\tif (emitSynced && syncMessageType === messageYjsSyncStep2) {\n\t\t\tprovider.synced = true;\n\t\t}\n\t}\n\n\tapplySyncStatusMessage(provider: HocuspocusProvider, applied: boolean) {\n\t\tif (applied) {\n\t\t\tprovider.decrementUnsyncedChanges();\n\t\t}\n\t}\n\n\tprivate applyAwarenessMessage(provider: HocuspocusProvider) {\n\t\tif (!provider.awareness) return;\n\n\t\tconst { message } = this;\n\n\t\tawarenessProtocol.applyAwarenessUpdate(\n\t\t\tprovider.awareness,\n\t\t\tmessage.readVarUint8Array(),\n\t\t\tprovider,\n\t\t);\n\t}\n\n\tprivate applyAuthMessage(provider: HocuspocusProvider) {\n\t\tconst { message } = this;\n\n\t\treadAuthMessage(\n\t\t\tmessage.decoder,\n\t\t\tprovider.sendToken.bind(provider),\n\t\t\tprovider.permissionDeniedHandler.bind(provider),\n\t\t\tprovider.authenticatedHandler.bind(provider),\n\t\t);\n\t}\n\n\tprivate applyQueryAwarenessMessage(provider: HocuspocusProvider) {\n\t\tif (!provider.awareness) return;\n\n\t\tconst { message } = this;\n\n\t\tmessage.writeVarUint(MessageType.Awareness);\n\t\tmessage.writeVarUint8Array(\n\t\t\tawarenessProtocol.encodeAwarenessUpdate(\n\t\t\t\tprovider.awareness,\n\t\t\t\tArray.from(provider.awareness.getStates().keys()),\n\t\t\t),\n\t\t);\n\t}\n}\n","import type { Encoder } from \"lib0/encoding\";\nimport { toUint8Array } from \"lib0/encoding\";\nimport type { ConstructableOutgoingMessage } from \"./types.ts\";\n\nexport class MessageSender {\n\tencoder: Encoder;\n\n\tmessage: any;\n\n\tconstructor(Message: ConstructableOutgoingMessage, args: any = {}) {\n\t\tthis.message = new Message();\n\t\tthis.encoder = this.message.get(args);\n\t}\n\n\tcreate() {\n\t\treturn toUint8Array(this.encoder);\n\t}\n\n\tsend(webSocket: any) {\n\t\twebSocket?.send(this.create());\n\t}\n}\n","export const version: string =\n\t// @ts-expect-error - __HOCUSPOCUS_VERSION__ is replaced at build time by rolldown\n\ttypeof __HOCUSPOCUS_VERSION__ !== \"undefined\"\n\t\t? // @ts-expect-error - __HOCUSPOCUS_VERSION__ is replaced at build time by rolldown\n\t\t\t__HOCUSPOCUS_VERSION__\n\t\t: \"unknown\";\n","import { writeVarString, writeVarUint } from \"lib0/encoding\";\nimport { writeAuthentication } from \"@hocuspocus/common\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\nimport { version } from \"../version.ts\";\n\nexport class AuthenticationMessage extends OutgoingMessage {\n\ttype = MessageType.Auth;\n\n\tdescription = \"Authentication\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tif (typeof args.token === \"undefined\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"The authentication message requires `token` as an argument.\",\n\t\t\t);\n\t\t}\n\n\t\twriteVarString(this.encoder, args.documentName!);\n\t\twriteVarUint(this.encoder, this.type);\n\t\twriteAuthentication(this.encoder, args.token);\n\t\twriteVarString(this.encoder, version);\n\n\t\treturn this.encoder;\n\t}\n}\n","import * as encoding from \"lib0/encoding\";\nimport { encodeAwarenessUpdate } from \"y-protocols/awareness\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class AwarenessMessage extends OutgoingMessage {\n\ttype = MessageType.Awareness;\n\n\tdescription = \"Awareness states update\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tif (typeof args.awareness === \"undefined\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"The awareness message requires awareness as an argument\",\n\t\t\t);\n\t\t}\n\n\t\tif (typeof args.clients === \"undefined\") {\n\t\t\tthrow new Error(\"The awareness message requires clients as an argument\");\n\t\t}\n\n\t\tencoding.writeVarString(this.encoder, args.documentName!);\n\t\tencoding.writeVarUint(this.encoder, this.type);\n\n\t\tlet awarenessUpdate;\n\t\tif (args.states === undefined) {\n\t\t\tawarenessUpdate = encodeAwarenessUpdate(args.awareness, args.clients);\n\t\t} else {\n\t\t\tawarenessUpdate = encodeAwarenessUpdate(\n\t\t\t\targs.awareness,\n\t\t\t\targs.clients,\n\t\t\t\targs.states,\n\t\t\t);\n\t\t}\n\n\t\tencoding.writeVarUint8Array(this.encoder, awarenessUpdate);\n\n\t\treturn this.encoder;\n\t}\n}\n","import { writeVarString, writeVarUint } from \"lib0/encoding\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class StatelessMessage extends OutgoingMessage {\n\ttype = MessageType.Stateless;\n\n\tdescription = \"A stateless message\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\twriteVarString(this.encoder, args.documentName!);\n\t\twriteVarUint(this.encoder, this.type);\n\t\twriteVarString(this.encoder, args.payload ?? \"\");\n\n\t\treturn this.encoder;\n\t}\n}\n","import * as encoding from \"lib0/encoding\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class SyncStepOneMessage extends OutgoingMessage {\n\ttype = MessageType.Sync;\n\n\tdescription = \"First sync step\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tif (typeof args.document === \"undefined\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"The sync step one message requires document as an argument\",\n\t\t\t);\n\t\t}\n\n\t\tencoding.writeVarString(this.encoder, args.documentName!);\n\t\tencoding.writeVarUint(this.encoder, this.type);\n\t\tsyncProtocol.writeSyncStep1(this.encoder, args.document);\n\n\t\treturn this.encoder;\n\t}\n}\n","import { writeVarString, writeVarUint } from \"lib0/encoding\";\nimport { writeUpdate } from \"y-protocols/sync\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class UpdateMessage extends OutgoingMessage {\n\ttype = MessageType.Sync;\n\n\tdescription = \"A document update\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\twriteVarString(this.encoder, args.documentName!);\n\t\twriteVarUint(this.encoder, this.type);\n\n\t\twriteUpdate(this.encoder, args.update);\n\n\t\treturn this.encoder;\n\t}\n}\n","import { awarenessStatesToArray, makeRoutingKey, parseRoutingKey } from \"@hocuspocus/common\";\nimport { Awareness, removeAwarenessStates } from \"y-protocols/awareness\";\nimport * as Y from \"yjs\";\nimport EventEmitter from \"./EventEmitter.ts\";\nimport type { CompleteHocuspocusProviderWebsocketConfiguration } from \"./HocuspocusProviderWebsocket.ts\";\nimport { HocuspocusProviderWebsocket } from \"./HocuspocusProviderWebsocket.ts\";\nimport { IncomingMessage } from \"./IncomingMessage.ts\";\nimport { MessageReceiver } from \"./MessageReceiver.ts\";\nimport { MessageSender } from \"./MessageSender.ts\";\nimport { AuthenticationMessage } from \"./OutgoingMessages/AuthenticationMessage.ts\";\nimport { AwarenessMessage } from \"./OutgoingMessages/AwarenessMessage.ts\";\nimport { StatelessMessage } from \"./OutgoingMessages/StatelessMessage.ts\";\nimport { SyncStepOneMessage } from \"./OutgoingMessages/SyncStepOneMessage.ts\";\nimport { UpdateMessage } from \"./OutgoingMessages/UpdateMessage.ts\";\nimport type {\n\tAuthorizedScope,\n\tConstructableOutgoingMessage,\n\tonAuthenticatedParameters,\n\tonAuthenticationFailedParameters,\n\tonAwarenessChangeParameters,\n\tonAwarenessUpdateParameters,\n\tonCloseParameters,\n\tonDisconnectParameters,\n\tonMessageParameters,\n\tonOpenParameters,\n\tonOutgoingMessageParameters,\n\tonStatelessParameters,\n\tonStatusParameters,\n\tonSyncedParameters,\n\tonUnsyncedChangesParameters,\n} from \"./types.ts\";\n\nexport type HocuspocusProviderConfiguration = Required<\n\tPick<CompleteHocuspocusProviderConfiguration, \"name\">\n> &\n\tPartial<CompleteHocuspocusProviderConfiguration> &\n\t(\n\t\t| (Required<Pick<CompleteHocuspocusProviderWebsocketConfiguration, \"url\">> &\n\t\t\t\tPartial<\n\t\t\t\t\tPick<\n\t\t\t\t\t\tCompleteHocuspocusProviderWebsocketConfiguration,\n\t\t\t\t\t\t\"preserveTrailingSlash\"\n\t\t\t\t\t>\n\t\t\t\t>)\n\t\t| Required<\n\t\t\t\tPick<CompleteHocuspocusProviderConfiguration, \"websocketProvider\">\n\t\t >\n\t);\n\nexport interface CompleteHocuspocusProviderConfiguration {\n\t/**\n\t * The identifier/name of your document\n\t */\n\tname: string;\n\t/**\n\t * The actual Y.js document\n\t */\n\tdocument: Y.Doc;\n\n\t/**\n\t * An Awareness instance to keep the presence state of all clients.\n\t *\n\t * You can disable sharing awareness information by passing `null`.\n\t * Note that having no awareness information shared across all connections will break our ping checks\n\t * and thus trigger reconnects. You should always have at least one Provider with enabled awareness per\n\t * socket connection, or ensure that the Provider receives messages before running into `HocuspocusProviderWebsocket.messageReconnectTimeout`.\n\t */\n\tawareness: Awareness | null;\n\n\t/**\n\t * A token that’s sent to the backend for authentication purposes.\n\t */\n\ttoken: string | (() => string) | (() => Promise<string>) | null;\n\n\t/**\n\t * Hocuspocus websocket provider\n\t */\n\twebsocketProvider: HocuspocusProviderWebsocket;\n\n\t/**\n\t * Enable session-aware multiplexing. When true, the provider embeds a unique\n\t * sessionId in the documentName field of every message, allowing multiple\n\t * providers with the same document name on a single WebSocket connection.\n\t *\n\t * Only set this to `true` when connecting to a v4 server that does \n\t * support session awareness.\n\t *\n\t * Default: false\n\t */\n\tsessionAwareness: boolean;\n\n\t/**\n\t * Force syncing the document in the defined interval.\n\t */\n\tforceSyncInterval: false | number;\n\n\tonAuthenticated: (data: onAuthenticatedParameters) => void;\n\tonAuthenticationFailed: (data: onAuthenticationFailedParameters) => void;\n\tonOpen: (data: onOpenParameters) => void;\n\tonConnect: () => void;\n\tonStatus: (data: onStatusParameters) => void;\n\tonMessage: (data: onMessageParameters) => void;\n\tonOutgoingMessage: (data: onOutgoingMessageParameters) => void;\n\tonSynced: (data: onSyncedParameters) => void;\n\tonDisconnect: (data: onDisconnectParameters) => void;\n\tonClose: (data: onCloseParameters) => void;\n\tonDestroy: () => void;\n\tonAwarenessUpdate: (data: onAwarenessUpdateParameters) => void;\n\tonAwarenessChange: (data: onAwarenessChangeParameters) => void;\n\tonStateless: (data: onStatelessParameters) => void;\n\tonUnsyncedChanges: (data: onUnsyncedChangesParameters) => void;\n}\n\nexport class AwarenessError extends Error {\n\tcode = 1001;\n}\n\nexport class HocuspocusProvider extends EventEmitter {\n\tpublic configuration: CompleteHocuspocusProviderConfiguration = {\n\t\tname: \"\",\n\t\t// @ts-expect-error\n\t\tdocument: undefined,\n\t\t// @ts-expect-error\n\t\tawareness: undefined,\n\t\ttoken: null,\n\t\tsessionAwareness: false,\n\t\tforceSyncInterval: false,\n\t\tonAuthenticated: () => null,\n\t\tonAuthenticationFailed: () => null,\n\t\tonOpen: () => null,\n\t\tonConnect: () => null,\n\t\tonMessage: () => null,\n\t\tonOutgoingMessage: () => null,\n\t\tonSynced: () => null,\n\t\tonStatus: () => null,\n\t\tonDisconnect: () => null,\n\t\tonClose: () => null,\n\t\tonDestroy: () => null,\n\t\tonAwarenessUpdate: () => null,\n\t\tonAwarenessChange: () => null,\n\t\tonStateless: () => null,\n\t\tonUnsyncedChanges: () => null,\n\t};\n\n\tisSynced = false;\n\n\tunsyncedChanges = 0;\n\n\tisAuthenticated = false;\n\n\tauthorizedScope: AuthorizedScope | undefined = undefined;\n\n\t// @internal\n\tmanageSocket = false;\n\n\tprivate _isAttached = false;\n\n\t/**\n\t * Unique session identifier for this provider instance.\n\t * Used for multiplexing multiple providers with the same document name on a single WebSocket.\n\t */\n\tsessionId: string = Math.random().toString(36).slice(2);\n\n\t/**\n\t * The effective name used as the first VarString in messages.\n\t * When `sessionAwareness` is enabled, returns a composite key (documentName\\0sessionId).\n\t * Otherwise, returns the plain document name.\n\t */\n\tget effectiveName(): string {\n\t\treturn this.configuration.sessionAwareness\n\t\t\t? makeRoutingKey(this.configuration.name, this.sessionId)\n\t\t\t: this.configuration.name;\n\t}\n\n\tintervals: any = {\n\t\tforceSync: null,\n\t};\n\n\tconstructor(configuration: HocuspocusProviderConfiguration) {\n\t\tsuper();\n\t\tthis.setConfiguration(configuration);\n\n\t\tthis.configuration.document = configuration.document\n\t\t\t? configuration.document\n\t\t\t: new Y.Doc();\n\t\tthis.configuration.awareness =\n\t\t\tconfiguration.awareness !== undefined\n\t\t\t\t? configuration.awareness\n\t\t\t\t: new Awareness(this.document);\n\n\t\tthis.on(\"open\", this.configuration.onOpen);\n\t\tthis.on(\"message\", this.configuration.onMessage);\n\t\tthis.on(\"outgoingMessage\", this.configuration.onOutgoingMessage);\n\t\tthis.on(\"synced\", this.configuration.onSynced);\n\t\tthis.on(\"destroy\", this.configuration.onDestroy);\n\t\tthis.on(\"awarenessUpdate\", this.configuration.onAwarenessUpdate);\n\t\tthis.on(\"awarenessChange\", this.configuration.onAwarenessChange);\n\t\tthis.on(\"stateless\", this.configuration.onStateless);\n\t\tthis.on(\"unsyncedChanges\", this.configuration.onUnsyncedChanges);\n\n\t\tthis.on(\"authenticated\", this.configuration.onAuthenticated);\n\t\tthis.on(\"authenticationFailed\", this.configuration.onAuthenticationFailed);\n\n\t\tthis.awareness?.on(\"update\", () => {\n\t\t\tthis.emit(\"awarenessUpdate\", {\n\t\t\t\tstates: awarenessStatesToArray(this.awareness!.getStates()),\n\t\t\t});\n\t\t});\n\n\t\tthis.awareness?.on(\"change\", () => {\n\t\t\tthis.emit(\"awarenessChange\", {\n\t\t\t\tstates: awarenessStatesToArray(this.awareness!.getStates()),\n\t\t\t});\n\t\t});\n\n\t\tthis.document.on(\"update\", this.boundDocumentUpdateHandler);\n\t\tthis.awareness?.on(\"update\", this.boundAwarenessUpdateHandler);\n\n\t\tthis.registerEventListeners();\n\n\t\tif (\n\t\t\tthis.configuration.forceSyncInterval &&\n\t\t\ttypeof this.configuration.forceSyncInterval === \"number\"\n\t\t) {\n\t\t\tthis.intervals.forceSync = setInterval(\n\t\t\t\tthis.forceSync.bind(this),\n\t\t\t\tthis.configuration.forceSyncInterval,\n\t\t\t);\n\t\t}\n\n\t\tif (this.manageSocket) {\n\t\t\tthis.attach();\n\t\t}\n\t}\n\n\tboundDocumentUpdateHandler = this.documentUpdateHandler.bind(this);\n\n\tboundAwarenessUpdateHandler = this.awarenessUpdateHandler.bind(this);\n\n\tboundPageHide = this.pageHide.bind(this);\n\n\tboundOnOpen = this.onOpen.bind(this);\n\n\tboundOnClose = this.onClose.bind(this);\n\n\tforwardConnect = () => this.emit(\"connect\");\n\n\tforwardStatus = (e: onStatusParameters) => this.emit(\"status\", e);\n\n\tforwardClose = (e: onCloseParameters) => this.emit(\"close\", e);\n\n\tforwardDisconnect = (e: onDisconnectParameters) => this.emit(\"disconnect\", e);\n\n\tforwardDestroy = () => this.emit(\"destroy\");\n\n\tpublic setConfiguration(\n\t\tconfiguration: Partial<HocuspocusProviderConfiguration> = {},\n\t): void {\n\t\tif (!configuration.websocketProvider) {\n\t\t\tthis.manageSocket = true;\n\t\t\tthis.configuration.websocketProvider = new HocuspocusProviderWebsocket(\n\t\t\t\tconfiguration as CompleteHocuspocusProviderWebsocketConfiguration,\n\t\t\t);\n\t\t}\n\n\t\tthis.configuration = { ...this.configuration, ...configuration };\n\t}\n\n\tget document() {\n\t\treturn this.configuration.document;\n\t}\n\n\tpublic get isAttached() {\n\t\treturn this._isAttached;\n\t}\n\n\tget awareness() {\n\t\treturn this.configuration.awareness;\n\t}\n\n\tget hasUnsyncedChanges(): boolean {\n\t\treturn this.unsyncedChanges > 0;\n\t}\n\n\tprivate resetUnsyncedChanges() {\n\t\tthis.unsyncedChanges = 1;\n\t\tthis.emit(\"unsyncedChanges\", { number: this.unsyncedChanges });\n\t}\n\n\tincrementUnsyncedChanges() {\n\t\tthis.unsyncedChanges += 1;\n\t\tthis.emit(\"unsyncedChanges\", { number: this.unsyncedChanges });\n\t}\n\n\tdecrementUnsyncedChanges() {\n\t\tif (this.unsyncedChanges > 0) {\n\t\t\tthis.unsyncedChanges -= 1;\n\t\t}\n\n\t\tif (this.unsyncedChanges === 0) {\n\t\t\tthis.synced = true;\n\t\t}\n\n\t\tthis.emit(\"unsyncedChanges\", { number: this.unsyncedChanges });\n\t}\n\n\tforceSync() {\n\t\tthis.resetUnsyncedChanges();\n\n\t\tthis.send(SyncStepOneMessage, {\n\t\t\tdocument: this.document,\n\t\t\tdocumentName: this.effectiveName,\n\t\t});\n\t}\n\n\tpageHide() {\n\t\tif (this.awareness) {\n\t\t\tremoveAwarenessStates(\n\t\t\t\tthis.awareness,\n\t\t\t\t[this.document.clientID],\n\t\t\t\t\"page hide\",\n\t\t\t);\n\t\t}\n\t}\n\n\tregisterEventListeners() {\n\t\tif (typeof window === \"undefined\" || !(\"addEventListener\" in window)) {\n\t\t\treturn;\n\t\t}\n\n\t\twindow.addEventListener(\"pagehide\", this.boundPageHide);\n\t}\n\n\tsendStateless(payload: string) {\n\t\tthis.send(StatelessMessage, {\n\t\t\tdocumentName: this.effectiveName,\n\t\t\tpayload,\n\t\t});\n\t}\n\n\tasync sendToken() {\n\t\tlet token: string | null;\n\t\ttry {\n\t\t\ttoken = await this.getToken();\n\t\t} catch (error) {\n\t\t\tthis.permissionDeniedHandler(\n\t\t\t\t`Failed to get token during sendToken(): ${error}`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.send(AuthenticationMessage, {\n\t\t\ttoken: token ?? \"\",\n\t\t\tdocumentName: this.effectiveName,\n\t\t});\n\t}\n\n\tdocumentUpdateHandler(update: Uint8Array, origin: any) {\n\t\tif (origin === this) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.incrementUnsyncedChanges();\n\t\tthis.send(UpdateMessage, { update, documentName: this.effectiveName });\n\t}\n\n\tawarenessUpdateHandler({ added, updated, removed }: any, origin: any) {\n\t\tconst changedClients = added.concat(updated).concat(removed);\n\n\t\tthis.send(AwarenessMessage, {\n\t\t\tawareness: this.awareness,\n\t\t\tclients: changedClients,\n\t\t\tdocumentName: this.effectiveName,\n\t\t});\n\t}\n\n\t/**\n\t * Indicates whether a first handshake with the server has been established\n\t *\n\t * Note: this does not mean all updates from the client have been persisted to the backend. For this,\n\t * use `hasUnsyncedChanges`.\n\t */\n\tget synced(): boolean {\n\t\treturn this.isSynced;\n\t}\n\n\tset synced(state) {\n\t\tif (this.isSynced === state) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.isSynced = state;\n\n\t\tif (state) {\n\t\t\tthis.emit(\"synced\", { state });\n\t\t}\n\t}\n\n\treceiveStateless(payload: string) {\n\t\tthis.emit(\"stateless\", { payload });\n\t}\n\n\t// not needed, but provides backward compatibility with e.g. lexical/yjs\n\tasync connect() {\n\t\tif (this.manageSocket) {\n\t\t\treturn this.configuration.websocketProvider.connect();\n\t\t}\n\n\t\tconsole.warn(\n\t\t\t\"HocuspocusProvider::connect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.\",\n\t\t);\n\t}\n\n\tdisconnect() {\n\t\tif (this.manageSocket) {\n\t\t\treturn this.configuration.websocketProvider.disconnect();\n\t\t}\n\n\t\tconsole.warn(\n\t\t\t\"HocuspocusProvider::disconnect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.\",\n\t\t);\n\t}\n\n\tasync onOpen(event: Event) {\n\t\tthis.isAuthenticated = false;\n\n\t\tthis.emit(\"open\", { event });\n\t\tawait this.sendToken();\n\t\tthis.startSync();\n\t}\n\n\tasync getToken() {\n\t\tif (typeof this.configuration.token === \"function\") {\n\t\t\tconst token = await this.configuration.token();\n\t\t\treturn token;\n\t\t}\n\n\t\treturn this.configuration.token;\n\t}\n\n\tstartSync() {\n\t\tthis.resetUnsyncedChanges();\n\n\t\tthis.send(SyncStepOneMessage, {\n\t\t\tdocument: this.document,\n\t\t\tdocumentName: this.effectiveName,\n\t\t});\n\n\t\tif (this.awareness && this.awareness.getLocalState() !== null) {\n\t\t\tthis.send(AwarenessMessage, {\n\t\t\t\tawareness: this.awareness,\n\t\t\t\tclients: [this.document.clientID],\n\t\t\t\tdocumentName: this.effectiveName,\n\t\t\t});\n\t\t}\n\t}\n\n\tsend(message: ConstructableOutgoingMessage, args: any) {\n\t\tif (!this._isAttached) return;\n\n\t\tconst messageSender = new MessageSender(message, args);\n\n\t\tthis.emit(\"outgoingMessage\", { message: messageSender.message });\n\t\tmessageSender.send(this.configuration.websocketProvider);\n\t}\n\n\tonMessage(event: MessageEvent) {\n\t\tconst message = new IncomingMessage(event.data);\n\n\t\tconst rawKey = message.readVarString();\n\t\t// Extract actual documentName from potentially composite routing key\n\t\tconst { documentName } = parseRoutingKey(rawKey);\n\n\t\tmessage.writeVarString(this.effectiveName);\n\n\t\tthis.emit(\"message\", { event, message: new IncomingMessage(event.data) });\n\n\t\tnew MessageReceiver(message).apply(this, true);\n\t}\n\n\tonClose() {\n\t\tthis.isAuthenticated = false;\n\t\tthis.synced = false;\n\n\t\t// update awareness (all users except local left)\n\t\tif (this.awareness) {\n\t\t\tremoveAwarenessStates(\n\t\t\t\tthis.awareness,\n\t\t\t\tArray.from(this.awareness.getStates().keys()).filter(\n\t\t\t\t\t(client) => client !== this.document.clientID,\n\t\t\t\t),\n\t\t\t\tthis,\n\t\t\t);\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tthis.emit(\"destroy\");\n\n\t\tif (this.intervals.forceSync) {\n\t\t\tclearInterval(this.intervals.forceSync);\n\t\t}\n\n\t\tif (this.awareness) {\n\t\t\tremoveAwarenessStates(\n\t\t\t\tthis.awareness,\n\t\t\t\t[this.document.clientID],\n\t\t\t\t\"provider destroy\",\n\t\t\t);\n\t\t\tthis.awareness.off(\"update\", this.boundAwarenessUpdateHandler);\n\t\t\tthis.awareness.destroy();\n\t\t}\n\n\t\tthis.document.off(\"update\", this.boundDocumentUpdateHandler);\n\n\t\tthis.removeAllListeners();\n\n\t\tthis.detach();\n\n\t\tif (this.manageSocket) {\n\t\t\tthis.configuration.websocketProvider.destroy();\n\t\t}\n\n\t\tif (typeof window === \"undefined\" || !(\"removeEventListener\" in window)) {\n\t\t\treturn;\n\t\t}\n\n\t\twindow.removeEventListener(\"pagehide\", this.boundPageHide);\n\t}\n\n\tdetach() {\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"connect\",\n\t\t\tthis.configuration.onConnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\"connect\", this.forwardConnect);\n\n\t\tthis.configuration.websocketProvider.off(\"status\", this.forwardStatus);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"status\",\n\t\t\tthis.configuration.onStatus,\n\t\t);\n\n\t\tthis.configuration.websocketProvider.off(\"open\", this.boundOnOpen);\n\t\tthis.configuration.websocketProvider.off(\"close\", this.boundOnClose);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"close\",\n\t\t\tthis.configuration.onClose,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\"close\", this.forwardClose);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"disconnect\",\n\t\t\tthis.configuration.onDisconnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"disconnect\",\n\t\t\tthis.forwardDisconnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"destroy\",\n\t\t\tthis.configuration.onDestroy,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\"destroy\", this.forwardDestroy);\n\n\t\tthis.configuration.websocketProvider.detach(this);\n\n\t\tthis._isAttached = false;\n\t}\n\n\tattach() {\n\t\tif (this._isAttached) return;\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"connect\",\n\t\t\tthis.configuration.onConnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"connect\", this.forwardConnect);\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"status\",\n\t\t\tthis.configuration.onStatus,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"status\", this.forwardStatus);\n\n\t\tthis.configuration.websocketProvider.on(\"open\", this.boundOnOpen);\n\n\t\tthis.configuration.websocketProvider.on(\"close\", this.boundOnClose);\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"close\",\n\t\t\tthis.configuration.onClose,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"close\", this.forwardClose);\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"disconnect\",\n\t\t\tthis.configuration.onDisconnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"disconnect\",\n\t\t\tthis.forwardDisconnect,\n\t\t);\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"destroy\",\n\t\t\tthis.configuration.onDestroy,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"destroy\", this.forwardDestroy);\n\n\t\tthis.configuration.websocketProvider.attach(this);\n\n\t\tthis._isAttached = true;\n\t}\n\n\tpermissionDeniedHandler(reason: string) {\n\t\tthis.emit(\"authenticationFailed\", { reason });\n\t\tthis.isAuthenticated = false;\n\t}\n\n\tauthenticatedHandler(scope: string) {\n\t\tthis.isAuthenticated = true;\n\t\tthis.authorizedScope = scope as AuthorizedScope;\n\n\t\tthis.emit(\"authenticated\", { scope });\n\t}\n\n\tsetAwarenessField(key: string, value: any) {\n\t\tif (!this.awareness) {\n\t\t\tthrow new AwarenessError(\n\t\t\t\t`Cannot set awareness field \"${key}\" to ${JSON.stringify(value)}. You have disabled Awareness for this provider by explicitly passing awareness: null in the provider configuration.`,\n\t\t\t);\n\t\t}\n\t\tthis.awareness.setLocalStateField(key, value);\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"hocuspocus-provider.esm.js","names":[],"sources":["../src/EventEmitter.ts","../src/IncomingMessage.ts","../src/types.ts","../src/OutgoingMessage.ts","../src/OutgoingMessages/CloseMessage.ts","../src/HocuspocusProviderWebsocket.ts","../src/MessageReceiver.ts","../src/MessageSender.ts","../src/version.ts","../src/OutgoingMessages/AuthenticationMessage.ts","../src/OutgoingMessages/AwarenessMessage.ts","../src/OutgoingMessages/StatelessMessage.ts","../src/OutgoingMessages/SyncStepOneMessage.ts","../src/OutgoingMessages/UpdateMessage.ts","../src/HocuspocusProvider.ts"],"sourcesContent":["export default class EventEmitter {\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tpublic callbacks: { [key: string]: Function[] } = {};\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tpublic on(event: string, fn: Function): this {\n\t\tif (!this.callbacks[event]) {\n\t\t\tthis.callbacks[event] = [];\n\t\t}\n\n\t\tthis.callbacks[event].push(fn);\n\n\t\treturn this;\n\t}\n\n\tprotected emit(event: string, ...args: any): this {\n\t\tconst callbacks = this.callbacks[event];\n\n\t\tif (callbacks) {\n\t\t\tcallbacks.forEach((callback) => callback.apply(this, args));\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tpublic off(event: string, fn?: Function): this {\n\t\tconst callbacks = this.callbacks[event];\n\n\t\tif (callbacks) {\n\t\t\tif (fn) {\n\t\t\t\tthis.callbacks[event] = callbacks.filter((callback) => callback !== fn);\n\t\t\t} else {\n\t\t\t\tdelete this.callbacks[event];\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n\n\tremoveAllListeners(): void {\n\t\tthis.callbacks = {};\n\t}\n}\n","import type { Decoder } from \"lib0/decoding\";\nimport {\n\tcreateDecoder,\n\tpeekVarString,\n\treadVarUint,\n\treadVarUint8Array,\n\treadVarString,\n} from \"lib0/decoding\";\nimport type { Encoder } from \"lib0/encoding\";\nimport {\n\tcreateEncoder,\n\twriteVarUint,\n\twriteVarUint8Array,\n\twriteVarString,\n\tlength,\n} from \"lib0/encoding\";\nimport type { MessageType } from \"./types.ts\";\n\nexport class IncomingMessage {\n\tdata: any;\n\n\tencoder: Encoder;\n\n\tdecoder: Decoder;\n\n\tconstructor(data: any) {\n\t\tthis.data = data;\n\t\tthis.encoder = createEncoder();\n\t\tthis.decoder = createDecoder(new Uint8Array(this.data));\n\t}\n\n\tpeekVarString(): string {\n\t\treturn peekVarString(this.decoder);\n\t}\n\n\treadVarUint(): MessageType {\n\t\treturn readVarUint(this.decoder);\n\t}\n\n\treadVarString(): string {\n\t\treturn readVarString(this.decoder);\n\t}\n\n\treadVarUint8Array() {\n\t\treturn readVarUint8Array(this.decoder);\n\t}\n\n\twriteVarUint(type: MessageType) {\n\t\treturn writeVarUint(this.encoder, type);\n\t}\n\n\twriteVarString(string: string) {\n\t\treturn writeVarString(this.encoder, string);\n\t}\n\n\twriteVarUint8Array(data: Uint8Array) {\n\t\treturn writeVarUint8Array(this.encoder, data);\n\t}\n\n\tlength() {\n\t\treturn length(this.encoder);\n\t}\n}\n","import type { Encoder } from \"lib0/encoding\";\nimport type { Awareness } from \"y-protocols/awareness\";\nimport type * as Y from \"yjs\";\nimport type { CloseEvent } from \"@hocuspocus/common\";\nimport type { IncomingMessage } from \"./IncomingMessage.ts\";\nimport type { OutgoingMessage } from \"./OutgoingMessage.ts\";\nimport type { AuthenticationMessage } from \"./OutgoingMessages/AuthenticationMessage.ts\";\nimport type { AwarenessMessage } from \"./OutgoingMessages/AwarenessMessage.ts\";\nimport type { QueryAwarenessMessage } from \"./OutgoingMessages/QueryAwarenessMessage.ts\";\nimport type { SyncStepOneMessage } from \"./OutgoingMessages/SyncStepOneMessage.ts\";\nimport type { SyncStepTwoMessage } from \"./OutgoingMessages/SyncStepTwoMessage.ts\";\nimport type { UpdateMessage } from \"./OutgoingMessages/UpdateMessage.ts\";\n\nexport enum MessageType {\n\tSync = 0,\n\tAwareness = 1,\n\tAuth = 2,\n\tQueryAwareness = 3,\n\tStateless = 5,\n\tCLOSE = 7,\n\tSyncStatus = 8,\n\tPing = 9,\n\tPong = 10,\n}\n\nexport enum WebSocketStatus {\n\tConnecting = \"connecting\",\n\tConnected = \"connected\",\n\tDisconnected = \"disconnected\",\n}\n\nexport type AuthorizedScope = \"read-write\" | \"readonly\";\n\nexport interface OutgoingMessageInterface {\n\tencoder: Encoder;\n\ttype?: MessageType;\n}\n\nexport interface OutgoingMessageArguments {\n\tdocumentName: string;\n\ttoken: string;\n\tdocument: Y.Doc;\n\tawareness: Awareness;\n\tclients: number[];\n\tstates: Map<number, { [key: string]: any }>;\n\tupdate: any;\n\tpayload: string;\n\tencoder: Encoder;\n}\n\nexport interface Constructable<T> {\n\tnew (...args: any): T;\n}\n\nexport type ConstructableOutgoingMessage =\n\t| Constructable<AuthenticationMessage>\n\t| Constructable<AwarenessMessage>\n\t| Constructable<QueryAwarenessMessage>\n\t| Constructable<SyncStepOneMessage>\n\t| Constructable<SyncStepTwoMessage>\n\t| Constructable<UpdateMessage>;\n\nexport type onAuthenticationFailedParameters = {\n\treason: string;\n};\n\nexport type onAuthenticatedParameters = {\n\tscope: AuthorizedScope;\n};\n\nexport type onOpenParameters = {\n\tevent: Event;\n};\n\nexport type onMessageParameters = {\n\tevent: MessageEvent;\n\tmessage: IncomingMessage;\n};\n\nexport type onOutgoingMessageParameters = {\n\tmessage: OutgoingMessage;\n};\n\nexport type onStatusParameters = {\n\tstatus: WebSocketStatus;\n};\n\nexport type onSyncedParameters = {\n\tstate: boolean;\n};\n\nexport type onUnsyncedChangesParameters = {\n\tnumber: number;\n};\n\nexport type onDisconnectParameters = {\n\tevent: CloseEvent;\n};\n\nexport type onCloseParameters = {\n\tevent: CloseEvent;\n};\n\nexport type onAwarenessUpdateParameters = {\n\tstates: StatesArray;\n};\n\nexport type onAwarenessChangeParameters = {\n\tstates: StatesArray;\n};\n\nexport type onStatelessParameters = {\n\tpayload: string;\n};\n\nexport type StatesArray = { clientId: number; [key: string | number]: any }[];\n","import type { Encoder } from \"lib0/encoding\";\nimport { createEncoder, toUint8Array } from \"lib0/encoding\";\nimport type {\n\tMessageType,\n\tOutgoingMessageArguments,\n\tOutgoingMessageInterface,\n} from \"./types.ts\";\n\nexport class OutgoingMessage implements OutgoingMessageInterface {\n\tencoder: Encoder;\n\n\ttype?: MessageType;\n\n\tconstructor() {\n\t\tthis.encoder = createEncoder();\n\t}\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\treturn args.encoder;\n\t}\n\n\ttoUint8Array() {\n\t\treturn toUint8Array(this.encoder);\n\t}\n}\n","import * as encoding from \"lib0/encoding\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class CloseMessage extends OutgoingMessage {\n\ttype = MessageType.CLOSE;\n\n\tdescription = \"Ask the server to close the connection\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tencoding.writeVarString(this.encoder, args.documentName!);\n\t\tencoding.writeVarUint(this.encoder, this.type);\n\n\t\treturn this.encoder;\n\t}\n}\n","import { WsReadyStates } from \"@hocuspocus/common\";\nimport { retry } from \"@lifeomic/attempt\";\nimport { createDecoder, readVarString, readVarUint } from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport * as time from \"lib0/time\";\nimport EventEmitter from \"./EventEmitter.ts\";\nimport type { HocuspocusProvider } from \"./HocuspocusProvider.ts\";\nimport { IncomingMessage } from \"./IncomingMessage.ts\";\nimport { CloseMessage } from \"./OutgoingMessages/CloseMessage.ts\";\nimport {\n\tMessageType,\n\ttype onAwarenessChangeParameters,\n\ttype onAwarenessUpdateParameters,\n\ttype onCloseParameters,\n\ttype onDisconnectParameters,\n\ttype onMessageParameters,\n\ttype onOpenParameters,\n\ttype onOutgoingMessageParameters,\n\ttype onStatusParameters,\n\tWebSocketStatus,\n} from \"./types.ts\";\n\nexport type HocuspocusWebSocket = WebSocket & { identifier: string };\nexport type HocusPocusWebSocket = HocuspocusWebSocket;\n\nexport type HocuspocusProviderWebsocketConfiguration = Required<\n\tPick<CompleteHocuspocusProviderWebsocketConfiguration, \"url\">\n> &\n\tPartial<CompleteHocuspocusProviderWebsocketConfiguration>;\n\nexport interface CompleteHocuspocusProviderWebsocketConfiguration {\n\t/**\n\t * Whether to connect automatically when creating the provider instance. Default=true\n\t */\n\tautoConnect: boolean;\n\n\t/**\n\t * URL of your @hocuspocus/server instance\n\t */\n\turl: string;\n\n\t/**\n\t * By default, trailing slashes are removed from the URL. Set this to true\n\t * to preserve trailing slashes if your server configuration requires them.\n\t */\n\tpreserveTrailingSlash: boolean;\n\n\t/**\n\t * An optional WebSocket polyfill, for example for Node.js\n\t */\n\tWebSocketPolyfill: any;\n\n\t/**\n\t * Disconnect when no message is received for the defined amount of milliseconds.\n\t */\n\tmessageReconnectTimeout: number;\n\t/**\n\t * The delay between each attempt in milliseconds. You can provide a factor to have the delay grow exponentially.\n\t */\n\tdelay: number;\n\t/**\n\t * The initialDelay is the amount of time to wait before making the first attempt. This option should typically be 0 since you typically want the first attempt to happen immediately.\n\t */\n\tinitialDelay: number;\n\t/**\n\t * The factor option is used to grow the delay exponentially.\n\t */\n\tfactor: number;\n\t/**\n\t * The maximum number of attempts or 0 if there is no limit on number of attempts.\n\t */\n\tmaxAttempts: number;\n\t/**\n\t * minDelay is used to set a lower bound of delay when jitter is enabled. This property has no effect if jitter is disabled.\n\t */\n\tminDelay: number;\n\t/**\n\t * The maxDelay option is used to set an upper bound for the delay when factor is enabled. A value of 0 can be provided if there should be no upper bound when calculating delay.\n\t */\n\tmaxDelay: number;\n\t/**\n\t * If jitter is true then the calculated delay will be a random integer value between minDelay and the calculated delay for the current iteration.\n\t */\n\tjitter: boolean;\n\t/**\n\t * A timeout in milliseconds. If timeout is non-zero then a timer is set using setTimeout. If the timeout is triggered then future attempts will be aborted.\n\t */\n\ttimeout: number;\n\thandleTimeout: (() => Promise<unknown>) | null;\n\tonOpen: (data: onOpenParameters) => void;\n\tonConnect: () => void;\n\tonMessage: (data: onMessageParameters) => void;\n\tonOutgoingMessage: (data: onOutgoingMessageParameters) => void;\n\tonStatus: (data: onStatusParameters) => void;\n\tonDisconnect: (data: onDisconnectParameters) => void;\n\tonClose: (data: onCloseParameters) => void;\n\tonDestroy: () => void;\n\tonAwarenessUpdate: (data: onAwarenessUpdateParameters) => void;\n\tonAwarenessChange: (data: onAwarenessChangeParameters) => void;\n\n\t/**\n\t * Map of attached providers keyed by documentName.\n\t */\n\tproviderMap: Map<string, HocuspocusProvider>;\n}\n\nexport class HocuspocusProviderWebsocket extends EventEmitter {\n\tprivate static readonly DEDUPLICATABLE_TYPES = new Set([\n\t\tMessageType.Awareness,\n\t\tMessageType.QueryAwareness,\n\t]);\n\n\tprivate messageQueue: any[] = [];\n\n\tpublic configuration: CompleteHocuspocusProviderWebsocketConfiguration = {\n\t\turl: \"\",\n\t\tautoConnect: true,\n\t\tpreserveTrailingSlash: false,\n\t\t// @ts-expect-error\n\t\tdocument: undefined,\n\t\tWebSocketPolyfill: undefined,\n\t\t// TODO: this should depend on awareness.outdatedTime\n\t\tmessageReconnectTimeout: 30000,\n\t\t// 1 second\n\t\tdelay: 1000,\n\t\t// instant\n\t\tinitialDelay: 0,\n\t\t// double the delay each time\n\t\tfactor: 2,\n\t\t// unlimited retries\n\t\tmaxAttempts: 0,\n\t\t// wait at least 1 second\n\t\tminDelay: 1000,\n\t\t// at least every 30 seconds\n\t\tmaxDelay: 30000,\n\t\t// randomize\n\t\tjitter: true,\n\t\t// retry forever\n\t\ttimeout: 0,\n\t\tonOpen: () => null,\n\t\tonConnect: () => null,\n\t\tonMessage: () => null,\n\t\tonOutgoingMessage: () => null,\n\t\tonStatus: () => null,\n\t\tonDisconnect: () => null,\n\t\tonClose: () => null,\n\t\tonDestroy: () => null,\n\t\tonAwarenessUpdate: () => null,\n\t\tonAwarenessChange: () => null,\n\t\thandleTimeout: null,\n\t\tproviderMap: new Map(),\n\t};\n\n\twebSocket: HocusPocusWebSocket | null = null;\n\n\twebSocketHandlers: { [key: string]: any } = {};\n\n\tshouldConnect = true;\n\n\tstatus = WebSocketStatus.Disconnected;\n\n\tlastMessageReceived = 0;\n\n\tidentifier = 0;\n\n\tintervals: any = {\n\t\tconnectionChecker: null,\n\t};\n\n\tconnectionAttempt: {\n\t\tresolve: (value?: any) => void;\n\t\treject: (reason?: any) => void;\n\t} | null = null;\n\n\tconstructor(configuration: HocuspocusProviderWebsocketConfiguration) {\n\t\tsuper();\n\t\tthis.setConfiguration(configuration);\n\n\t\tthis.configuration.WebSocketPolyfill = configuration.WebSocketPolyfill\n\t\t\t? configuration.WebSocketPolyfill\n\t\t\t: WebSocket;\n\n\t\tthis.on(\"open\", this.configuration.onOpen);\n\t\tthis.on(\"open\", this.onOpen.bind(this));\n\t\tthis.on(\"connect\", this.configuration.onConnect);\n\t\tthis.on(\"message\", this.configuration.onMessage);\n\t\tthis.on(\"outgoingMessage\", this.configuration.onOutgoingMessage);\n\t\tthis.on(\"status\", this.configuration.onStatus);\n\t\tthis.on(\"disconnect\", this.configuration.onDisconnect);\n\t\tthis.on(\"close\", this.configuration.onClose);\n\t\tthis.on(\"destroy\", this.configuration.onDestroy);\n\t\tthis.on(\"awarenessUpdate\", this.configuration.onAwarenessUpdate);\n\t\tthis.on(\"awarenessChange\", this.configuration.onAwarenessChange);\n\n\t\tthis.on(\"close\", this.onClose.bind(this));\n\t\tthis.on(\"message\", this.onMessage.bind(this));\n\n\t\tthis.intervals.connectionChecker = setInterval(\n\t\t\tthis.checkConnection.bind(this),\n\t\t\tthis.configuration.messageReconnectTimeout / 10,\n\t\t);\n\n\t\tif (this.shouldConnect) {\n\t\t\tthis.connect();\n\t\t}\n\t}\n\n\treceivedOnOpenPayload?: Event | undefined = undefined;\n\n\tasync onOpen(event: Event) {\n\t\tthis.status = WebSocketStatus.Connected;\n\t\tthis.emit(\"status\", { status: WebSocketStatus.Connected });\n\n\t\tthis.cancelWebsocketRetry = undefined;\n\t\tthis.receivedOnOpenPayload = event;\n\t}\n\n\tattach(provider: HocuspocusProvider) {\n\t\tconst key = provider.effectiveName;\n\t\tconst existing = this.configuration.providerMap.get(key);\n\n\t\tif (existing && existing !== provider) {\n\t\t\t// Allow replacing a provider that hasn't authenticated (e.g., after auth failure retry)\n\t\t\tif (existing.isAuthenticated) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot attach two providers with the same effective name \"${key}\". ` +\n\t\t\t\t\t\t\"Use sessionAwareness: true to multiplex providers with the same document name.\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis.configuration.providerMap.set(key, provider);\n\n\t\tif (this.status === WebSocketStatus.Disconnected && this.shouldConnect) {\n\t\t\tthis.connect();\n\t\t}\n\n\t\tif (\n\t\t\tthis.receivedOnOpenPayload &&\n\t\t\tthis.status === WebSocketStatus.Connected\n\t\t) {\n\t\t\tprovider.onOpen(this.receivedOnOpenPayload);\n\t\t}\n\t}\n\n\tdetach(provider: HocuspocusProvider) {\n\t\tconst key = provider.effectiveName;\n\t\tif (this.configuration.providerMap.has(key)) {\n\t\t\tprovider.send(CloseMessage, {\n\t\t\t\tdocumentName: key,\n\t\t\t});\n\t\t\tthis.configuration.providerMap.delete(key);\n\t\t}\n\t}\n\n\tpublic setConfiguration(\n\t\tconfiguration: Partial<HocuspocusProviderWebsocketConfiguration> = {},\n\t): void {\n\t\tthis.configuration = { ...this.configuration, ...configuration };\n\n\t\tif (!this.configuration.autoConnect) {\n\t\t\tthis.shouldConnect = false;\n\t\t}\n\t}\n\n\tcancelWebsocketRetry?: () => void;\n\n\tasync connect() {\n\t\tif (this.status === WebSocketStatus.Connected) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Always cancel any previously initiated connection retryer instances\n\t\tif (this.cancelWebsocketRetry) {\n\t\t\tthis.cancelWebsocketRetry();\n\t\t\tthis.cancelWebsocketRetry = undefined;\n\t\t}\n\n\t\tthis.receivedOnOpenPayload = undefined;\n\t\tthis.shouldConnect = true;\n\n\t\tconst abortableRetry = () => {\n\t\t\tlet cancelAttempt = false;\n\n\t\t\tconst retryPromise = retry(this.createWebSocketConnection.bind(this), {\n\t\t\t\tdelay: this.configuration.delay,\n\t\t\t\tinitialDelay: this.configuration.initialDelay,\n\t\t\t\tfactor: this.configuration.factor,\n\t\t\t\tmaxAttempts: this.configuration.maxAttempts,\n\t\t\t\tminDelay: this.configuration.minDelay,\n\t\t\t\tmaxDelay: this.configuration.maxDelay,\n\t\t\t\tjitter: this.configuration.jitter,\n\t\t\t\ttimeout: this.configuration.timeout,\n\t\t\t\thandleTimeout: this.configuration.handleTimeout,\n\t\t\t\tbeforeAttempt: (context) => {\n\t\t\t\t\tif (!this.shouldConnect || cancelAttempt) {\n\t\t\t\t\t\tcontext.abort();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t}).catch((error: any) => {\n\t\t\t\t// If we aborted the connection attempt then don’t throw an error\n\t\t\t\t// ref: https://github.com/lifeomic/attempt/blob/master/src/index.ts#L136\n\t\t\t\tif (error && error.code !== \"ATTEMPT_ABORTED\") {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tretryPromise,\n\t\t\t\tcancelFunc: () => {\n\t\t\t\t\tcancelAttempt = true;\n\t\t\t\t},\n\t\t\t};\n\t\t};\n\n\t\tconst { retryPromise, cancelFunc } = abortableRetry();\n\t\tthis.cancelWebsocketRetry = cancelFunc;\n\n\t\treturn retryPromise;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n\tattachWebSocketListeners(ws: HocusPocusWebSocket, reject: Function) {\n\t\tconst { identifier } = ws;\n\t\tconst onMessageHandler = (payload: any) => this.emit(\"message\", payload);\n\t\tconst onCloseHandler = (payload: any) =>\n\t\t\tthis.emit(\"close\", { event: payload });\n\t\tconst onOpenHandler = (payload: any) => this.emit(\"open\", payload);\n\t\tconst onErrorHandler = (err: any) => {\n\t\t\treject(err);\n\t\t};\n\n\t\tthis.webSocketHandlers[identifier] = {\n\t\t\tmessage: onMessageHandler,\n\t\t\tclose: onCloseHandler,\n\t\t\topen: onOpenHandler,\n\t\t\terror: onErrorHandler,\n\t\t};\n\n\t\tconst handlers = this.webSocketHandlers[ws.identifier];\n\n\t\tObject.keys(handlers).forEach((name) => {\n\t\t\tws.addEventListener(name, handlers[name]);\n\t\t});\n\t}\n\n\tcleanupWebSocket() {\n\t\tif (!this.webSocket) {\n\t\t\treturn;\n\t\t}\n\t\tconst { identifier } = this.webSocket;\n\t\tconst handlers = this.webSocketHandlers[identifier];\n\n\t\tObject.keys(handlers).forEach((name) => {\n\t\t\tthis.webSocket?.removeEventListener(name, handlers[name]);\n\t\t\tdelete this.webSocketHandlers[identifier];\n\t\t});\n\t\tthis.webSocket.close();\n\t\tthis.webSocket = null;\n\t}\n\n\tcreateWebSocketConnection() {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tif (this.webSocket) {\n\t\t\t\tthis.messageQueue = [];\n\t\t\t\tthis.cleanupWebSocket();\n\t\t\t}\n\t\t\tthis.lastMessageReceived = 0;\n\t\t\tthis.identifier += 1;\n\n\t\t\t// Init the WebSocket connection\n\t\t\tconst ws = new this.configuration.WebSocketPolyfill(this.url);\n\t\t\tws.binaryType = \"arraybuffer\";\n\t\t\tws.identifier = this.identifier;\n\n\t\t\tthis.attachWebSocketListeners(ws, reject);\n\n\t\t\tthis.webSocket = ws;\n\n\t\t\t// Reset the status\n\t\t\tthis.status = WebSocketStatus.Connecting;\n\t\t\tthis.emit(\"status\", { status: WebSocketStatus.Connecting });\n\n\t\t\t// Store resolve/reject for later use\n\t\t\tthis.connectionAttempt = {\n\t\t\t\tresolve,\n\t\t\t\treject,\n\t\t\t};\n\t\t});\n\t}\n\n\tonMessage(event: MessageEvent) {\n\t\tthis.resolveConnectionAttempt();\n\n\t\tthis.lastMessageReceived = time.getUnixTime();\n\n\t\tconst data = new Uint8Array(event.data as ArrayBuffer);\n\n\t\t// Check for connection-level Ping message (no document name prefix)\n\t\t// Ping messages are sent as just the message type byte (length 1)\n\t\t// We check length to avoid confusing with regular messages that happen to have\n\t\t// a document name length of 9 as the first byte\n\t\tif (data.length === 1 && data[0] === MessageType.Ping) {\n\t\t\tthis.sendPong();\n\t\t\treturn;\n\t\t}\n\n\t\tconst message = new IncomingMessage(data);\n\t\tconst rawKey = message.peekVarString();\n\n\t\tconst provider = this.configuration.providerMap.get(rawKey);\n\t\tprovider?.onMessage(event);\n\t}\n\n\t/**\n\t * Send application-level Pong response to server Ping\n\t */\n\tprivate sendPong() {\n\t\tconst encoder = encoding.createEncoder();\n\t\tencoding.writeVarUint(encoder, MessageType.Pong);\n\t\tthis.send(encoding.toUint8Array(encoder));\n\t}\n\n\tresolveConnectionAttempt() {\n\t\tif (this.connectionAttempt) {\n\t\t\tthis.connectionAttempt.resolve();\n\t\t\tthis.connectionAttempt = null;\n\n\t\t\tthis.status = WebSocketStatus.Connected;\n\t\t\tthis.emit(\"status\", { status: WebSocketStatus.Connected });\n\t\t\tthis.emit(\"connect\");\n\t\t\tthis.messageQueue.forEach((message) => this.send(message));\n\t\t\tthis.messageQueue = [];\n\t\t}\n\t}\n\n\tstopConnectionAttempt() {\n\t\tthis.connectionAttempt = null;\n\t}\n\n\trejectConnectionAttempt() {\n\t\tthis.connectionAttempt?.reject();\n\t\tthis.connectionAttempt = null;\n\t}\n\n\tcloseTries = 0;\n\n\tcheckConnection() {\n\t\t// Don’t check the connection when it’s not even established\n\t\tif (this.status !== WebSocketStatus.Connected) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Don’t close the connection while waiting for the first message\n\t\tif (!this.lastMessageReceived) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Don’t close the connection when a message was received recently\n\t\tif (\n\t\t\tthis.configuration.messageReconnectTimeout >=\n\t\t\ttime.getUnixTime() - this.lastMessageReceived\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// No message received in a long time, not even your own\n\t\t// Awareness updates, which are updated every 15 seconds\n\t\t// if awareness is enabled.\n\t\tthis.closeTries += 1;\n\t\t// https://bugs.webkit.org/show_bug.cgi?id=247943\n\t\tif (this.closeTries > 2) {\n\t\t\tthis.onClose({\n\t\t\t\tevent: {\n\t\t\t\t\tcode: 4408,\n\t\t\t\t\treason: \"forced\",\n\t\t\t\t},\n\t\t\t});\n\t\t\tthis.closeTries = 0;\n\t\t} else {\n\t\t\tthis.webSocket?.close();\n\t\t\tthis.messageQueue = [];\n\t\t}\n\t}\n\n\tget serverUrl() {\n\t\tif (this.configuration.preserveTrailingSlash) {\n\t\t\treturn this.configuration.url;\n\t\t}\n\n\t\t// By default, ensure that the URL never ends with /\n\t\tlet url = this.configuration.url;\n\t\twhile (url[url.length - 1] === \"/\") {\n\t\t\turl = url.slice(0, url.length - 1);\n\t\t}\n\n\t\treturn url;\n\t}\n\n\tget url() {\n\t\treturn this.serverUrl;\n\t}\n\n\tdisconnect() {\n\t\tthis.shouldConnect = false;\n\n\t\tif (this.webSocket === null) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.webSocket.close();\n\t\t\tthis.messageQueue = [];\n\t\t} catch (e) {\n\t\t\tconsole.error(e);\n\t\t}\n\t}\n\n\tprivate parseQueuedMessage(\n\t\tmessage: Uint8Array,\n\t): { documentName: string; messageType: number } | null {\n\t\ttry {\n\t\t\tconst decoder = createDecoder(message);\n\t\t\tconst documentName = readVarString(decoder);\n\t\t\tconst messageType = readVarUint(decoder);\n\t\t\treturn { documentName, messageType };\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate addToQueue(message: any) {\n\t\tif (message instanceof Uint8Array) {\n\t\t\tconst parsed = this.parseQueuedMessage(message);\n\t\t\tif (\n\t\t\t\tparsed &&\n\t\t\t\tHocuspocusProviderWebsocket.DEDUPLICATABLE_TYPES.has(parsed.messageType)\n\t\t\t) {\n\t\t\t\tthis.messageQueue = this.messageQueue.filter((queued) => {\n\t\t\t\t\tif (!(queued instanceof Uint8Array)) return true;\n\t\t\t\t\tconst queuedParsed = this.parseQueuedMessage(queued);\n\t\t\t\t\tif (!queuedParsed) return true;\n\t\t\t\t\treturn !(\n\t\t\t\t\t\tqueuedParsed.documentName === parsed.documentName &&\n\t\t\t\t\t\tqueuedParsed.messageType === parsed.messageType\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthis.messageQueue.push(message);\n\t}\n\n\tsend(message: any) {\n\t\tif (this.webSocket?.readyState === WsReadyStates.Open) {\n\t\t\tthis.webSocket.send(message);\n\t\t} else {\n\t\t\tthis.addToQueue(message);\n\t\t}\n\t}\n\n\tonClose({ event }: onCloseParameters) {\n\t\tthis.closeTries = 0;\n\t\tthis.cleanupWebSocket();\n\n\t\tif (this.connectionAttempt) {\n\t\t\t// That connection attempt failed.\n\t\t\tthis.rejectConnectionAttempt();\n\t\t}\n\n\t\t// Let’s update the connection status.\n\t\tthis.status = WebSocketStatus.Disconnected;\n\t\tthis.emit(\"status\", { status: WebSocketStatus.Disconnected });\n\t\tthis.emit(\"disconnect\", { event });\n\n\t\t// trigger connect if no retry is running and we want to have a connection\n\t\tif (!this.cancelWebsocketRetry && this.shouldConnect) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.connect();\n\t\t\t}, this.configuration.delay);\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tthis.emit(\"destroy\");\n\n\t\tclearInterval(this.intervals.connectionChecker);\n\n\t\t// If there is still a connection attempt outstanding then we should stop\n\t\t// it before calling disconnect, otherwise it will be rejected in the onClose\n\t\t// handler and trigger a retry\n\t\tthis.stopConnectionAttempt();\n\n\t\tthis.disconnect();\n\n\t\tthis.removeAllListeners();\n\n\t\tthis.cleanupWebSocket();\n\t}\n}\n","import { type CloseEvent, readAuthMessage } from \"@hocuspocus/common\";\nimport { readVarInt, readVarString } from \"lib0/decoding\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport { messageYjsSyncStep2, readSyncMessage } from \"y-protocols/sync\";\nimport type { HocuspocusProvider } from \"./HocuspocusProvider.ts\";\nimport type { IncomingMessage } from \"./IncomingMessage.ts\";\nimport { OutgoingMessage } from \"./OutgoingMessage.ts\";\nimport { MessageType } from \"./types.ts\";\n\nexport class MessageReceiver {\n\tmessage: IncomingMessage;\n\n\tconstructor(message: IncomingMessage) {\n\t\tthis.message = message;\n\t}\n\n\tpublic apply(provider: HocuspocusProvider, emitSynced: boolean) {\n\t\tconst { message } = this;\n\t\tconst type = message.readVarUint();\n\n\t\tconst emptyMessageLength = message.length();\n\n\t\tswitch (type) {\n\t\t\tcase MessageType.Sync:\n\t\t\t\tthis.applySyncMessage(provider, emitSynced);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.Awareness:\n\t\t\t\tthis.applyAwarenessMessage(provider);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.Auth:\n\t\t\t\tthis.applyAuthMessage(provider);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.QueryAwareness:\n\t\t\t\tthis.applyQueryAwarenessMessage(provider);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.Stateless:\n\t\t\t\tprovider.receiveStateless(readVarString(message.decoder));\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.SyncStatus:\n\t\t\t\tthis.applySyncStatusMessage(\n\t\t\t\t\tprovider,\n\t\t\t\t\treadVarInt(message.decoder) === 1,\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase MessageType.CLOSE: {\n\t\t\t\t// eslint-disable-next-line no-case-declarations\n\t\t\t\tconst event: CloseEvent = {\n\t\t\t\t\tcode: 1000,\n\t\t\t\t\treason: readVarString(message.decoder),\n\t\t\t\t};\n\t\t\t\tprovider.onClose();\n\t\t\t\tprovider.configuration.onClose({ event });\n\t\t\t\tprovider.forwardClose({ event });\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tconsole.error(`Can’t apply message of unknown type: ${type}`);\n\t\t}\n\n\t\t// Reply\n\t\tif (message.length() > emptyMessageLength + 1) {\n\t\t\t// length of documentName (considered in emptyMessageLength plus length of yjs sync type, set in applySyncMessage)\n\t\t\t// @ts-expect-error\n\t\t\tprovider.send(OutgoingMessage, { encoder: message.encoder });\n\t\t}\n\t}\n\n\tprivate applySyncMessage(provider: HocuspocusProvider, emitSynced: boolean) {\n\t\tconst { message } = this;\n\n\t\tmessage.writeVarUint(MessageType.Sync);\n\n\t\t// Apply update\n\t\tconst syncMessageType = readSyncMessage(\n\t\t\tmessage.decoder,\n\t\t\tmessage.encoder,\n\t\t\tprovider.document,\n\t\t\tprovider,\n\t\t);\n\n\t\t// Synced once we receive Step2\n\t\tif (emitSynced && syncMessageType === messageYjsSyncStep2) {\n\t\t\tprovider.synced = true;\n\t\t}\n\t}\n\n\tapplySyncStatusMessage(provider: HocuspocusProvider, applied: boolean) {\n\t\tif (applied) {\n\t\t\tprovider.decrementUnsyncedChanges();\n\t\t}\n\t}\n\n\tprivate applyAwarenessMessage(provider: HocuspocusProvider) {\n\t\tif (!provider.awareness) return;\n\n\t\tconst { message } = this;\n\n\t\tawarenessProtocol.applyAwarenessUpdate(\n\t\t\tprovider.awareness,\n\t\t\tmessage.readVarUint8Array(),\n\t\t\tprovider,\n\t\t);\n\t}\n\n\tprivate applyAuthMessage(provider: HocuspocusProvider) {\n\t\tconst { message } = this;\n\n\t\treadAuthMessage(\n\t\t\tmessage.decoder,\n\t\t\tprovider.sendToken.bind(provider),\n\t\t\tprovider.permissionDeniedHandler.bind(provider),\n\t\t\tprovider.authenticatedHandler.bind(provider),\n\t\t);\n\t}\n\n\tprivate applyQueryAwarenessMessage(provider: HocuspocusProvider) {\n\t\tif (!provider.awareness) return;\n\n\t\tconst { message } = this;\n\n\t\tmessage.writeVarUint(MessageType.Awareness);\n\t\tmessage.writeVarUint8Array(\n\t\t\tawarenessProtocol.encodeAwarenessUpdate(\n\t\t\t\tprovider.awareness,\n\t\t\t\tArray.from(provider.awareness.getStates().keys()),\n\t\t\t),\n\t\t);\n\t}\n}\n","import type { Encoder } from \"lib0/encoding\";\nimport { toUint8Array } from \"lib0/encoding\";\nimport type { ConstructableOutgoingMessage } from \"./types.ts\";\n\nexport class MessageSender {\n\tencoder: Encoder;\n\n\tmessage: any;\n\n\tconstructor(Message: ConstructableOutgoingMessage, args: any = {}) {\n\t\tthis.message = new Message();\n\t\tthis.encoder = this.message.get(args);\n\t}\n\n\tcreate() {\n\t\treturn toUint8Array(this.encoder);\n\t}\n\n\tsend(webSocket: any) {\n\t\twebSocket?.send(this.create());\n\t}\n}\n","export const version: string =\n\t// @ts-expect-error - __HOCUSPOCUS_VERSION__ is replaced at build time by rolldown\n\ttypeof __HOCUSPOCUS_VERSION__ !== \"undefined\"\n\t\t? // @ts-expect-error - __HOCUSPOCUS_VERSION__ is replaced at build time by rolldown\n\t\t\t__HOCUSPOCUS_VERSION__\n\t\t: \"unknown\";\n","import { writeVarString, writeVarUint } from \"lib0/encoding\";\nimport { writeAuthentication } from \"@hocuspocus/common\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\nimport { version } from \"../version.ts\";\n\nexport class AuthenticationMessage extends OutgoingMessage {\n\ttype = MessageType.Auth;\n\n\tdescription = \"Authentication\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tif (typeof args.token === \"undefined\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"The authentication message requires `token` as an argument.\",\n\t\t\t);\n\t\t}\n\n\t\twriteVarString(this.encoder, args.documentName!);\n\t\twriteVarUint(this.encoder, this.type);\n\t\twriteAuthentication(this.encoder, args.token);\n\t\twriteVarString(this.encoder, version);\n\n\t\treturn this.encoder;\n\t}\n}\n","import * as encoding from \"lib0/encoding\";\nimport { encodeAwarenessUpdate } from \"y-protocols/awareness\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class AwarenessMessage extends OutgoingMessage {\n\ttype = MessageType.Awareness;\n\n\tdescription = \"Awareness states update\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tif (typeof args.awareness === \"undefined\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"The awareness message requires awareness as an argument\",\n\t\t\t);\n\t\t}\n\n\t\tif (typeof args.clients === \"undefined\") {\n\t\t\tthrow new Error(\"The awareness message requires clients as an argument\");\n\t\t}\n\n\t\tencoding.writeVarString(this.encoder, args.documentName!);\n\t\tencoding.writeVarUint(this.encoder, this.type);\n\n\t\tlet awarenessUpdate;\n\t\tif (args.states === undefined) {\n\t\t\tawarenessUpdate = encodeAwarenessUpdate(args.awareness, args.clients);\n\t\t} else {\n\t\t\tawarenessUpdate = encodeAwarenessUpdate(\n\t\t\t\targs.awareness,\n\t\t\t\targs.clients,\n\t\t\t\targs.states,\n\t\t\t);\n\t\t}\n\n\t\tencoding.writeVarUint8Array(this.encoder, awarenessUpdate);\n\n\t\treturn this.encoder;\n\t}\n}\n","import { writeVarString, writeVarUint } from \"lib0/encoding\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class StatelessMessage extends OutgoingMessage {\n\ttype = MessageType.Stateless;\n\n\tdescription = \"A stateless message\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\twriteVarString(this.encoder, args.documentName!);\n\t\twriteVarUint(this.encoder, this.type);\n\t\twriteVarString(this.encoder, args.payload ?? \"\");\n\n\t\treturn this.encoder;\n\t}\n}\n","import * as encoding from \"lib0/encoding\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class SyncStepOneMessage extends OutgoingMessage {\n\ttype = MessageType.Sync;\n\n\tdescription = \"First sync step\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\tif (typeof args.document === \"undefined\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"The sync step one message requires document as an argument\",\n\t\t\t);\n\t\t}\n\n\t\tencoding.writeVarString(this.encoder, args.documentName!);\n\t\tencoding.writeVarUint(this.encoder, this.type);\n\t\tsyncProtocol.writeSyncStep1(this.encoder, args.document);\n\n\t\treturn this.encoder;\n\t}\n}\n","import { writeVarString, writeVarUint } from \"lib0/encoding\";\nimport { writeUpdate } from \"y-protocols/sync\";\nimport type { OutgoingMessageArguments } from \"../types.ts\";\nimport { MessageType } from \"../types.ts\";\nimport { OutgoingMessage } from \"../OutgoingMessage.ts\";\n\nexport class UpdateMessage extends OutgoingMessage {\n\ttype = MessageType.Sync;\n\n\tdescription = \"A document update\";\n\n\tget(args: Partial<OutgoingMessageArguments>) {\n\t\twriteVarString(this.encoder, args.documentName!);\n\t\twriteVarUint(this.encoder, this.type);\n\n\t\twriteUpdate(this.encoder, args.update);\n\n\t\treturn this.encoder;\n\t}\n}\n","import {\n\tawarenessStatesToArray,\n\tmakeRoutingKey,\n\tparseRoutingKey,\n} from \"@hocuspocus/common\";\nimport { Awareness, removeAwarenessStates } from \"y-protocols/awareness\";\nimport * as Y from \"yjs\";\nimport EventEmitter from \"./EventEmitter.ts\";\nimport type { CompleteHocuspocusProviderWebsocketConfiguration } from \"./HocuspocusProviderWebsocket.ts\";\nimport { HocuspocusProviderWebsocket } from \"./HocuspocusProviderWebsocket.ts\";\nimport { IncomingMessage } from \"./IncomingMessage.ts\";\nimport { MessageReceiver } from \"./MessageReceiver.ts\";\nimport { MessageSender } from \"./MessageSender.ts\";\nimport { AuthenticationMessage } from \"./OutgoingMessages/AuthenticationMessage.ts\";\nimport { AwarenessMessage } from \"./OutgoingMessages/AwarenessMessage.ts\";\nimport { StatelessMessage } from \"./OutgoingMessages/StatelessMessage.ts\";\nimport { SyncStepOneMessage } from \"./OutgoingMessages/SyncStepOneMessage.ts\";\nimport { UpdateMessage } from \"./OutgoingMessages/UpdateMessage.ts\";\nimport type {\n\tAuthorizedScope,\n\tConstructableOutgoingMessage,\n\tonAuthenticatedParameters,\n\tonAuthenticationFailedParameters,\n\tonAwarenessChangeParameters,\n\tonAwarenessUpdateParameters,\n\tonCloseParameters,\n\tonDisconnectParameters,\n\tonMessageParameters,\n\tonOpenParameters,\n\tonOutgoingMessageParameters,\n\tonStatelessParameters,\n\tonStatusParameters,\n\tonSyncedParameters,\n\tonUnsyncedChangesParameters,\n} from \"./types.ts\";\n\nexport type HocuspocusProviderConfiguration = Required<\n\tPick<CompleteHocuspocusProviderConfiguration, \"name\">\n> &\n\tPartial<CompleteHocuspocusProviderConfiguration> &\n\t(\n\t\t| (Required<Pick<CompleteHocuspocusProviderWebsocketConfiguration, \"url\">> &\n\t\t\t\tPartial<\n\t\t\t\t\tPick<\n\t\t\t\t\t\tCompleteHocuspocusProviderWebsocketConfiguration,\n\t\t\t\t\t\t\"preserveTrailingSlash\"\n\t\t\t\t\t>\n\t\t\t\t>)\n\t\t| Required<\n\t\t\t\tPick<CompleteHocuspocusProviderConfiguration, \"websocketProvider\">\n\t\t >\n\t);\n\nexport interface CompleteHocuspocusProviderConfiguration {\n\t/**\n\t * The identifier/name of your document\n\t */\n\tname: string;\n\t/**\n\t * The actual Y.js document\n\t */\n\tdocument: Y.Doc;\n\n\t/**\n\t * An Awareness instance to keep the presence state of all clients.\n\t *\n\t * You can disable sharing awareness information by passing `null`.\n\t * Note that having no awareness information shared across all connections will break our ping checks\n\t * and thus trigger reconnects. You should always have at least one Provider with enabled awareness per\n\t * socket connection, or ensure that the Provider receives messages before running into `HocuspocusProviderWebsocket.messageReconnectTimeout`.\n\t */\n\tawareness: Awareness | null;\n\n\t/**\n\t * A token that’s sent to the backend for authentication purposes.\n\t */\n\ttoken: string | (() => string) | (() => Promise<string>) | null;\n\n\t/**\n\t * Hocuspocus websocket provider\n\t */\n\twebsocketProvider: HocuspocusProviderWebsocket;\n\n\t/**\n\t * Enable session-aware multiplexing. When true, the provider embeds a unique\n\t * sessionId in the documentName field of every message, allowing multiple\n\t * providers with the same document name on a single WebSocket connection.\n\t *\n\t * Only set this to `true` when connecting to a v4 server that does\n\t * support session awareness.\n\t *\n\t * Default: false\n\t */\n\tsessionAwareness: boolean;\n\n\t/**\n\t * Force syncing the document in the defined interval.\n\t */\n\tforceSyncInterval: false | number;\n\n\t/**\n\t * Batch outgoing document and awareness updates over a short window (in\n\t * milliseconds) instead of sending one message per change. During heavy\n\t * editing this drastically reduces the number of websocket messages: Yjs\n\t * updates collected in the window are merged with `Y.mergeUpdates` into a\n\t * single message, and awareness collapses to the latest state of each\n\t * changed client.\n\t *\n\t * The window is a fixed batch, not a resetting debounce, so the added\n\t * latency is capped at `flushDelay` even while the user keeps typing. Keep\n\t * it small (e.g. 500) to avoid delaying what other clients see.\n\t *\n\t * Set to `false` (the default) to send every change immediately.\n\t */\n\tflushDelay: false | number;\n\n\tonAuthenticated: (data: onAuthenticatedParameters) => void;\n\tonAuthenticationFailed: (data: onAuthenticationFailedParameters) => void;\n\tonOpen: (data: onOpenParameters) => void;\n\tonConnect: () => void;\n\tonStatus: (data: onStatusParameters) => void;\n\tonMessage: (data: onMessageParameters) => void;\n\tonOutgoingMessage: (data: onOutgoingMessageParameters) => void;\n\tonSynced: (data: onSyncedParameters) => void;\n\tonDisconnect: (data: onDisconnectParameters) => void;\n\tonClose: (data: onCloseParameters) => void;\n\tonDestroy: () => void;\n\tonAwarenessUpdate: (data: onAwarenessUpdateParameters) => void;\n\tonAwarenessChange: (data: onAwarenessChangeParameters) => void;\n\tonStateless: (data: onStatelessParameters) => void;\n\tonUnsyncedChanges: (data: onUnsyncedChangesParameters) => void;\n}\n\nexport class AwarenessError extends Error {\n\tcode = 1001;\n}\n\nexport class HocuspocusProvider extends EventEmitter {\n\tpublic configuration: CompleteHocuspocusProviderConfiguration = {\n\t\tname: \"\",\n\t\t// @ts-expect-error\n\t\tdocument: undefined,\n\t\t// @ts-expect-error\n\t\tawareness: undefined,\n\t\ttoken: null,\n\t\tsessionAwareness: false,\n\t\tforceSyncInterval: false,\n\t\tflushDelay: false,\n\t\tonAuthenticated: () => null,\n\t\tonAuthenticationFailed: () => null,\n\t\tonOpen: () => null,\n\t\tonConnect: () => null,\n\t\tonMessage: () => null,\n\t\tonOutgoingMessage: () => null,\n\t\tonSynced: () => null,\n\t\tonStatus: () => null,\n\t\tonDisconnect: () => null,\n\t\tonClose: () => null,\n\t\tonDestroy: () => null,\n\t\tonAwarenessUpdate: () => null,\n\t\tonAwarenessChange: () => null,\n\t\tonStateless: () => null,\n\t\tonUnsyncedChanges: () => null,\n\t};\n\n\tisSynced = false;\n\n\tunsyncedChanges = 0;\n\n\tisAuthenticated = false;\n\n\tauthorizedScope: AuthorizedScope | undefined = undefined;\n\n\t// @internal\n\tmanageSocket = false;\n\n\tprivate _isAttached = false;\n\n\t/**\n\t * Outgoing document updates buffered for the current `flushDelay` window.\n\t */\n\tprivate pendingUpdates: Uint8Array[] = [];\n\n\t/**\n\t * Awareness client ids whose latest state should be sent on the next flush.\n\t */\n\tprivate pendingAwarenessClients = new Set<number>();\n\n\tprivate flushTimeout: ReturnType<typeof setTimeout> | null = null;\n\n\t/**\n\t * Unique session identifier for this provider instance.\n\t * Used for multiplexing multiple providers with the same document name on a single WebSocket.\n\t */\n\tsessionId: string = Math.random().toString(36).slice(2);\n\n\t/**\n\t * The effective name used as the first VarString in messages.\n\t * When `sessionAwareness` is enabled, returns a composite key (documentName\\0sessionId).\n\t * Otherwise, returns the plain document name.\n\t */\n\tget effectiveName(): string {\n\t\treturn this.configuration.sessionAwareness\n\t\t\t? makeRoutingKey(this.configuration.name, this.sessionId)\n\t\t\t: this.configuration.name;\n\t}\n\n\tintervals: any = {\n\t\tforceSync: null,\n\t};\n\n\tconstructor(configuration: HocuspocusProviderConfiguration) {\n\t\tsuper();\n\t\tthis.setConfiguration(configuration);\n\n\t\tthis.configuration.document = configuration.document\n\t\t\t? configuration.document\n\t\t\t: new Y.Doc();\n\t\tthis.configuration.awareness =\n\t\t\tconfiguration.awareness !== undefined\n\t\t\t\t? configuration.awareness\n\t\t\t\t: new Awareness(this.document);\n\n\t\tthis.on(\"open\", this.configuration.onOpen);\n\t\tthis.on(\"message\", this.configuration.onMessage);\n\t\tthis.on(\"outgoingMessage\", this.configuration.onOutgoingMessage);\n\t\tthis.on(\"synced\", this.configuration.onSynced);\n\t\tthis.on(\"destroy\", this.configuration.onDestroy);\n\t\tthis.on(\"awarenessUpdate\", this.configuration.onAwarenessUpdate);\n\t\tthis.on(\"awarenessChange\", this.configuration.onAwarenessChange);\n\t\tthis.on(\"stateless\", this.configuration.onStateless);\n\t\tthis.on(\"unsyncedChanges\", this.configuration.onUnsyncedChanges);\n\n\t\tthis.on(\"authenticated\", this.configuration.onAuthenticated);\n\t\tthis.on(\"authenticationFailed\", this.configuration.onAuthenticationFailed);\n\n\t\tthis.awareness?.on(\"update\", () => {\n\t\t\tthis.emit(\"awarenessUpdate\", {\n\t\t\t\tstates: awarenessStatesToArray(this.awareness!.getStates()),\n\t\t\t});\n\t\t});\n\n\t\tthis.awareness?.on(\"change\", () => {\n\t\t\tthis.emit(\"awarenessChange\", {\n\t\t\t\tstates: awarenessStatesToArray(this.awareness!.getStates()),\n\t\t\t});\n\t\t});\n\n\t\tthis.document.on(\"update\", this.boundDocumentUpdateHandler);\n\t\tthis.awareness?.on(\"update\", this.boundAwarenessUpdateHandler);\n\n\t\tthis.registerEventListeners();\n\n\t\tif (\n\t\t\tthis.configuration.forceSyncInterval &&\n\t\t\ttypeof this.configuration.forceSyncInterval === \"number\"\n\t\t) {\n\t\t\tthis.intervals.forceSync = setInterval(\n\t\t\t\tthis.forceSync.bind(this),\n\t\t\t\tthis.configuration.forceSyncInterval,\n\t\t\t);\n\t\t}\n\n\t\tif (this.manageSocket) {\n\t\t\tthis.attach();\n\t\t}\n\t}\n\n\tboundDocumentUpdateHandler = this.documentUpdateHandler.bind(this);\n\n\tboundAwarenessUpdateHandler = this.awarenessUpdateHandler.bind(this);\n\n\tboundPageHide = this.pageHide.bind(this);\n\n\tboundOnOpen = this.onOpen.bind(this);\n\n\tboundOnClose = this.onClose.bind(this);\n\n\tforwardConnect = () => this.emit(\"connect\");\n\n\tforwardStatus = (e: onStatusParameters) => this.emit(\"status\", e);\n\n\tforwardClose = (e: onCloseParameters) => this.emit(\"close\", e);\n\n\tforwardDisconnect = (e: onDisconnectParameters) => this.emit(\"disconnect\", e);\n\n\tforwardDestroy = () => this.emit(\"destroy\");\n\n\tpublic setConfiguration(\n\t\tconfiguration: Partial<HocuspocusProviderConfiguration> = {},\n\t): void {\n\t\tif (!configuration.websocketProvider) {\n\t\t\tthis.manageSocket = true;\n\t\t\tthis.configuration.websocketProvider = new HocuspocusProviderWebsocket(\n\t\t\t\tconfiguration as CompleteHocuspocusProviderWebsocketConfiguration,\n\t\t\t);\n\t\t}\n\n\t\tthis.configuration = { ...this.configuration, ...configuration };\n\t}\n\n\tget document() {\n\t\treturn this.configuration.document;\n\t}\n\n\tpublic get isAttached() {\n\t\treturn this._isAttached;\n\t}\n\n\tget awareness() {\n\t\treturn this.configuration.awareness;\n\t}\n\n\tget hasUnsyncedChanges(): boolean {\n\t\treturn this.unsyncedChanges > 0;\n\t}\n\n\tprivate resetUnsyncedChanges() {\n\t\tthis.unsyncedChanges = 1;\n\t\tthis.emit(\"unsyncedChanges\", { number: this.unsyncedChanges });\n\t}\n\n\tincrementUnsyncedChanges() {\n\t\tthis.unsyncedChanges += 1;\n\t\tthis.emit(\"unsyncedChanges\", { number: this.unsyncedChanges });\n\t}\n\n\tdecrementUnsyncedChanges() {\n\t\tif (this.unsyncedChanges > 0) {\n\t\t\tthis.unsyncedChanges -= 1;\n\t\t}\n\n\t\tif (this.unsyncedChanges === 0) {\n\t\t\tthis.synced = true;\n\t\t}\n\n\t\tthis.emit(\"unsyncedChanges\", { number: this.unsyncedChanges });\n\t}\n\n\tforceSync() {\n\t\tthis.resetUnsyncedChanges();\n\n\t\tthis.send(SyncStepOneMessage, {\n\t\t\tdocument: this.document,\n\t\t\tdocumentName: this.effectiveName,\n\t\t});\n\t}\n\n\tpageHide() {\n\t\tif (this.awareness) {\n\t\t\tremoveAwarenessStates(\n\t\t\t\tthis.awareness,\n\t\t\t\t[this.document.clientID],\n\t\t\t\t\"page hide\",\n\t\t\t);\n\t\t}\n\t}\n\n\tregisterEventListeners() {\n\t\tif (typeof window === \"undefined\" || !(\"addEventListener\" in window)) {\n\t\t\treturn;\n\t\t}\n\n\t\twindow.addEventListener(\"pagehide\", this.boundPageHide);\n\t}\n\n\tsendStateless(payload: string) {\n\t\tthis.send(StatelessMessage, {\n\t\t\tdocumentName: this.effectiveName,\n\t\t\tpayload,\n\t\t});\n\t}\n\n\tasync sendToken() {\n\t\tlet token: string | null;\n\t\ttry {\n\t\t\ttoken = await this.getToken();\n\t\t} catch (error) {\n\t\t\tthis.permissionDeniedHandler(\n\t\t\t\t`Failed to get token during sendToken(): ${error}`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.send(AuthenticationMessage, {\n\t\t\ttoken: token ?? \"\",\n\t\t\tdocumentName: this.effectiveName,\n\t\t});\n\t}\n\n\tprivate get batchingEnabled(): boolean {\n\t\treturn (\n\t\t\t!!this.configuration.flushDelay &&\n\t\t\ttypeof this.configuration.flushDelay === \"number\"\n\t\t);\n\t}\n\n\tdocumentUpdateHandler(update: Uint8Array, origin: any) {\n\t\tif (origin === this) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.batchingEnabled) {\n\t\t\tthis.incrementUnsyncedChanges();\n\t\t\tthis.send(UpdateMessage, { update, documentName: this.effectiveName });\n\t\t\treturn;\n\t\t}\n\n\t\t// Count one outstanding change per batch: the server acks once per\n\t\t// merged message, so incrementing per buffered update would never balance.\n\t\tif (this.pendingUpdates.length === 0) {\n\t\t\tthis.incrementUnsyncedChanges();\n\t\t}\n\n\t\tthis.pendingUpdates.push(update);\n\t\tthis.scheduleFlush();\n\t}\n\n\tawarenessUpdateHandler({ added, updated, removed }: any, origin: any) {\n\t\tconst changedClients = added.concat(updated).concat(removed);\n\n\t\tif (!this.batchingEnabled) {\n\t\t\tthis.send(AwarenessMessage, {\n\t\t\t\tawareness: this.awareness,\n\t\t\t\tclients: changedClients,\n\t\t\t\tdocumentName: this.effectiveName,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const client of changedClients) {\n\t\t\tthis.pendingAwarenessClients.add(client);\n\t\t}\n\n\t\tthis.scheduleFlush();\n\t}\n\n\tprivate scheduleFlush() {\n\t\t// Fixed-window batching: the first pending change starts the timer and\n\t\t// everything until it fires is flushed together, so latency stays capped\n\t\t// at `flushDelay` instead of growing while the user keeps typing.\n\t\tif (this.flushTimeout !== null) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.flushTimeout = setTimeout(() => {\n\t\t\tthis.flushTimeout = null;\n\t\t\tthis.flushPendingUpdates();\n\t\t}, this.configuration.flushDelay as number);\n\t}\n\n\t/**\n\t * Send everything buffered for the current `flushDelay` window right away.\n\t * Buffered document updates are merged into a single message and awareness\n\t * collapses to the latest state of each changed client. Safe to call when\n\t * nothing is pending.\n\t */\n\tflushPendingUpdates() {\n\t\tif (this.flushTimeout !== null) {\n\t\t\tclearTimeout(this.flushTimeout);\n\t\t\tthis.flushTimeout = null;\n\t\t}\n\n\t\tif (this.pendingUpdates.length > 0) {\n\t\t\tconst update =\n\t\t\t\tthis.pendingUpdates.length === 1\n\t\t\t\t\t? this.pendingUpdates[0]\n\t\t\t\t\t: Y.mergeUpdates(this.pendingUpdates);\n\n\t\t\tthis.pendingUpdates = [];\n\t\t\tthis.send(UpdateMessage, { update, documentName: this.effectiveName });\n\t\t}\n\n\t\tif (this.pendingAwarenessClients.size > 0) {\n\t\t\tconst clients = Array.from(this.pendingAwarenessClients);\n\n\t\t\tthis.pendingAwarenessClients.clear();\n\t\t\tthis.send(AwarenessMessage, {\n\t\t\t\tawareness: this.awareness,\n\t\t\t\tclients,\n\t\t\t\tdocumentName: this.effectiveName,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Indicates whether a first handshake with the server has been established\n\t *\n\t * Note: this does not mean all updates from the client have been persisted to the backend. For this,\n\t * use `hasUnsyncedChanges`.\n\t */\n\tget synced(): boolean {\n\t\treturn this.isSynced;\n\t}\n\n\tset synced(state) {\n\t\tif (this.isSynced === state) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.isSynced = state;\n\n\t\tif (state) {\n\t\t\tthis.emit(\"synced\", { state });\n\t\t}\n\t}\n\n\treceiveStateless(payload: string) {\n\t\tthis.emit(\"stateless\", { payload });\n\t}\n\n\t// not needed, but provides backward compatibility with e.g. lexical/yjs\n\tasync connect() {\n\t\tif (this.manageSocket) {\n\t\t\treturn this.configuration.websocketProvider.connect();\n\t\t}\n\n\t\tconsole.warn(\n\t\t\t\"HocuspocusProvider::connect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.\",\n\t\t);\n\t}\n\n\tdisconnect() {\n\t\tif (this.manageSocket) {\n\t\t\treturn this.configuration.websocketProvider.disconnect();\n\t\t}\n\n\t\tconsole.warn(\n\t\t\t\"HocuspocusProvider::disconnect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.\",\n\t\t);\n\t}\n\n\tasync onOpen(event: Event) {\n\t\tthis.isAuthenticated = false;\n\n\t\tthis.emit(\"open\", { event });\n\t\tawait this.sendToken();\n\t\tthis.startSync();\n\t}\n\n\tasync getToken() {\n\t\tif (typeof this.configuration.token === \"function\") {\n\t\t\tconst token = await this.configuration.token();\n\t\t\treturn token;\n\t\t}\n\n\t\treturn this.configuration.token;\n\t}\n\n\tstartSync() {\n\t\tthis.resetUnsyncedChanges();\n\n\t\tthis.send(SyncStepOneMessage, {\n\t\t\tdocument: this.document,\n\t\t\tdocumentName: this.effectiveName,\n\t\t});\n\n\t\tif (this.awareness && this.awareness.getLocalState() !== null) {\n\t\t\tthis.send(AwarenessMessage, {\n\t\t\t\tawareness: this.awareness,\n\t\t\t\tclients: [this.document.clientID],\n\t\t\t\tdocumentName: this.effectiveName,\n\t\t\t});\n\t\t}\n\t}\n\n\tsend(message: ConstructableOutgoingMessage, args: any) {\n\t\tif (!this._isAttached) return;\n\n\t\tconst messageSender = new MessageSender(message, args);\n\n\t\tthis.emit(\"outgoingMessage\", { message: messageSender.message });\n\t\tmessageSender.send(this.configuration.websocketProvider);\n\t}\n\n\tonMessage(event: MessageEvent) {\n\t\tconst message = new IncomingMessage(event.data);\n\n\t\tconst rawKey = message.readVarString();\n\t\t// Extract actual documentName from potentially composite routing key\n\t\tconst { documentName } = parseRoutingKey(rawKey);\n\n\t\tmessage.writeVarString(this.effectiveName);\n\n\t\tthis.emit(\"message\", { event, message: new IncomingMessage(event.data) });\n\n\t\tnew MessageReceiver(message).apply(this, true);\n\t}\n\n\tonClose() {\n\t\tthis.isAuthenticated = false;\n\t\tthis.synced = false;\n\n\t\t// Drop anything buffered for batching; the reconnect sync handshake will\n\t\t// reconcile these changes from the document via state vectors.\n\t\tif (this.flushTimeout !== null) {\n\t\t\tclearTimeout(this.flushTimeout);\n\t\t\tthis.flushTimeout = null;\n\t\t}\n\t\tthis.pendingUpdates = [];\n\t\tthis.pendingAwarenessClients.clear();\n\n\t\t// update awareness (all users except local left)\n\t\tif (this.awareness) {\n\t\t\tremoveAwarenessStates(\n\t\t\t\tthis.awareness,\n\t\t\t\tArray.from(this.awareness.getStates().keys()).filter(\n\t\t\t\t\t(client) => client !== this.document.clientID,\n\t\t\t\t),\n\t\t\t\tthis,\n\t\t\t);\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tthis.emit(\"destroy\");\n\n\t\tif (this.intervals.forceSync) {\n\t\t\tclearInterval(this.intervals.forceSync);\n\t\t}\n\n\t\tif (this.awareness) {\n\t\t\tremoveAwarenessStates(\n\t\t\t\tthis.awareness,\n\t\t\t\t[this.document.clientID],\n\t\t\t\t\"provider destroy\",\n\t\t\t);\n\t\t\tthis.awareness.off(\"update\", this.boundAwarenessUpdateHandler);\n\t\t\tthis.awareness.destroy();\n\t\t}\n\n\t\t// Send any buffered updates before the socket is torn down. The websocket\n\t\t// safely queues the message if it is no longer open.\n\t\tthis.flushPendingUpdates();\n\n\t\tthis.document.off(\"update\", this.boundDocumentUpdateHandler);\n\n\t\tthis.removeAllListeners();\n\n\t\tthis.detach();\n\n\t\tif (this.manageSocket) {\n\t\t\tthis.configuration.websocketProvider.destroy();\n\t\t}\n\n\t\tif (typeof window === \"undefined\" || !(\"removeEventListener\" in window)) {\n\t\t\treturn;\n\t\t}\n\n\t\twindow.removeEventListener(\"pagehide\", this.boundPageHide);\n\t}\n\n\tdetach() {\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"connect\",\n\t\t\tthis.configuration.onConnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\"connect\", this.forwardConnect);\n\n\t\tthis.configuration.websocketProvider.off(\"status\", this.forwardStatus);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"status\",\n\t\t\tthis.configuration.onStatus,\n\t\t);\n\n\t\tthis.configuration.websocketProvider.off(\"open\", this.boundOnOpen);\n\t\tthis.configuration.websocketProvider.off(\"close\", this.boundOnClose);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"close\",\n\t\t\tthis.configuration.onClose,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\"close\", this.forwardClose);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"disconnect\",\n\t\t\tthis.configuration.onDisconnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"disconnect\",\n\t\t\tthis.forwardDisconnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\n\t\t\t\"destroy\",\n\t\t\tthis.configuration.onDestroy,\n\t\t);\n\t\tthis.configuration.websocketProvider.off(\"destroy\", this.forwardDestroy);\n\n\t\tthis.configuration.websocketProvider.detach(this);\n\n\t\tthis._isAttached = false;\n\t}\n\n\tattach() {\n\t\tif (this._isAttached) return;\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"connect\",\n\t\t\tthis.configuration.onConnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"connect\", this.forwardConnect);\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"status\",\n\t\t\tthis.configuration.onStatus,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"status\", this.forwardStatus);\n\n\t\tthis.configuration.websocketProvider.on(\"open\", this.boundOnOpen);\n\n\t\tthis.configuration.websocketProvider.on(\"close\", this.boundOnClose);\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"close\",\n\t\t\tthis.configuration.onClose,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"close\", this.forwardClose);\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"disconnect\",\n\t\t\tthis.configuration.onDisconnect,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"disconnect\",\n\t\t\tthis.forwardDisconnect,\n\t\t);\n\n\t\tthis.configuration.websocketProvider.on(\n\t\t\t\"destroy\",\n\t\t\tthis.configuration.onDestroy,\n\t\t);\n\t\tthis.configuration.websocketProvider.on(\"destroy\", this.forwardDestroy);\n\n\t\tthis.configuration.websocketProvider.attach(this);\n\n\t\tthis._isAttached = true;\n\t}\n\n\tpermissionDeniedHandler(reason: string) {\n\t\tthis.emit(\"authenticationFailed\", { reason });\n\t\tthis.isAuthenticated = false;\n\t}\n\n\tauthenticatedHandler(scope: string) {\n\t\tthis.isAuthenticated = true;\n\t\tthis.authorizedScope = scope as AuthorizedScope;\n\n\t\tthis.emit(\"authenticated\", { scope });\n\t}\n\n\tsetAwarenessField(key: string, value: any) {\n\t\tif (!this.awareness) {\n\t\t\tthrow new AwarenessError(\n\t\t\t\t`Cannot set awareness field \"${key}\" to ${JSON.stringify(value)}. You have disabled Awareness for this provider by explicitly passing awareness: null in the provider configuration.`,\n\t\t\t);\n\t\t}\n\t\tthis.awareness.setLocalStateField(key, value);\n\t}\n}\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -336,6 +336,21 @@ interface CompleteHocuspocusProviderConfiguration {
336
336
  * Force syncing the document in the defined interval.
337
337
  */
338
338
  forceSyncInterval: false | number;
339
+ /**
340
+ * Batch outgoing document and awareness updates over a short window (in
341
+ * milliseconds) instead of sending one message per change. During heavy
342
+ * editing this drastically reduces the number of websocket messages: Yjs
343
+ * updates collected in the window are merged with `Y.mergeUpdates` into a
344
+ * single message, and awareness collapses to the latest state of each
345
+ * changed client.
346
+ *
347
+ * The window is a fixed batch, not a resetting debounce, so the added
348
+ * latency is capped at `flushDelay` even while the user keeps typing. Keep
349
+ * it small (e.g. 500) to avoid delaying what other clients see.
350
+ *
351
+ * Set to `false` (the default) to send every change immediately.
352
+ */
353
+ flushDelay: false | number;
339
354
  onAuthenticated: (data: onAuthenticatedParameters) => void;
340
355
  onAuthenticationFailed: (data: onAuthenticationFailedParameters) => void;
341
356
  onOpen: (data: onOpenParameters) => void;
@@ -363,6 +378,15 @@ declare class HocuspocusProvider extends EventEmitter {
363
378
  authorizedScope: AuthorizedScope | undefined;
364
379
  manageSocket: boolean;
365
380
  private _isAttached;
381
+ /**
382
+ * Outgoing document updates buffered for the current `flushDelay` window.
383
+ */
384
+ private pendingUpdates;
385
+ /**
386
+ * Awareness client ids whose latest state should be sent on the next flush.
387
+ */
388
+ private pendingAwarenessClients;
389
+ private flushTimeout;
366
390
  /**
367
391
  * Unique session identifier for this provider instance.
368
392
  * Used for multiplexing multiple providers with the same document name on a single WebSocket.
@@ -403,12 +427,21 @@ declare class HocuspocusProvider extends EventEmitter {
403
427
  registerEventListeners(): void;
404
428
  sendStateless(payload: string): void;
405
429
  sendToken(): Promise<void>;
430
+ private get batchingEnabled();
406
431
  documentUpdateHandler(update: Uint8Array, origin: any): void;
407
432
  awarenessUpdateHandler({
408
433
  added,
409
434
  updated,
410
435
  removed
411
436
  }: any, origin: any): void;
437
+ private scheduleFlush;
438
+ /**
439
+ * Send everything buffered for the current `flushDelay` window right away.
440
+ * Buffered document updates are merged into a single message and awareness
441
+ * collapses to the latest state of each changed client. Safe to call when
442
+ * nothing is pending.
443
+ */
444
+ flushPendingUpdates(): void;
412
445
  /**
413
446
  * Indicates whether a first handshake with the server has been established
414
447
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hocuspocus/provider",
3
- "version": "4.2.0",
3
+ "version": "4.4.0",
4
4
  "description": "hocuspocus provider",
5
5
  "homepage": "https://hocuspocus.dev",
6
6
  "keywords": [
@@ -29,7 +29,7 @@
29
29
  "dist"
30
30
  ],
31
31
  "dependencies": {
32
- "@hocuspocus/common": "^4.2.0",
32
+ "@hocuspocus/common": "^4.4.0",
33
33
  "@lifeomic/attempt": "^3.0.2",
34
34
  "lib0": "^0.2.87"
35
35
  },
@@ -37,7 +37,7 @@
37
37
  "y-protocols": "^1.0.6",
38
38
  "yjs": "^13.6.8"
39
39
  },
40
- "gitHead": "94fa0c7114e69c3660b7bf621fe1fdfa6a358de9",
40
+ "gitHead": "3634ee9ad71f7c9800a500f2556e42b1d14cf203",
41
41
  "repository": {
42
42
  "url": "https://github.com/ueberdosis/hocuspocus"
43
43
  },
@@ -1,4 +1,8 @@
1
- import { awarenessStatesToArray, makeRoutingKey, parseRoutingKey } from "@hocuspocus/common";
1
+ import {
2
+ awarenessStatesToArray,
3
+ makeRoutingKey,
4
+ parseRoutingKey,
5
+ } from "@hocuspocus/common";
2
6
  import { Awareness, removeAwarenessStates } from "y-protocols/awareness";
3
7
  import * as Y from "yjs";
4
8
  import EventEmitter from "./EventEmitter.ts";
@@ -82,7 +86,7 @@ export interface CompleteHocuspocusProviderConfiguration {
82
86
  * sessionId in the documentName field of every message, allowing multiple
83
87
  * providers with the same document name on a single WebSocket connection.
84
88
  *
85
- * Only set this to `true` when connecting to a v4 server that does
89
+ * Only set this to `true` when connecting to a v4 server that does
86
90
  * support session awareness.
87
91
  *
88
92
  * Default: false
@@ -94,6 +98,22 @@ export interface CompleteHocuspocusProviderConfiguration {
94
98
  */
95
99
  forceSyncInterval: false | number;
96
100
 
101
+ /**
102
+ * Batch outgoing document and awareness updates over a short window (in
103
+ * milliseconds) instead of sending one message per change. During heavy
104
+ * editing this drastically reduces the number of websocket messages: Yjs
105
+ * updates collected in the window are merged with `Y.mergeUpdates` into a
106
+ * single message, and awareness collapses to the latest state of each
107
+ * changed client.
108
+ *
109
+ * The window is a fixed batch, not a resetting debounce, so the added
110
+ * latency is capped at `flushDelay` even while the user keeps typing. Keep
111
+ * it small (e.g. 500) to avoid delaying what other clients see.
112
+ *
113
+ * Set to `false` (the default) to send every change immediately.
114
+ */
115
+ flushDelay: false | number;
116
+
97
117
  onAuthenticated: (data: onAuthenticatedParameters) => void;
98
118
  onAuthenticationFailed: (data: onAuthenticationFailedParameters) => void;
99
119
  onOpen: (data: onOpenParameters) => void;
@@ -125,6 +145,7 @@ export class HocuspocusProvider extends EventEmitter {
125
145
  token: null,
126
146
  sessionAwareness: false,
127
147
  forceSyncInterval: false,
148
+ flushDelay: false,
128
149
  onAuthenticated: () => null,
129
150
  onAuthenticationFailed: () => null,
130
151
  onOpen: () => null,
@@ -155,6 +176,18 @@ export class HocuspocusProvider extends EventEmitter {
155
176
 
156
177
  private _isAttached = false;
157
178
 
179
+ /**
180
+ * Outgoing document updates buffered for the current `flushDelay` window.
181
+ */
182
+ private pendingUpdates: Uint8Array[] = [];
183
+
184
+ /**
185
+ * Awareness client ids whose latest state should be sent on the next flush.
186
+ */
187
+ private pendingAwarenessClients = new Set<number>();
188
+
189
+ private flushTimeout: ReturnType<typeof setTimeout> | null = null;
190
+
158
191
  /**
159
192
  * Unique session identifier for this provider instance.
160
193
  * Used for multiplexing multiple providers with the same document name on a single WebSocket.
@@ -355,23 +388,99 @@ export class HocuspocusProvider extends EventEmitter {
355
388
  });
356
389
  }
357
390
 
391
+ private get batchingEnabled(): boolean {
392
+ return (
393
+ !!this.configuration.flushDelay &&
394
+ typeof this.configuration.flushDelay === "number"
395
+ );
396
+ }
397
+
358
398
  documentUpdateHandler(update: Uint8Array, origin: any) {
359
399
  if (origin === this) {
360
400
  return;
361
401
  }
362
402
 
363
- this.incrementUnsyncedChanges();
364
- this.send(UpdateMessage, { update, documentName: this.effectiveName });
403
+ if (!this.batchingEnabled) {
404
+ this.incrementUnsyncedChanges();
405
+ this.send(UpdateMessage, { update, documentName: this.effectiveName });
406
+ return;
407
+ }
408
+
409
+ // Count one outstanding change per batch: the server acks once per
410
+ // merged message, so incrementing per buffered update would never balance.
411
+ if (this.pendingUpdates.length === 0) {
412
+ this.incrementUnsyncedChanges();
413
+ }
414
+
415
+ this.pendingUpdates.push(update);
416
+ this.scheduleFlush();
365
417
  }
366
418
 
367
419
  awarenessUpdateHandler({ added, updated, removed }: any, origin: any) {
368
420
  const changedClients = added.concat(updated).concat(removed);
369
421
 
370
- this.send(AwarenessMessage, {
371
- awareness: this.awareness,
372
- clients: changedClients,
373
- documentName: this.effectiveName,
374
- });
422
+ if (!this.batchingEnabled) {
423
+ this.send(AwarenessMessage, {
424
+ awareness: this.awareness,
425
+ clients: changedClients,
426
+ documentName: this.effectiveName,
427
+ });
428
+ return;
429
+ }
430
+
431
+ for (const client of changedClients) {
432
+ this.pendingAwarenessClients.add(client);
433
+ }
434
+
435
+ this.scheduleFlush();
436
+ }
437
+
438
+ private scheduleFlush() {
439
+ // Fixed-window batching: the first pending change starts the timer and
440
+ // everything until it fires is flushed together, so latency stays capped
441
+ // at `flushDelay` instead of growing while the user keeps typing.
442
+ if (this.flushTimeout !== null) {
443
+ return;
444
+ }
445
+
446
+ this.flushTimeout = setTimeout(() => {
447
+ this.flushTimeout = null;
448
+ this.flushPendingUpdates();
449
+ }, this.configuration.flushDelay as number);
450
+ }
451
+
452
+ /**
453
+ * Send everything buffered for the current `flushDelay` window right away.
454
+ * Buffered document updates are merged into a single message and awareness
455
+ * collapses to the latest state of each changed client. Safe to call when
456
+ * nothing is pending.
457
+ */
458
+ flushPendingUpdates() {
459
+ if (this.flushTimeout !== null) {
460
+ clearTimeout(this.flushTimeout);
461
+ this.flushTimeout = null;
462
+ }
463
+
464
+ if (this.pendingUpdates.length > 0) {
465
+ const update =
466
+ this.pendingUpdates.length === 1
467
+ ? this.pendingUpdates[0]
468
+ : Y.mergeUpdates(this.pendingUpdates);
469
+
470
+ this.pendingUpdates = [];
471
+ this.send(UpdateMessage, { update, documentName: this.effectiveName });
472
+ }
473
+
474
+ if (this.pendingAwarenessClients.size > 0) {
475
+ const clients = Array.from(this.pendingAwarenessClients);
476
+
477
+ this.pendingAwarenessClients.clear();
478
+ this.send(AwarenessMessage, {
479
+ awareness: this.awareness,
480
+ clients,
481
+ documentName: this.effectiveName,
482
+ });
483
+ }
375
484
  }
376
485
 
377
486
  /**
@@ -482,6 +591,15 @@ export class HocuspocusProvider extends EventEmitter {
482
591
  this.isAuthenticated = false;
483
592
  this.synced = false;
484
593
 
594
+ // Drop anything buffered for batching; the reconnect sync handshake will
595
+ // reconcile these changes from the document via state vectors.
596
+ if (this.flushTimeout !== null) {
597
+ clearTimeout(this.flushTimeout);
598
+ this.flushTimeout = null;
599
+ }
600
+ this.pendingUpdates = [];
601
+ this.pendingAwarenessClients.clear();
602
+
485
603
  // update awareness (all users except local left)
486
604
  if (this.awareness) {
487
605
  removeAwarenessStates(
@@ -511,6 +629,10 @@ export class HocuspocusProvider extends EventEmitter {
511
629
  this.awareness.destroy();
512
630
  }
513
631
 
632
+ // Send any buffered updates before the socket is torn down. The websocket
633
+ // safely queues the message if it is no longer open.
634
+ this.flushPendingUpdates();
635
+
514
636
  this.document.off("update", this.boundDocumentUpdateHandler);
515
637
 
516
638
  this.removeAllListeners();