Migrate from socket.io

Reviewed By: passy

Differential Revision: D34787674

fbshipit-source-id: 63d7c166ea29d14c96f0646a045e3f6fa93472e2
This commit is contained in:
Andrey Goncharov
2022-03-10 10:31:24 -08:00
committed by Facebook GitHub Bot
parent 6ec3771824
commit f85def32fb
11 changed files with 307 additions and 210 deletions

View File

@@ -54,3 +54,4 @@ export * from './settings';
export * from './PluginDetails';
export * from './doctor';
export * from './ServerAddOn';
export * from './transport';

View File

@@ -0,0 +1,49 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {FlipperServerCommands, FlipperServerEvents} from './server-types';
type GenericWebSocketMessage<E = string, T = unknown> = {
event: E;
payload: T;
};
export type ExecWebSocketMessage = GenericWebSocketMessage<
'exec',
{
[K in keyof FlipperServerCommands]: {
id: number;
command: K;
args: Parameters<FlipperServerCommands[K]>;
};
}[keyof FlipperServerCommands]
>;
export type ExecResponseWebSocketMessage = GenericWebSocketMessage<
'exec-response',
{id: number; data: unknown}
>;
export type ExecResponseErrorWebSocketMessage = GenericWebSocketMessage<
'exec-response-error',
{id: number; data: unknown}
>;
export type ServerEventWebSocketMessage = GenericWebSocketMessage<
'server-event',
{
[K in keyof FlipperServerEvents]: {event: K; data: FlipperServerEvents[K]};
}[keyof FlipperServerEvents]
>;
export type ClientWebSocketMessage = ExecWebSocketMessage;
export type ServerWebSocketMessage =
| ExecResponseWebSocketMessage
| ExecResponseErrorWebSocketMessage
| ServerEventWebSocketMessage;

View File

@@ -11,7 +11,8 @@
"dependenciesComment": "mac-ca is required dynamically for darwin, node-fetch is treated special in electron-requires, not sure why",
"dependencies": {
"mac-ca": "^1.0.6",
"node-fetch": "^2.6.7"
"node-fetch": "^2.6.7",
"ws": "^8.5.0"
},
"devDependencies": {
"@types/express": "^4.17.13",
@@ -25,7 +26,6 @@
"metro": "^0.69.0",
"open": "^8.3.0",
"p-filter": "^2.1.0",
"socket.io": "^4.4.1",
"yargs": "^17.0.1"
},
"peerDependencies": {},

View File

