From de18196fd819fcd9f42d8361beee127f1cb87c96 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sat, 16 Jul 2022 14:02:03 +0100 Subject: [PATCH] chore: Upgrade socket.io (#3697) * Upgrade wip * tsc * tsc * fix: Missing authenticated message --- app/components/SocketProvider.tsx | 14 +- package.json | 10 +- server/services/websockets.ts | 155 +++++++---------- server/typings/index.d.ts | 2 - server/typings/socketio-auth.d.ts | 28 --- server/typings/socketio-redis.d.ts | 12 -- yarn.lock | 264 +++++++++++------------------ 7 files changed, 164 insertions(+), 321 deletions(-) delete mode 100644 server/typings/socketio-auth.d.ts delete mode 100644 server/typings/socketio-redis.d.ts diff --git a/app/components/SocketProvider.tsx b/app/components/SocketProvider.tsx index 9c18da302..26f2d7bd2 100644 --- a/app/components/SocketProvider.tsx +++ b/app/components/SocketProvider.tsx @@ -3,23 +3,17 @@ import { find } from "lodash"; import { observable } from "mobx"; import { observer } from "mobx-react"; import * as React from "react"; -import io from "socket.io-client"; +import { io, Socket } from "socket.io-client"; import RootStore from "~/stores/RootStore"; import withStores from "~/components/withStores"; import { AuthorizationError, NotFoundError } from "~/utils/errors"; import { getVisibilityListener, getPageVisible } from "~/utils/pageVisibility"; -type SocketWithAuthentication = { +type SocketWithAuthentication = Socket & { authenticated?: boolean; - disconnected: boolean; - disconnect: () => void; - close: () => void; - on: (event: string, callback: (data: any) => void) => void; - emit: (event: string, data: any) => void; - io: any; }; -export const SocketContext: any = React.createContext( +export const SocketContext = React.createContext( null ); @@ -99,7 +93,7 @@ class SocketProvider extends React.Component { // on reconnection, reset the transports option, as the Websocket // connection may have failed (caused by proxy, firewall, browser, ...) - this.socket.on("reconnect_attempt", () => { + this.socket.io.on("reconnect_attempt", () => { if (this.socket) { this.socket.io.opts.transports = auth?.team?.domain ? ["websocket"] diff --git a/package.json b/package.json index 5bc71e35e..f616b9635 100644 --- a/package.json +++ b/package.json @@ -132,8 +132,8 @@ "mobx": "^4.15.4", "mobx-react": "^6.3.1", "natural-sort": "^1.0.0", - "nodemailer": "^6.6.1", "node-fetch": "2.6.7", + "nodemailer": "^6.6.1", "outline-icons": "^1.43.1", "oy-vey": "^0.10.0", "passport": "^0.4.1", @@ -194,8 +194,9 @@ "slug": "^4.0.4", "slugify": "^1.6.5", "smooth-scroll-into-view-if-needed": "^1.1.32", - "socket.io": "^2.4.0", - "socket.io-redis": "^5.4.0", + "socket.io": "^3.1.2", + "socket.io-client": "^3.1.3", + "socket.io-redis": "^6.1.0", "stoppable": "^1.1.0", "string-replace-to-array": "^1.0.3", "styled-components": "^5.2.3", @@ -279,8 +280,6 @@ "@types/semver": "^7.3.9", "@types/sequelize": "^4.28.10", "@types/slug": "^5.0.2", - "@types/socket.io": "2.1.13", - "@types/socket.io-parser": "^2.2.1", "@types/stoppable": "^1.1.1", "@types/styled-components": "^5.1.15", "@types/throng": "^5.0.3", @@ -335,7 +334,6 @@ "resolutions": { "d3": "^7.0.0", "node-fetch": "^2.6.7", - "socket.io-parser": "^3.4.0", "prosemirror-transform": "1.2.5", "dot-prop": "^5.2.0", "js-yaml": "^3.14.1", diff --git a/server/services/websockets.ts b/server/services/websockets.ts index 4f12426ac..662613c50 100644 --- a/server/services/websockets.ts +++ b/server/services/websockets.ts @@ -2,9 +2,8 @@ import http, { IncomingMessage } from "http"; import { Duplex } from "stream"; import invariant from "invariant"; import Koa from "koa"; -import { each, find } from "lodash"; -import IO, { Client } from "socket.io"; -import socketRedisAdapter from "socket.io-redis"; +import IO from "socket.io"; +import { createAdapter } from "socket.io-redis"; import Logger from "@server/logging/Logger"; import Metrics from "@server/logging/metrics"; import { Document, Collection, View, User } from "@server/models"; @@ -15,8 +14,7 @@ import WebsocketsProcessor from "../queues/processors/WebsocketsProcessor"; import Redis from "../redis"; type SocketWithAuth = IO.Socket & { - auth: boolean; - client: Client & { + client: IO.Socket["client"] & { user?: User; }; }; @@ -29,10 +27,15 @@ export default function init( const path = "/realtime"; // Websockets for events and non-collaborative documents - const io = IO(server, { + const io = new IO.Server(server, { path, + allowEIO3: true, serveClient: false, cookie: false, + cors: { + origin: "*", + methods: ["GET", "POST"], + }, }); // Remove the upgrade handler that we just added when registering the IO engine @@ -72,20 +75,13 @@ export default function init( Metrics.gaugePerInstance("websockets.count", 0); }); - // Forbid all unauthenticated connections - each(io.nsps, forbidConnections); - io.adapter( - socketRedisAdapter({ + createAdapter({ pubClient: Redis.defaultClient, subClient: Redis.defaultSubscriber, }) ); - io.origins((_req, callback) => { - callback(null, true); - }); - io.of("/").adapter.on("error", (err: Error) => { if (err.name === "MaxRetriesPerRequestError") { Logger.error("Redis maximum retries exceeded in socketio adapter", err); @@ -102,19 +98,12 @@ export default function init( socket.client.conn.server.clientsCount ); - socket.auth = false; - socket.on("authentication", async function (data) { try { await authenticate(socket, data); - Logger.debug("websockets", `Authenticated socket ${socket.id}`); - socket.auth = true; - - each(io.nsps, function (nsp) { - restoreConnection(nsp, socket); - }); + socket.emit("authenticated", true); void authenticated(io, socket); } catch (err) { Logger.error(`Authentication error socket ${socket.id}`, err); @@ -135,7 +124,7 @@ export default function init( setTimeout(function () { // If the socket didn't authenticate after connection, disconnect it - if (!socket.auth) { + if (!socket.client.user) { Logger.debug("websockets", `Disconnecting socket ${socket.id}`); // @ts-expect-error should be boolean @@ -188,9 +177,8 @@ async function authenticated(io: IO.Server, socket: SocketWithAuth) { }).findByPk(event.collectionId); if (can(user, "read", collection)) { - socket.join(`collection-${event.collectionId}`, () => { - Metrics.increment("websockets.collections.join"); - }); + await socket.join(`collection-${event.collectionId}`); + Metrics.increment("websockets.collections.join"); } } @@ -208,71 +196,66 @@ async function authenticated(io: IO.Server, socket: SocketWithAuth) { event.documentId ); - socket.join(room, () => { - Metrics.increment("websockets.documents.join"); + await socket.join(room); + Metrics.increment("websockets.documents.join"); - // let everyone else in the room know that a new user joined - io.to(room).emit("user.join", { - userId: user.id, - documentId: event.documentId, - isEditing: event.isEditing, - }); - - // let this user know who else is already present in the room - io.in(room).clients(async (err: Error, sockets: string[]) => { - if (err) { - Logger.error("Error getting clients for room", err, { - sockets, - }); - return; - } - - // because a single user can have multiple socket connections we - // need to make sure that only unique userIds are returned. A Map - // makes this easy. - const userIds = new Map(); - - for (const socketId of sockets) { - const userId = await Redis.defaultClient.hget(socketId, "userId"); - userIds.set(userId, userId); - } - - socket.emit("document.presence", { - documentId: event.documentId, - userIds: Array.from(userIds.keys()), - editingIds: editing.map((view) => view.userId), - }); - }); + // let everyone else in the room know that a new user joined + io.to(room).emit("user.join", { + userId: user.id, + documentId: event.documentId, + isEditing: event.isEditing, }); + + // let this user know who else is already present in the room + try { + const socketIds = await io.in(room).allSockets(); + + // because a single user can have multiple socket connections we + // need to make sure that only unique userIds are returned. A Map + // makes this easy. + const userIds = new Map(); + + for (const socketId of socketIds) { + const userId = await Redis.defaultClient.hget(socketId, "userId"); + userIds.set(userId, userId); + } + + socket.emit("document.presence", { + documentId: event.documentId, + userIds: Array.from(userIds.keys()), + editingIds: editing.map((view) => view.userId), + }); + } catch (err) { + if (err) { + Logger.error("Error getting clients for room", err); + return; + } + } } } }); // allow the client to request to leave rooms - socket.on("leave", (event) => { + socket.on("leave", async (event) => { if (event.collectionId) { - socket.leave(`collection-${event.collectionId}`, () => { - Metrics.increment("websockets.collections.leave"); - }); + await socket.leave(`collection-${event.collectionId}`); + Metrics.increment("websockets.collections.leave"); } if (event.documentId) { const room = `document-${event.documentId}`; - socket.leave(room, () => { - Metrics.increment("websockets.documents.leave"); - io.to(room).emit("user.leave", { - userId: user.id, - documentId: event.documentId, - }); + await socket.leave(room); + Metrics.increment("websockets.documents.leave"); + io.to(room).emit("user.leave", { + userId: user.id, + documentId: event.documentId, }); } }); socket.on("disconnecting", () => { - const rooms = Object.keys(socket.rooms); - - rooms.forEach((room) => { + socket.rooms.forEach((room) => { if (room.startsWith("document-")) { const documentId = room.replace("document-", ""); io.to(room).emit("user.leave", { @@ -287,7 +270,7 @@ async function authenticated(io: IO.Server, socket: SocketWithAuth) { Metrics.increment("websockets.presence"); const room = `document-${event.documentId}`; - if (event.documentId && socket.rooms[room]) { + if (event.documentId && socket.rooms.has(room)) { const view = await View.touch(event.documentId, user.id, event.isEditing); view.user = user; @@ -314,27 +297,3 @@ async function authenticate(socket: SocketWithAuth, data: { token: string }) { // accessible across multiple websocket servers await Redis.defaultClient.hset(socket.id, "userId", user.id); } - -/** - * Set a listener so connections from unauthenticated sockets are not - * considered when emitting to the namespace. The connections will be - * restored after authentication succeeds. - */ -function forbidConnections(nsp: IO.Namespace) { - nsp.on("connect", function (socket: SocketWithAuth) { - if (!socket.auth) { - Logger.debug("websockets", `removing socket from ${nsp.name}`); - delete nsp.connected[socket.id]; - } - }); -} - -/** - * If the socket attempted a connection before authentication, restore it. - */ -function restoreConnection(nsp: IO.Namespace, socket: IO.Socket) { - if (find(nsp.sockets, { id: socket.id })) { - Logger.debug("websockets", `restoring socket to ${nsp.name}`); - nsp.connected[socket.id] = socket; - } -} diff --git a/server/typings/index.d.ts b/server/typings/index.d.ts index fcc219e3d..0671de6ae 100644 --- a/server/typings/index.d.ts +++ b/server/typings/index.d.ts @@ -6,8 +6,6 @@ declare module "styled-components-breakpoint"; declare module "formidable/lib/file"; -declare module "socket.io-client"; - declare module "oy-vey"; declare module "fetch-test-server"; diff --git a/server/typings/socketio-auth.d.ts b/server/typings/socketio-auth.d.ts deleted file mode 100644 index defed7698..000000000 --- a/server/typings/socketio-auth.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -declare module "socketio-auth" { - import IO from "socket.io"; - - type AuthenticatedSocket = IO.Socket & { - client: IO.Client & { - user: any; - }; - }; - - type AuthenticateCallback = ( - socket: AuthenticatedSocket, - data: { token: string }, - callback: (err: Error | null, allow: boolean) => void - ) => Promise; - - type PostAuthenticateCallback = ( - socket: AuthenticatedSocket - ) => Promise; - - type AuthenticationConfig = { - authenticate: AuthenticateCallback; - postAuthenticate: PostAuthenticateCallback; - }; - - const SocketAuth: (io: IO.Server, config: AuthenticationConfig) => void; - - export = SocketAuth; -} diff --git a/server/typings/socketio-redis.d.ts b/server/typings/socketio-redis.d.ts deleted file mode 100644 index 6093173fc..000000000 --- a/server/typings/socketio-redis.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -declare module "socket.io-redis" { - import { Redis } from "ioredis"; - - type Config = { - pubClient: Redis; - subClient: Redis; - }; - - const socketRedisAdapter: (config: Config) => void; - - export = socketRedisAdapter; -} diff --git a/yarn.lock b/yarn.lock index 276e8dcf9..507b0f100 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1004,7 +1004,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.16.0", "@babel/template@^7.16.7", "@babel/template@^7.18.6", "@babel/template@^7.3.3": +"@babel/template@^7.16.0", "@babel/template@^7.18.6", "@babel/template@^7.3.3": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.6.tgz#1283f4993e00b929d6e2d3c72fdc9168a2977a31" integrity sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw== @@ -2418,6 +2418,11 @@ dependencies: "@types/node" "*" +"@types/component-emitter@^1.2.10": + version "1.2.11" + resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506" + integrity sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ== + "@types/connect@*": version "3.4.35" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" @@ -2437,6 +2442,11 @@ dependencies: "@types/node" "*" +"@types/cookie@^0.4.0": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" + integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== + "@types/cookies@*": version "0.7.7" resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.7.7.tgz#7a92453d1d16389c05a5301eef566f34946cfd81" @@ -2447,6 +2457,11 @@ "@types/keygrip" "*" "@types/node" "*" +"@types/cors@^2.8.8": + version "2.8.12" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" + integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== + "@types/crypto-js@^4.1.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@types/crypto-js/-/crypto-js-4.1.0.tgz#09ba1b49bcce62c9a8e6d5e50a3364aa98975578" @@ -2471,13 +2486,6 @@ dependencies: emoji-regex "*" -"@types/engine.io@*": - version "3.1.7" - resolved "https://registry.yarnpkg.com/@types/engine.io/-/engine.io-3.1.7.tgz#86e541a5dc52fb7e97735383564a6ae4cfe2e8f5" - integrity sha512-qNjVXcrp+1sS8YpRUa714r0pgzOwESdW5UjHL7D/2ZFdBX0BXUXtg1LUrp+ylvqbvMcMWUy73YpRoxPN2VoKAQ== - dependencies: - "@types/node" "*" - "@types/enzyme-adapter-react-16@^1.0.6": version "1.0.6" resolved "https://registry.yarnpkg.com/@types/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.0.6.tgz#8aca7ae2fd6c7137d869b6616e696d21bb8b0cec" @@ -2824,10 +2832,10 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node@*", "@types/node@>=12", "@types/node@>=13.7.0": - version "17.0.38" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.38.tgz#f8bb07c371ccb1903f3752872c89f44006132947" - integrity sha512-5jY9RhV7c0Z4Jy09G+NIDTsCZ5G0L5n+Z+p+Y7t5VJHM30bgwzSjVtlcBxqAj+6L/swIlvtOSzr8rBk/aNyV2g== +"@types/node@*", "@types/node@>=10.0.0", "@types/node@>=12", "@types/node@>=13.7.0": + version "18.0.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.0.tgz#67c7b724e1bcdd7a8821ce0d5ee184d3b4dd525a" + integrity sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA== "@types/node@15.12.2": version "15.12.2" @@ -3157,29 +3165,6 @@ resolved "https://registry.yarnpkg.com/@types/slug/-/slug-5.0.2.tgz#1461545e8c23484fbded34ae6ff647c55cc09f28" integrity sha512-HFyrrOlpdLESwF4iuuoM0v66uo3Wm7R5rD6iZ5Odeej0dhcp1Crx0WaOzhmr19JtzUBr5NPH2JBTwxW4XUlkkg== -"@types/socket.io-parser@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/socket.io-parser/-/socket.io-parser-3.0.0.tgz#9726d3ab9235757a0a30dd5ccf8975dce54e5e2c" - integrity sha512-Ry/rbTE6HQNL9eu3LpL1Ocup5VexXu1bSSGlSho/IR5LuRc8YvxwSNJ3JxqTltVJEATLbZkMQETSbxfKNgp4Ew== - dependencies: - socket.io-parser "*" - -"@types/socket.io-parser@^2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@types/socket.io-parser/-/socket.io-parser-2.2.1.tgz#dc94aed303839487f4975249a32a548109ea3647" - integrity sha512-+JNb+7N7tSINyXPxAJb62+NcpC1x/fPn7z818W4xeNCdPTp6VsO/X8fCsg6+ug4a56m1v9sEiTIIUKVupcHOFQ== - dependencies: - "@types/node" "*" - -"@types/socket.io@2.1.13": - version "2.1.13" - resolved "https://registry.yarnpkg.com/@types/socket.io/-/socket.io-2.1.13.tgz#b6d694234e99956c96ff99e197eda824b6f9dc48" - integrity sha512-JRgH3nCgsWel4OPANkhH8TelpXvacAJ9VeryjuqCDiaVDMpLysd6sbt0dr6Z15pqH3p2YpOT3T1C5vQ+O/7uyg== - dependencies: - "@types/engine.io" "*" - "@types/node" "*" - "@types/socket.io-parser" "*" - "@types/source-list-map@*": version "0.1.2" resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" @@ -3584,11 +3569,6 @@ acorn@^8.2.4: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== -after@0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" - integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= - agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -3878,11 +3858,6 @@ array.prototype.flatmap@^1.2.3: es-abstract "^1.17.0-next.1" function-bind "^1.1.1" -arraybuffer.slice@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" - integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== - arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -4286,10 +4261,10 @@ babylon@^6.18.0: resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== -backo2@1.0.2: +backo2@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" - integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= + integrity sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA== balanced-match@^1.0.0: version "1.0.0" @@ -4306,7 +4281,7 @@ base64-js@^1.0.2, base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -base64id@2.0.0: +base64id@2.0.0, base64id@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== @@ -4356,11 +4331,6 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -blob@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683" - integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== - bluebird@^3.5.5, bluebird@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -5215,26 +5185,11 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -component-bind@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" - integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= - -component-emitter@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= - component-emitter@^1.2.1, component-emitter@~1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== -component-inherit@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" - integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= - compressible@^2.0.0: version "2.0.18" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" @@ -5435,6 +5390,14 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +cors@~2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + cosmiconfig@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.0.tgz#ef9b44d773959cae63ddecd122de23853b60f8d3" @@ -5959,14 +5922,14 @@ de-indent@^1.0.2: resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0= -debug@3.1.0, debug@~3.1.0: +debug@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== dependencies: ms "2.0.0" -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3: +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@~4.3.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -5987,13 +5950,6 @@ debug@^3.1.0, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@~4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - debuglog@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -6484,44 +6440,40 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -engine.io-client@~3.5.0: - version "3.5.2" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.5.2.tgz#0ef473621294004e9ceebe73cef0af9e36f2f5fa" - integrity sha512-QEqIp+gJ/kMHeUun7f5Vv3bteRHppHH/FMBQX/esFj/fuYfjyUKWGMo3VCvIP/V8bE9KcjHmRZrhIz2Z9oNsDA== +engine.io-client@~4.1.0: + version "4.1.4" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-4.1.4.tgz#0bda5ba4bd87bced2ad00b93c67e133d0fb981ba" + integrity sha512-843fqAdKeUMFqKi1sSjnR11tJ4wi8sIefu6+JC1OzkkJBmjtc/gM/rZ53tJfu5Iae/3gApm5veoS+v+gtT0+Fg== dependencies: + base64-arraybuffer "0.1.4" component-emitter "~1.3.0" - component-inherit "0.0.3" - debug "~3.1.0" - engine.io-parser "~2.2.0" + debug "~4.3.1" + engine.io-parser "~4.0.1" has-cors "1.1.0" - indexof "0.0.1" parseqs "0.0.6" parseuri "0.0.6" ws "~7.4.2" xmlhttprequest-ssl "~1.6.2" yeast "0.1.2" -engine.io-parser@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.1.tgz#57ce5611d9370ee94f99641b589f94c97e4f5da7" - integrity sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg== +engine.io-parser@~4.0.0, engine.io-parser@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-4.0.3.tgz#83d3a17acfd4226f19e721bb22a1ee8f7662d2f6" + integrity sha512-xEAAY0msNnESNPc00e19y5heTPX4y/TJ36gr8t1voOaNmTojP9b3oK3BbJLFufW2XFPQaaijpFewm2g2Um3uqA== dependencies: - after "0.8.2" - arraybuffer.slice "~0.0.7" base64-arraybuffer "0.1.4" - blob "0.0.5" - has-binary2 "~1.0.2" -engine.io@~3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.5.0.tgz#9d6b985c8a39b1fe87cd91eb014de0552259821b" - integrity sha512-21HlvPUKaitDGE4GXNtQ7PLP0Sz4aWLddMPw2VTyFz1FVZqu/kZsJUO8WNpKuE/OCL7nkfRaOui2ZCJloGznGA== +engine.io@~4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-4.1.2.tgz#f96ceb56d4b39cc7ca5bd29a20e9c99c1ad1a765" + integrity sha512-t5z6zjXuVLhXDMiFJPYsPOWEER8B0tIsD3ETgw19S1yg9zryvUfY3Vhtk3Gf4sihw/bQGIqQ//gjvVlu+Ca0bQ== dependencies: accepts "~1.3.4" base64id "2.0.0" cookie "~0.4.1" - debug "~4.1.0" - engine.io-parser "~2.2.0" + cors "~2.8.5" + debug "~4.3.1" + engine.io-parser "~4.0.0" ws "~7.4.2" enhanced-resolve@^4.1.1, enhanced-resolve@^4.3.0: @@ -7916,17 +7868,10 @@ has-bigints@^1.0.1: resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== -has-binary2@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d" - integrity sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw== - dependencies: - isarray "2.0.1" - has-cors@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" - integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= + integrity sha512-g5VNKdkFuUuVCP9gYfDJHjK2nqdQJ7aDLTnycnc2+RvsOQbuLdF5pm7vuE5J76SEBIQjs4kQY/BWq74JUmjbXA== has-flag@^3.0.0: version "3.0.0" @@ -8431,11 +8376,6 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= - infer-owner@^1.0.3, infer-owner@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" @@ -8956,11 +8896,6 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= -isarray@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" - integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4= - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -11063,7 +10998,7 @@ oauth@0.9.x: resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE= -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -13524,59 +13459,63 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -socket.io-adapter@~1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz#ab3f0d6f66b8fc7fca3959ab5991f82221789be9" - integrity sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g== +socket.io-adapter@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.1.0.tgz#edc5dc36602f2985918d631c1399215e97a1b527" + integrity sha512-+vDov/aTsLjViYTwS9fPy5pEtTkrbEKsw2M+oVSoFGw6OD1IpvlV1VPhUzNbofCQ8oyMbdYJqDtGdmHQK6TdPg== -socket.io-client@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.4.0.tgz#aafb5d594a3c55a34355562fc8aea22ed9119a35" - integrity sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ== +socket.io-adapter@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.2.0.tgz#43af9157c4609e74b8addc6867873ac7eb48fda2" + integrity sha512-rG49L+FwaVEwuAdeBRq49M97YI3ElVabJPzvHT9S6a2CWhDKnjSFasvwAwSYPRhQzfn4NtDIbCaGYgOCOU/rlg== + +socket.io-client@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-3.1.3.tgz#57ddcefea58cfab71f0e94c21124de8e3c5aa3e2" + integrity sha512-4sIGOGOmCg3AOgGi7EEr6ZkTZRkrXwub70bBB/F0JSkMOUFpA77WsL87o34DffQQ31PkbMUIadGOk+3tx1KGbw== dependencies: - backo2 "1.0.2" - component-bind "1.0.0" + "@types/component-emitter" "^1.2.10" + backo2 "~1.0.2" component-emitter "~1.3.0" - debug "~3.1.0" - engine.io-client "~3.5.0" - has-binary2 "~1.0.2" - indexof "0.0.1" - parseqs "0.0.6" + debug "~4.3.1" + engine.io-client "~4.1.0" parseuri "0.0.6" - socket.io-parser "~3.3.0" - to-array "0.1.4" + socket.io-parser "~4.0.4" -socket.io-parser@*, socket.io-parser@^3.4.0, socket.io-parser@~3.3.0, socket.io-parser@~3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.4.1.tgz#b06af838302975837eab2dc980037da24054d64a" - integrity sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A== +socket.io-parser@~4.0.3, socket.io-parser@~4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.5.tgz#cb404382c32324cc962f27f3a44058cf6e0552df" + integrity sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig== dependencies: - component-emitter "1.2.1" - debug "~4.1.0" - isarray "2.0.1" + "@types/component-emitter" "^1.2.10" + component-emitter "~1.3.0" + debug "~4.3.1" -socket.io-redis@^5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/socket.io-redis/-/socket.io-redis-5.4.0.tgz#d54bb8b757d04e9c0999d9a4ad07fc6c31bc848f" - integrity sha512-yCQm/Sywd3d08WXUfZRxt6O+JV2vWoPgWK6GVjiM0GkBtq5cpLOk8oILRPKbzTv1VEtSYmK41q0xzcgDinMbmQ== +socket.io-redis@^6.1.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/socket.io-redis/-/socket.io-redis-6.1.1.tgz#2361029a6c0b25c602d1422e1beb41907fd0e8bf" + integrity sha512-jeaXe3TGKC20GMSlPHEdwTUIWUpay/L7m5+S9TQcOf22p9Llx44/RkpJV08+buXTZ8E+aivOotj2RdeFJJWJJQ== dependencies: - debug "~4.1.0" + debug "~4.3.1" notepack.io "~2.2.0" redis "^3.0.0" - socket.io-adapter "~1.1.0" + socket.io-adapter "~2.2.0" uid2 "0.0.3" -socket.io@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.4.0.tgz#01030a2727bd8eb2e85ea96d69f03692ee53d47e" - integrity sha512-9UPJ1UTvKayuQfVv2IQ3k7tCQC/fboDyIK62i99dAQIyHKaBsNdTpwHLgKJ6guRWxRtC9H+138UwpaGuQO9uWQ== +socket.io@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-3.1.2.tgz#06e27caa1c4fc9617547acfbb5da9bc1747da39a" + integrity sha512-JubKZnTQ4Z8G4IZWtaAZSiRP3I/inpy8c/Bsx2jrwGrTbKeVU5xd6qkKMHpChYeM3dWZSO0QACiGK+obhBNwYw== dependencies: - debug "~4.1.0" - engine.io "~3.5.0" - has-binary2 "~1.0.2" - socket.io-adapter "~1.1.0" - socket.io-client "2.4.0" - socket.io-parser "~3.4.0" + "@types/cookie" "^0.4.0" + "@types/cors" "^2.8.8" + "@types/node" ">=10.0.0" + accepts "~1.3.4" + base64id "~2.0.0" + debug "~4.3.1" + engine.io "~4.1.0" + socket.io-adapter "~2.1.0" + socket.io-parser "~4.0.3" sort-keys@^5.0.0: version "5.0.0" @@ -14381,11 +14320,6 @@ to-absolute-glob@^2.0.0: is-absolute "^1.0.0" is-negated-glob "^1.0.0" -to-array@0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" - integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= - to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" @@ -14975,7 +14909,7 @@ value-or-function@^3.0.0: resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= -vary@^1.1.2: +vary@^1, vary@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= @@ -15765,7 +15699,7 @@ yarn-deduplicate@^3.1.0: yeast@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" - integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= + integrity sha512-8HFIh676uyGYP6wP13R/j6OJ/1HwJ46snpvzE7aHAN3Ryqh2yX6Xox2B4CUmTwwOIzlG3Bs7ocsP5dZH/R1Qbg== yjs@^13.5.29, yjs@^13.5.39: version "13.5.39"