UNPKG

codelabs.y-socket.io

Version:

Socket IO Connector for Yjs (Inspired by y-websocket)

1 lines 24.5 kB
{"version":3,"sources":["../src/client/provider.ts"],"sourcesContent":["import * as Y from 'yjs'\r\nimport * as bc from 'lib0/broadcastchannel'\r\nimport * as AwarenessProtocol from 'y-protocols/awareness'\r\nimport { Observable } from 'lib0/observable'\r\nimport { io, Socket } from 'socket.io-client'\r\nimport { AwarenessChange } from '../types'\r\n\r\n/**\r\n * SocketIOProvider instance configuration. Here you can configure:\r\n * - autoConnect: (Optional) Will try to connect to the server when the instance is created if true; otherwise you have to call `provider.connect()` manually\r\n * - awareness: (Optional) Give an existing awareness\r\n * - resyncInterval: (Optional) Specify the number of milliseconds to set an interval to synchronize the document,\r\n * if it is greater than 0 enable the synchronization interval (by default is -1)\r\n * - disableBc: (Optional) This boolean disable the broadcast channel functionality, by default is false (broadcast channel enabled)\r\n * - onConnect: (Optional) Set a callback that will triggered immediately when the socket is connected\r\n * - onDisconnect: (Optional) Set a callback that will triggered immediately when the socket is disconnected\r\n * - onConnectError: (Optional) Set a callback that will triggered immediately when the occurs a socket connection error\r\n */\r\nexport interface ProviderConfiguration {\r\n /**\r\n * (Optional) This boolean specify if the provider should connect when the instance is created, by default is true\r\n */\r\n autoConnect?: boolean\r\n /**\r\n * (Optional) An existent awareness, by default is a new AwarenessProtocol.Awareness instance\r\n */\r\n awareness?: AwarenessProtocol.Awareness\r\n /**\r\n * (optional) Specify the number of milliseconds to synchronize, by default is -1 (this disable resync interval)\r\n */\r\n resyncInterval?: number\r\n /**\r\n * (Optional) This boolean disable the broadcast channel functionality, by default is false (broadcast channel enabled)\r\n */\r\n disableBc?: boolean\r\n /**\r\n * (Optional) Add the authentication data\r\n */\r\n auth?: { [key: string]: any }\r\n /**\r\n * (Optional) Set the socket.io parser\r\n * @see https://socket.io/docs/v4/server-initialization/#parser\r\n */\r\n parser?: any\r\n}\r\n\r\n/**\r\n * The socket io provider class to sync a document\r\n */\r\nexport class SocketIOProvider extends Observable<string> {\r\n /**\r\n * The connection url to server. Example: `ws://localhost:3001`\r\n * @type {string}\r\n */\r\n private readonly _url: string\r\n /**\r\n * The name of the document room\r\n * @type {string}\r\n */\r\n public roomName: string\r\n /**\r\n * The broadcast channel room\r\n * @type {string}\r\n * @private\r\n */\r\n private readonly _broadcastChannel: string\r\n /**\r\n * The socket connection\r\n * @type {Socket}\r\n */\r\n public socket: Socket\r\n /**\r\n * The yjs document\r\n * @type {Y.Doc}\r\n */\r\n public doc: Y.Doc\r\n /**\r\n * The awareness\r\n * @type {AwarenessProtocol.Awareness}\r\n */\r\n public awareness: AwarenessProtocol.Awareness\r\n /**\r\n * Disable broadcast channel, by default is false\r\n * @type {boolean}\r\n */\r\n public disableBc: boolean\r\n /**\r\n * The broadcast channel connection status indicator\r\n * @type {boolean}\r\n */\r\n public bcconnected: boolean = false\r\n /**\r\n * The document's sync status indicator\r\n * @type {boolean}\r\n * @private\r\n */\r\n private _synced: boolean = false\r\n /**\r\n * Interval to emit `sync-step-1` to sync changes\r\n * @type {NodeJS.Timer | null}\r\n * @private\r\n */\r\n private resyncInterval: NodeJS.Timer | null = null\r\n\r\n /**\r\n * SocketIOProvider constructor\r\n * @constructor\r\n * @param {string} url The connection url from server\r\n * @param {string} roomName The document's room name\r\n * @param {Y.Doc} doc The yjs document\r\n * @param {ProviderConfiguration} options Configuration options to the SocketIOProvider\r\n */\r\n constructor (url: string, roomName: string, doc: Y.Doc = new Y.Doc(), {\r\n autoConnect = true,\r\n awareness = new AwarenessProtocol.Awareness(doc),\r\n resyncInterval = -1,\r\n disableBc = false,\r\n auth = {},\r\n parser = null\r\n }: ProviderConfiguration) {\r\n super()\r\n while (url[url.length - 1] === '/') {\r\n url = url.slice(0, url.length - 1)\r\n }\r\n this._url = url\r\n this.roomName = roomName\r\n this.doc = doc\r\n this.awareness = awareness\r\n\r\n this._broadcastChannel = `${url}/${roomName}`\r\n this.disableBc = disableBc\r\n\r\n this.socket = io(`${this.url}/yjs|${roomName}`, {\r\n autoConnect: false,\r\n transports: ['websocket'],\r\n forceNew: true,\r\n auth: auth,\r\n parser: parser\r\n })\r\n\r\n this.doc.on('update', this.onUpdateDoc)\r\n\r\n this.socket.on('connect', () => this.onSocketConnection(resyncInterval))\r\n\r\n this.socket.on('disconnect', (event) => this.onSocketDisconnection(event))\r\n\r\n this.socket.on('connect_error', (error) => this.onSocketConnectionError(error))\r\n\r\n this.initSyncListeners()\r\n\r\n this.initAwarenessListeners()\r\n\r\n this.initSystemListeners()\r\n\r\n awareness.on('update', this.awarenessUpdate)\r\n\r\n if (autoConnect) this.connect()\r\n }\r\n\r\n /**\r\n * Broadcast channel room getter\r\n * @type {string}\r\n */\r\n public get broadcastChannel (): string {\r\n return this._broadcastChannel\r\n }\r\n\r\n /**\r\n * URL getter\r\n * @type {string}\r\n */\r\n public get url (): string {\r\n return this._url\r\n }\r\n\r\n /**\r\n * Synchronized state flag getter\r\n * @type {boolean}\r\n */\r\n public get synced (): boolean {\r\n return this._synced\r\n }\r\n\r\n /**\r\n * Synchronized state flag setter\r\n */\r\n public set synced (state) {\r\n if (this._synced !== state) {\r\n this._synced = state\r\n this.emit('synced', [state])\r\n this.emit('sync', [state])\r\n }\r\n }\r\n\r\n /**\r\n * This function initializes the socket event listeners to synchronize document changes.\r\n *\r\n * The synchronization protocol is as follows:\r\n * - A server emits the sync step one event (`sync-step-1`) which sends the document as a state vector\r\n * and the sync step two callback as an acknowledgment according to the socket io acknowledgments.\r\n * - When the client receives the `sync-step-1` event, it executes the `syncStep2` acknowledgment callback and sends\r\n * the difference between the received state vector and the local document (this difference is called an update).\r\n * - The second step of the sync is to apply the update sent in the `syncStep2` callback parameters from the client\r\n * to the document on the server side.\r\n * - There is another event (`sync-update`) that is emitted from the server, which sends an update for the document,\r\n * and when the client receives this event, it applies the received update to the local document.\r\n * - When an update is applied to a document, it will fire the document's \"update\" event, which\r\n * sends the update to the server.\r\n * @type {() => void}\r\n * @private\r\n */\r\n private readonly initSyncListeners = (): void => {\r\n this.socket.on('sync-step-1', (stateVector: ArrayBuffer, syncStep2: (update: Uint8Array) => void) => {\r\n syncStep2(Y.encodeStateAsUpdate(this.doc, new Uint8Array(stateVector)))\r\n this.synced = true\r\n })\r\n\r\n this.socket.on('sync-update', this.onSocketSyncUpdate)\r\n }\r\n\r\n /**\r\n * This function initializes socket event listeners to synchronize awareness changes.\r\n *\r\n * The awareness protocol is as follows:\r\n * - The server emits the `awareness-update` event by sending the awareness update.\r\n * - The client receives that event and applies the received update to the local awareness.\r\n * - When an update is applied to awareness, the awareness \"update\" event will fire, which\r\n * sends the update to the server.\r\n * @type {() => void}\r\n * @private\r\n */\r\n private readonly initAwarenessListeners = (): void => {\r\n this.socket.on('awareness-update', (update: ArrayBuffer) => {\r\n AwarenessProtocol.applyAwarenessUpdate(this.awareness, new Uint8Array(update), this)\r\n })\r\n }\r\n\r\n /**\r\n * This function initialize the window or process events listener. Specifically set ups the\r\n * window `beforeunload` and process `exit` events to remove the client from the awareness.\r\n * @type {() => void}\r\n */\r\n private readonly initSystemListeners = (): void => {\r\n if (typeof window !== 'undefined') window.addEventListener('beforeunload', this.beforeUnloadHandler)\r\n else if (typeof process !== 'undefined') process.on('exit', this.beforeUnloadHandler)\r\n }\r\n\r\n /**\r\n * Connect provider's socket\r\n * @type {() => void}\r\n */\r\n public connect (): void {\r\n if (!this.socket.connected) {\r\n this.emit('status', [{ status: 'connecting' }])\r\n this.socket.connect()\r\n if (!this.disableBc) this.connectBc()\r\n this.synced = false\r\n }\r\n }\r\n\r\n /**\r\n * This function runs when the socket connects and reconnects and emits the `sync-step-1`\r\n * and `awareness-update` socket events to start synchronization.\r\n *\r\n * Also starts the resync interval if is enabled.\r\n * @private\r\n * @param {() => void | Promise<void>} onConnect (Optional) A callback that will be triggered every time that socket is connected or reconnected\r\n * @param {number} resyncInterval (Optional) A number of milliseconds for interval of synchronize\r\n * @type {(onConnect: () => void | Promise<void>, resyncInterval: number = -1) => void}\r\n */\r\n private readonly onSocketConnection = (resyncInterval: ProviderConfiguration['resyncInterval'] = -1): void => {\r\n this.emit('status', [{ status: 'connected' }])\r\n this.socket.emit('sync-step-1', Y.encodeStateVector(this.doc), (update: Uint8Array) => {\r\n Y.applyUpdate(this.doc, new Uint8Array(update), this)\r\n })\r\n if (this.awareness.getLocalState() !== null) this.socket.emit('awareness-update', AwarenessProtocol.encodeAwarenessUpdate(this.awareness, [this.doc.clientID]))\r\n if (resyncInterval > 0) {\r\n this.resyncInterval = setInterval(() => {\r\n if (this.socket.disconnected) return\r\n this.socket.emit('sync-step-1', Y.encodeStateVector(this.doc), (update: Uint8Array) => {\r\n Y.applyUpdate(this.doc, new Uint8Array(update), this)\r\n })\r\n }, resyncInterval)\r\n }\r\n }\r\n\r\n /**\r\n * Disconnect provider's socket\r\n * @type {() => void}\r\n */\r\n public disconnect (): void {\r\n if (this.socket.connected) {\r\n this.disconnectBc()\r\n this.socket.disconnect()\r\n }\r\n }\r\n\r\n /**\r\n * This function runs when the socket is disconnected and emits the socket event `awareness-update`\r\n * which removes this client from awareness.\r\n * @private\r\n * @param {Socket.DisconnectReason} event The reason of the socket disconnection\r\n * @param {() => void | Promise<void>} onDisconnect (Optional) A callback that will be triggered every time that socket is disconnected\r\n * @type {(event: Socket.DisconnectReason, onDisconnect: () => void | Promise<void>) => void}\r\n */\r\n private readonly onSocketDisconnection = (event: Socket.DisconnectReason): void => {\r\n this.emit('connection-close', [event, this])\r\n this.synced = false\r\n AwarenessProtocol.removeAwarenessStates(this.awareness, Array.from(this.awareness.getStates().keys()).filter(client => client !== this.doc.clientID), this)\r\n this.emit('status', [{ status: 'disconnected' }])\r\n }\r\n\r\n /**\r\n * This function is executed when the socket connection fails.\r\n * @param {Error} error The error in the connection\r\n * @param {(error: Error) => void | Promise<void>} onConnectError (Optional) A callback that will be triggered every time that socket has a connection error\r\n * @type {(error: Error, onConnectError: (error: Error) => void | Promise<void>) => void}\r\n */\r\n private readonly onSocketConnectionError = (error: Error): void => {\r\n this.emit('connection-error', [error, this])\r\n }\r\n\r\n /**\r\n * Destroy the provider. This method clears the document, awareness, and window/process listeners and disconnects the socket.\r\n * @type {() => void}\r\n */\r\n public destroy (): void {\r\n if (this.resyncInterval != null) clearInterval(this.resyncInterval)\r\n this.disconnect()\r\n if (typeof window !== 'undefined') window.removeEventListener('beforeunload', this.beforeUnloadHandler)\r\n else if (typeof process !== 'undefined') process.off('exit', this.beforeUnloadHandler)\r\n this.awareness.off('update', this.awarenessUpdate)\r\n this.doc.off('update', this.onUpdateDoc)\r\n super.destroy()\r\n }\r\n\r\n /**\r\n * This function is executed when the document is updated, if the instance that\r\n * emit the change is not this, it emit the changes by socket and broadcast channel.\r\n * @private\r\n * @param {Uint8Array} update Document update\r\n * @param {SocketIOProvider} origin The SocketIOProvider instance that emits the change.\r\n * @type {(update: Uint8Array, origin: SocketIOProvider) => void}\r\n */\r\n private readonly onUpdateDoc = (update: Uint8Array, origin: SocketIOProvider): void => {\r\n if (origin !== this) {\r\n this.socket.emit('sync-update', update)\r\n if (this.bcconnected) {\r\n bc.publish(this._broadcastChannel, {\r\n type: 'sync-update',\r\n data: update\r\n }, this)\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * This function is called when the server emits the `sync-update` event and applies the received update to the local document.\r\n * @private\r\n * @param {Uint8Array}update A document update received by the `sync-update` socket event\r\n * @type {(update: Uint8Array) => void}\r\n */\r\n private readonly onSocketSyncUpdate = (update: ArrayBuffer): void => {\r\n Y.applyUpdate(this.doc, new Uint8Array(update), this)\r\n }\r\n\r\n /**\r\n * This function is executed when the local awareness changes and this broadcasts the changes per socket and broadcast channel.\r\n * @private\r\n * @param {{ added: number[], updated: number[], removed: number[] }} awarenessChanges The clients added, updated and removed\r\n * @param {SocketIOProvider | null} origin The SocketIOProvider instance that emits the change.\r\n * @type {({ added, updated, removed }: { added: number[], updated: number[], removed: number[] }, origin: SocketIOProvider | null) => void}\r\n */\r\n private readonly awarenessUpdate = ({ added, updated, removed }: AwarenessChange, origin: SocketIOProvider | null): void => {\r\n const changedClients = added.concat(updated).concat(removed)\r\n this.socket.emit('awareness-update', AwarenessProtocol.encodeAwarenessUpdate(this.awareness, changedClients))\r\n if (this.bcconnected) {\r\n bc.publish(this._broadcastChannel, {\r\n type: 'awareness-update',\r\n data: AwarenessProtocol.encodeAwarenessUpdate(this.awareness, changedClients)\r\n }, this)\r\n }\r\n }\r\n\r\n /**\r\n * This function is executed when the windows will be unloaded or the process will be closed and this\r\n * will remove the local client from awareness.\r\n * @private\r\n * @type {() => void}\r\n */\r\n private readonly beforeUnloadHandler = (): void => {\r\n AwarenessProtocol.removeAwarenessStates(this.awareness, [this.doc.clientID], 'window unload')\r\n }\r\n\r\n /**\r\n * This function subscribes the provider to the broadcast channel and initiates synchronization by broadcast channel.\r\n * @type {() => void}\r\n */\r\n private readonly connectBc = (): void => {\r\n if (!this.bcconnected) {\r\n bc.subscribe(this._broadcastChannel, this.onBroadcastChannelMessage)\r\n this.bcconnected = true\r\n }\r\n bc.publish(this._broadcastChannel, { type: 'sync-step-1', data: Y.encodeStateVector(this.doc) }, this)\r\n bc.publish(this._broadcastChannel, { type: 'sync-step-2', data: Y.encodeStateAsUpdate(this.doc) }, this)\r\n bc.publish(this._broadcastChannel, { type: 'query-awareness', data: null }, this)\r\n bc.publish(this._broadcastChannel, { type: 'awareness-update', data: AwarenessProtocol.encodeAwarenessUpdate(this.awareness, [this.doc.clientID]) }, this)\r\n }\r\n\r\n /**\r\n * This function unsubscribes the provider from the broadcast channel and before unsubscribing, updates the awareness.\r\n * @type {() => void}\r\n */\r\n private readonly disconnectBc = (): void => {\r\n bc.publish(this._broadcastChannel, {\r\n type: 'awareness-update',\r\n data: AwarenessProtocol.encodeAwarenessUpdate(this.awareness, [this.doc.clientID], new Map())\r\n }, this)\r\n if (this.bcconnected) {\r\n bc.unsubscribe(this._broadcastChannel, this.onBroadcastChannelMessage)\r\n this.bcconnected = false\r\n }\r\n }\r\n\r\n /**\r\n * This method handles messages received by the broadcast channel and responds to them.\r\n * @param {{ type: string, data: any }} message The object message received by broadcast channel\r\n * @param {SocketIOProvider} origin The SocketIOProvider instance that emits the change\r\n * @type {(message: { type: string, data: any }, origin: SocketIOProvider) => void}\r\n */\r\n private readonly onBroadcastChannelMessage = (message: { type: string, data: any }, origin: SocketIOProvider): void => {\r\n if (origin !== this && message.type.length > 0) {\r\n switch (message.type) {\r\n case 'sync-step-1':\r\n bc.publish(this._broadcastChannel, {\r\n type: 'sync-step-2',\r\n data: Y.encodeStateAsUpdate(this.doc, message.data)\r\n }, this)\r\n break\r\n\r\n case 'sync-step-2':\r\n Y.applyUpdate(this.doc, new Uint8Array(message.data), this)\r\n break\r\n\r\n case 'sync-update':\r\n Y.applyUpdate(this.doc, new Uint8Array(message.data), this)\r\n break\r\n\r\n case 'query-awareness':\r\n bc.publish(this._broadcastChannel, {\r\n type: 'awareness-update',\r\n data: AwarenessProtocol.encodeAwarenessUpdate(this.awareness, Array.from(this.awareness.getStates().keys()))\r\n }, this)\r\n break\r\n\r\n case 'awareness-update':\r\n AwarenessProtocol.applyAwarenessUpdate(this.awareness, new Uint8Array(message.data), this)\r\n break\r\n\r\n default:\r\n break\r\n }\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":["Y","bc","AwarenessProtocol","Observable","io","SocketIOProvider","url","roomName","doc","autoConnect","awareness","resyncInterval","disableBc","auth","parser","stateVector","syncStep2","update","event","client","error","origin","added","updated","removed","changedClients","message","state"]}