@@ -11,8 +11,9 @@ import express, {Express} from 'express';
import http from 'http';
import path from 'path';
import fs from 'fs-extra';
import socketio from 'socket.io';
import {VerifyClientCallbackSync, WebSocketServer} from 'ws';
import {WEBSOCKET_MAX_MESSAGE_SIZE} from 'flipper-server-core';
import {parse} from 'url';
type Config = {
port: number;
@@ -23,7 +24,7 @@ type Config = {
export async function startBaseServer(config: Config): Promise<{
app: Express;
server: http.Server;
socket: socketio.Server;
socket: WebSocketServer;
}> {
const {app, server} = await startAssetServer(config);
const socket = addWebsocket(server, config);
@@ -67,36 +68,60 @@ function addWebsocket(server: http.Server, config: Config) {
const localhostIPV6NoBrackets = `::1:${config.port}`;
const possibleHosts = [localhostIPV4, localhostIPV6, localhostIPV6NoBrackets];
const possibleOrigins = possibleHosts.map((host) => `http://${host}`);
const io = new socketio.Server(server, {
maxHttpBufferSize: WEBSOCKET_MAX_MESSAGE_SIZE,
allowRequest(req, callback) {
const noOriginHeader = req.headers.origin === undefined;
if (
noOriginHeader &&
req.headers.host &&
possibleHosts.includes(req.headers.host)
) {
// no origin header? Either the request is not cross-origin,
// or the request is not originating from a browser, so should be OK to pass through
callback(null, true);
} else {
// for now we don't allow cross origin request, so that an arbitrary website cannot try to
// connect a socket to localhost:serverport, and try to use the all powerful Flipper APIs to read
// for example files.
// Potentially in the future we do want to allow this, e.g. if we want to connect to a local flipper-server
// directly from intern. But before that, we should either authenticate the request somehow,
// and discuss security impact and for example scope the files that can be read by Flipper.
console.warn(
`Refused sockect connection from cross domain request, origin: ${
req.headers.origin
}, host: ${req.headers.host}. Expected: ${possibleHosts.join(
' or ',
)}`,
);
callback(null, false);
}
},
const verifyClient: VerifyClientCallbackSync = ({origin, req}) => {
const noOriginHeader = origin === undefined;
if (
(noOriginHeader || possibleOrigins.includes(origin)) &&
req.headers.host &&
possibleHosts.includes(req.headers.host)
) {
// no origin header? The request is not originating from a browser, so should be OK to pass through
// If origin matches our own address, it means we are serving the page
return true;
} else {
// for now we don't allow cross origin request, so that an arbitrary website cannot try to
// connect a socket to localhost:serverport, and try to use the all powerful Flipper APIs to read
// for example files.
// Potentially in the future we do want to allow this, e.g. if we want to connect to a local flipper-server
// directly from intern. But before that, we should either authenticate the request somehow,
// and discuss security impact and for example scope the files that can be read by Flipper.
console.warn(
`Refused socket connection from cross domain request, origin: ${origin}, host: ${
req.headers.host
}. Expected origins: ${possibleOrigins.join(
' or ',
)}. Expected hosts: ${possibleHosts.join(' or ')}`,
);
return false;
}
};
const wss = new WebSocketServer({
noServer: true,
maxPayload: WEBSOCKET_MAX_MESSAGE_SIZE,
verifyClient,
});
return io;
server.on('upgrade', function upgrade(request, socket, head) {
const {pathname} = parse(request.url);
// Handled by Metro
if (pathname === '/hot') {
return;
}
if (pathname === '/') {
wss.handleUpgrade(request, socket, head, function done(ws) {
wss.emit('connection', ws, request);
});
return;
}
console.error('addWebsocket.upgrade -> unknown pathname', pathname);
socket.destroy();
});
return wss;
}

View File

@@ -8,53 +8,91 @@
*/
import chalk from 'chalk';
import {
ClientWebSocketMessage,
ExecResponseWebSocketMessage,
ExecResponseErrorWebSocketMessage,
ServerEventWebSocketMessage,
} from 'flipper-common';
import {FlipperServerImpl} from 'flipper-server-core';
import socketio from 'socket.io';
import {WebSocketServer} from 'ws';
export function startSocketServer(
flipperServer: FlipperServerImpl,
socket: socketio.Server,
socket: WebSocketServer,
) {
socket.on('connection', (client) => {
console.log(chalk.green(`Client connected ${client.id}`));
socket.on('connection', (client, req) => {
const clientAddress = `${req.socket.remoteAddress}:${req.socket.remotePort}`;
console.log(chalk.green(`Client connected ${clientAddress}`));
let connected = true;
function onServerEvent(event: string, payoad: any) {
client.emit('event', event, payoad);
function onServerEvent(event: string, payload: any) {
const message = {
event: 'server-event',
payload: {
event,
data: payload,
},
} as ServerEventWebSocketMessage;
client.send(JSON.stringify(message));
}
flipperServer.onAny(onServerEvent);
client.on('exec', (id, command, args) => {
flipperServer
.exec(command, ...args)
.then((result: any) => {
if (connected) {
client.emit('exec-response', id, result);
}
})
.catch((error: any) => {
if (connected) {
// TODO: Serialize error
// TODO: log if verbose console.warn('Failed to handle response', error);
client.emit(
'exec-response-error',
id,
error.toString() + (error.stack ? `\n${error.stack}` : ''),
);
}
});
client.on('message', (data) => {
const {event, payload} = JSON.parse(
data.toString(),
) as ClientWebSocketMessage;
switch (event) {
case 'exec': {
const {id, command, args} = payload;
flipperServer
.exec(command, ...args)
.then((result: any) => {
if (connected) {
const response: ExecResponseWebSocketMessage = {
event: 'exec-response',
payload: {
id,
data: result,
},
};
client.send(JSON.stringify(response));
}
})
.catch((error: any) => {
if (connected) {
// TODO: Serialize error
// TODO: log if verbose console.warn('Failed to handle response', error);
const responseError: ExecResponseErrorWebSocketMessage = {
event: 'exec-response-error',
payload: {
id,
data:
error.toString() +
(error.stack ? `\n${error.stack}` : ''),
},
};
client.send(JSON.stringify(responseError));
}
});
}
}
});
client.on('disconnect', () => {
console.log(chalk.red(`Client disconnected ${client.id}`));
client.on('close', () => {
console.log(chalk.red(`Client disconnected ${clientAddress}`));
connected = false;
flipperServer.offAny(onServerEvent);
});
client.on('error', (e) => {
console.error(chalk.red(`Socket error ${client.id}`), e);
console.error(chalk.red(`Socket error ${clientAddress}`), e);
connected = false;
flipperServer.offAny(onServerEvent);
});

View File

@@ -12,7 +12,7 @@ import {Express} from 'express';
import http from 'http';
import path from 'path';
import fs from 'fs-extra';
import socketio from 'socket.io';
import {WebSocketServer} from 'ws';
import pFilter from 'p-filter';
import {homedir} from 'os';
@@ -51,7 +51,7 @@ export async function getPluginSourceFolders(): Promise<string[]> {
export async function startWebServerDev(
app: Express,
server: http.Server,
socket: socketio.Server,
socket: WebSocketServer,
rootDir: string,
) {
// prevent bundling!
@@ -138,7 +138,11 @@ export async function startWebServerDev(
connectMiddleware.attachHmrServer(server);
app.use(function (err: any, _req: any, _res: any, next: any) {
console.error(chalk.red('\n\nCompile error in client bundle\n'), err);
socket.local.emit('hasErrors', err.toString());
socket.clients.forEach((client) => {
client.send(
JSON.stringify({event: 'hasErrors', payload: err.toString()}),
);
});
next();
});

View File

@@ -9,7 +9,9 @@
"types": "lib/index.d.ts",
"license": "MIT",
"bugs": "https://github.com/facebook/flipper/issues",
"dependencies": {},
"dependencies": {
"reconnecting-websocket": "^4.4.0"
},
"devDependencies": {
"eventemitter3": "^4.0.7",
"flipper-common": "0.0.0",
@@ -17,8 +19,7 @@
"invariant": "^2.2.4",
"metro-runtime": "^0.69.0",
"pretty-format": "^27.5.0",
"react-refresh": "^0.10.0",
"socket.io-client": "^4.4.1"
"react-refresh": "^0.10.0"
},
"peerDependencies": {},
"scripts": {

View File

@@ -8,8 +8,12 @@
*/
import EventEmitter from 'eventemitter3';
import {FlipperServer} from 'flipper-common';
import {io, Socket} from 'socket.io-client';
import {
ExecWebSocketMessage,
FlipperServer,
ServerWebSocketMessage,
} from 'flipper-common';
import ReconnectingWebSocket from 'reconnecting-websocket';
const CONNECTION_TIMEOUT = 30 * 1000;
const EXEC_TIMOUT = 30 * 1000;
@@ -18,7 +22,7 @@ export function createFlipperServer(): Promise<FlipperServer> {
// TODO: polish this all!
window.flipperShowError?.('Connecting to server...');
return new Promise<FlipperServer>((resolve, reject) => {
const initialConnectionTimeout = setTimeout(() => {
let initialConnectionTimeout: number | undefined = setTimeout(() => {
reject(
new Error('Failed to connect to Flipper server in a timely manner'),
);
@@ -26,7 +30,7 @@ export function createFlipperServer(): Promise<FlipperServer> {
const eventEmitter = new EventEmitter();
// TODO: recycle the socket that is created in index.web.dev.html?
const socket: Socket = io();
const socket = new ReconnectingWebSocket(`ws://${location.host}`);
const pendingRequests: Map<
number,
{
@@ -38,19 +42,20 @@ export function createFlipperServer(): Promise<FlipperServer> {
let requestId = 0;
let connected = false;
socket.on('connect', () => {
socket.addEventListener('open', () => {
if (initialConnectionTimeout) {
// only relevant for the first connect
resolve(flipperServer);
clearTimeout(initialConnectionTimeout);
initialConnectionTimeout = undefined;
}
window?.flipperHideError?.();
console.log('Socket to Flipper server connected');
connected = true;
});
socket.once('connect', () => {
// only relevant for the first connect
resolve(flipperServer);
clearTimeout(initialConnectionTimeout);
});
socket.on('disconnect', () => {
socket.addEventListener('close', () => {
window?.flipperShowError?.('WebSocket connection lost');
console.warn('Socket to Flipper server disconnected');
connected = false;
@@ -60,35 +65,50 @@ export function createFlipperServer(): Promise<FlipperServer> {
pendingRequests.clear();
});
socket.on('exec-response', (id: number, data: any) => {
console.debug('exec <<<', id, data);
const entry = pendingRequests.get(id);
if (!entry) {
console.warn(`Unknown request id `, id);
} else {
pendingRequests.delete(id);
clearTimeout(entry.timeout);
entry.resolve(data);
}
});
socket.addEventListener('message', ({data}) => {
const {event, payload} = JSON.parse(
data.toString(),
) as ServerWebSocketMessage;
socket.on('exec-response-error', (id: number, error: any) => {
// TODO: Deserialize error
console.debug('exec <<< [SERVER ERROR]', id, error);
const entry = pendingRequests.get(id);
if (!entry) {
console.warn(`Unknown request id `, id);
} else {
pendingRequests.delete(id);
clearTimeout(entry.timeout);
entry.reject(error);
switch (event) {
case 'exec-response': {
console.debug('exec <<<', payload);
const entry = pendingRequests.get(payload.id);
if (!entry) {
console.warn(`Unknown request id `, payload.id);
} else {
pendingRequests.delete(payload.id);
clearTimeout(entry.timeout);
entry.resolve(payload.data);
}
break;
}
case 'exec-response-error': {
// TODO: Deserialize error
console.debug('exec <<< [SERVER ERROR]', payload.id, payload.data);
const entry = pendingRequests.get(payload.id);
if (!entry) {
console.warn(`Unknown request id `, payload.id);
} else {
pendingRequests.delete(payload.id);
clearTimeout(entry.timeout);
entry.reject(payload.data);
}
break;
}
case 'server-event': {
eventEmitter.emit(payload.event, payload.data);
break;
}
default: {
console.warn(
'createFlipperServer -> unknown message',
data.toString(),
);
}
}
});
socket.on('event', (eventType, data) => {
eventEmitter.emit(eventType, data);
});
const flipperServer: FlipperServer = {
async connect() {},
close() {},
@@ -107,7 +127,15 @@ export function createFlipperServer(): Promise<FlipperServer> {
}, EXEC_TIMOUT),
});
socket.emit('exec', id, command, args);
const execMessage = {
event: 'exec',
payload: {
id,
command,
args,
},
} as ExecWebSocketMessage;
socket.send(JSON.stringify(execMessage));
});
// socket.
} else {

View File

@@ -1,3 +1,16 @@
diff --git a/node_modules/metro/src/index.js b/node_modules/metro/src/index.js
index 1c3a58e..96c7376 100644
--- a/node_modules/metro/src/index.js
+++ b/node_modules/metro/src/index.js
@@ -115,8 +115,6 @@ const createConnectMiddleware = async function (config, options) {
wss.handleUpgrade(request, socket, head, (ws) => {
wss.emit("connection", ws, request);
});
- } else {
- socket.destroy();
}
});
},
diff --git a/node_modules/metro/src/lib/getPreludeCode.js b/node_modules/metro/src/lib/getPreludeCode.js
index 56780d7..7da26d1 100644
--- a/node_modules/metro/src/lib/getPreludeCode.js

View File

@@ -58,24 +58,27 @@
</div>
<script src="/socket.io/socket.io.js"></script>
<script>
(function() {
// FIXME: needed to make Metro work
window.global = window;
let suppressErrors = false;
const socket = io(location.origin);
const socket = new WebSocket(`ws://${location.host}`);
socket.on('refresh', () => {
location.reload();
});
socket.addEventListener('message', ({ data: dataRaw }) => {
const message = JSON.parse(dataRaw.toString())
socket.on('hasErrors', (html) => {
openError(html);
if (message.event === 'hasErrors') {
openError(message.payload);
suppressErrors = true;
}
})
socket.addEventListener('error', () => {
openError('WebSocket -> error');
suppressErrors = true;
});
})
function openError(text) {

View File

@@ -2393,10 +2393,10 @@
dependencies:
"@sinonjs/commons" "^1.7.0"
"@socket.io/component-emitter@~3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.0.0.tgz#8863915676f837d9dad7b76f50cb500c1e9422e9"
integrity sha512-2pTGuibAXJswAPJjaKisthqS/NOK5ypG4LYT6tEAV0S/mxW0zOIvYvGK0V8w8+SHxAm6vRMSjqSalFXeBAqs+Q==
"@socket.io/base64-arraybuffer@~1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#568d9beae00b0d835f4f8c53fd55714986492e61"
integrity sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==
"@szmarczak/http-timer@^1.1.2":
version "1.1.2"
@@ -2523,9 +2523,9 @@
"@types/node" "*"
"@types/component-emitter@^1.2.10":
version "1.2.10"
resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.10.tgz#ef5b1589b9f16544642e473db5ea5639107ef3ea"
integrity sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==
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.33"
@@ -2770,11 +2770,16 @@
"@types/node" "*"
form-data "^3.0.0"
"@types/node@*", "@types/node@>=10.0.0":
"@types/node@*":
version "16.11.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.0.tgz#4b95f2327bacd1ef8f08d8ceda193039c5d7f52e"
integrity sha512-8MLkBIYQMuhRBQzGN9875bYsOhPnf/0rgXGo66S2FemHkhbn9qtsz9ywV1iCG+vbjigE4WUNVvw37Dx+L0qsPg==
"@types/node@>=10.0.0":
version "17.0.21"
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644"
integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==
"@types/node@^12.0.12":
version "12.20.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.7.tgz#1cb61fd0c85cb87e728c43107b5fd82b69bc9ef8"
@@ -3186,7 +3191,7 @@ absolute-path@^0.0.0:
resolved "https://registry.yarnpkg.com/absolute-path/-/absolute-path-0.0.0.tgz#a78762fbdadfb5297be99b15d35a785b2f095bf7"
integrity sha1-p4di+9rftSl76ZsV01p4Wy8JW/c=
accepts@^1.3.7, accepts@~1.3.4:
accepts@^1.3.7:
version "1.3.7"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
@@ -3194,7 +3199,7 @@ accepts@^1.3.7, accepts@~1.3.4:
mime-types "~2.1.24"
negotiator "0.6.2"
accepts@~1.3.8:
accepts@~1.3.4, accepts@~1.3.8:
version "1.3.8"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
@@ -3974,11 +3979,6 @@ babel-preset-jest@^26.6.2:
babel-plugin-jest-hoist "^26.6.2"
babel-preset-current-node-syntax "^1.0.0"
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=
bail@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776"
@@ -3989,11 +3989,6 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
base64-arraybuffer@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.1.tgz#87bd13525626db4a9838e00a508c2b73efcf348c"
integrity sha512-vFIUq7FdLtjZMhATwDul5RZWv2jpXQ09Pd6jcVEOvIsqCWTRFD/ONHNfyOS8dA/Ippi5dsIgpyKWKZaAKZltbA==
base64-js@^1.3.1, base64-js@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
@@ -4872,16 +4867,11 @@ cookie-signature@1.0.6:
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
cookie@0.4.2:
cookie@0.4.2, cookie@~0.4.1:
version "0.4.2"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432"
integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
cookie@~0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1"
integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==
copy-anything@^2.0.1:
version "2.0.3"
resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-2.0.3.tgz#842407ba02466b0df844819bbe3baebbe5d45d87"
@@ -5584,32 +5574,17 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
dependencies:
once "^1.4.0"
engine.io-client@~6.1.1:
version "6.1.1"
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.1.1.tgz#800d4b9db5487d169686729e5bd887afa78d36b0"
integrity sha512-V05mmDo4gjimYW+FGujoGmmmxRaDsrVr7AXA3ZIfa04MWM1jOfZfUwou0oNqhNwy/votUDvGDt4JA4QF4e0b4g==
engine.io-parser@~5.0.3:
version "5.0.3"
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.3.tgz#ca1f0d7b11e290b4bfda251803baea765ed89c09"
integrity sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==
dependencies:
"@socket.io/component-emitter" "~3.0.0"
debug "~4.3.1"
engine.io-parser "~5.0.0"
has-cors "1.1.0"
parseqs "0.0.6"
parseuri "0.0.6"
ws "~8.2.3"
xmlhttprequest-ssl "~2.0.0"
yeast "0.1.2"
engine.io-parser@~5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.1.tgz#6695fc0f1e6d76ad4a48300ff80db5f6b3654939"
integrity sha512-j4p3WwJrG2k92VISM0op7wiq60vO92MlF3CRGxhKHy9ywG1/Dkc72g0dXeDQ+//hrcDn8gqQzoEkdO9FN0d9AA==
dependencies:
base64-arraybuffer "~1.0.1"
"@socket.io/base64-arraybuffer" "~1.0.2"
engine.io@~6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.1.0.tgz#459eab0c3724899d7b63a20c3a6835cf92857939"
integrity sha512-ErhZOVu2xweCjEfYcTdkCnEYUiZgkAcBBAhW4jbIvNG8SLU3orAqoJCiytZjYF7eTpVmmCrLDjLIEaPlUAs1uw==
version "6.1.3"
resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.1.3.tgz#f156293d011d99a3df5691ac29d63737c3302e6f"
integrity sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==
dependencies:
"@types/cookie" "^0.4.1"
"@types/cors" "^2.8.12"
@@ -5619,7 +5594,7 @@ engine.io@~6.1.0:
cookie "~0.4.1"
cors "~2.8.5"
debug "~4.3.1"
engine.io-parser "~5.0.0"
engine.io-parser "~5.0.3"
ws "~8.2.3"
enquirer@^2.3.5:
@@ -6883,11 +6858,6 @@ has-bigints@^1.0.1:
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113"
integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==
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=
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@@ -9835,16 +9805,6 @@ parse5@6.0.1:
resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
parseqs@0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.6.tgz#8e4bb5a19d1cdc844a08ac974d34e273afa670d5"
integrity sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==
parseuri@0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.6.tgz#e1496e829e3ac2ff47f39a4dd044b32823c4a25a"
integrity sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==
parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
@@ -10838,6 +10798,11 @@ readdir-glob@^1.0.0:
dependencies:
minimatch "^3.0.4"
reconnecting-websocket@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz#3b0e5b96ef119e78a03135865b8bb0af1b948783"
integrity sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng==
recursive-readdir@^2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f"
@@ -11548,18 +11513,6 @@ socket.io-adapter@~2.3.3:
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz#4d6111e4d42e9f7646e365b4f578269821f13486"
integrity sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==
socket.io-client@^4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.4.1.tgz#b6aa9448149d09b8d0b2bbf3d2fac310631fdec9"
integrity sha512-N5C/L5fLNha5Ojd7Yeb/puKcPWWcoB/A09fEjjNsg91EDVr5twk/OEyO6VT9dlLSUNY85NpW6KBhVMvaLKQ3vQ==
dependencies:
"@socket.io/component-emitter" "~3.0.0"
backo2 "~1.0.2"
debug "~4.3.2"
engine.io-client "~6.1.1"
parseuri "0.0.6"
socket.io-parser "~4.1.1"
socket.io-parser@~4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.4.tgz#9ea21b0d61508d18196ef04a2c6b9ab630f4c2b0"
@@ -11569,14 +11522,6 @@ socket.io-parser@~4.0.4:
component-emitter "~1.3.0"
debug "~4.3.1"
socket.io-parser@~4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.1.1.tgz#0ad53d980781cab1eabe320417d8480c0133e62d"
integrity sha512-USQVLSkDWE5nbcY760ExdKaJxCE65kcsG/8k5FDGZVVxpD1pA7hABYXYkCUvxUuYYh/+uQw0N/fvBzfT8o07KA==
dependencies:
"@socket.io/component-emitter" "~3.0.0"
debug "~4.3.1"
socket.io@^4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.4.1.tgz#cd6de29e277a161d176832bb24f64ee045c56ab8"
@@ -12900,11 +12845,6 @@ xmldom@^0.5.0:
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.5.0.tgz#193cb96b84aa3486127ea6272c4596354cb4962e"
integrity sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA==
xmlhttprequest-ssl@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67"
integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==
xtend@^4.0.0, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
@@ -13022,11 +12962,6 @@ yauzl@^2.10.0, yauzl@^2.4.2:
buffer-crc32 "~0.2.3"
fd-slicer "~1.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=
yn@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"