diff --git a/desktop/flipper-server/package.json b/desktop/flipper-server/package.json index 2174c12c7..e5f3964f0 100644 --- a/desktop/flipper-server/package.json +++ b/desktop/flipper-server/package.json @@ -27,6 +27,7 @@ "flipper-pkg-lib": "0.0.0", "flipper-server-core": "0.0.0", "fs-extra": "^10.1.0", + "flipper-server-companion": "0.0.0", "metro": "^0.70.2", "open": "^8.3.0", "p-filter": "^2.1.0", diff --git a/desktop/flipper-server/src/index.tsx b/desktop/flipper-server/src/index.tsx index a83f35315..a7c882a43 100644 --- a/desktop/flipper-server/src/index.tsx +++ b/desktop/flipper-server/src/index.tsx @@ -18,6 +18,7 @@ import {startWebServerDev} from './startWebServerDev'; import yargs from 'yargs'; import open from 'open'; import {sleep} from 'flipper-common'; +import {initCompanionEnv} from 'flipper-server-companion'; const argv = yargs .usage('yarn flipper-server [args]') @@ -88,6 +89,7 @@ async function start() { argv.settingsString, argv.launcherSettings, ); + const companionEnv = await initCompanionEnv(flipperServer); if (argv.failFast) { flipperServer.on('server-state', ({state}) => { if (state === 'error') { @@ -100,7 +102,7 @@ async function start() { if (argv.bundler) { await startWebServerDev(app, server, socket, rootDir); } - startSocketServer(flipperServer, socket); + startSocketServer(flipperServer, socket, companionEnv); } start() diff --git a/desktop/flipper-server/src/startSocketServer.tsx b/desktop/flipper-server/src/startSocketServer.tsx index 94d99f40c..3b96df4c1 100644 --- a/desktop/flipper-server/src/startSocketServer.tsx +++ b/desktop/flipper-server/src/startSocketServer.tsx @@ -16,13 +16,20 @@ import { GenericWebSocketError, UserError, SystemError, + getLogger, } from 'flipper-common'; import {FlipperServerImpl} from 'flipper-server-core'; import {WebSocketServer} from 'ws'; +import { + FlipperServerCompanion, + FlipperServerCompanionEnv, +} from 'flipper-server-companion'; +import {URLSearchParams} from 'url'; export function startSocketServer( flipperServer: FlipperServerImpl, socket: WebSocketServer, + companionEnv: FlipperServerCompanionEnv, ) { socket.on('connection', (client, req) => { const clientAddress = @@ -34,7 +41,52 @@ export function startSocketServer( let connected = true; - function onServerEvent(event: string, payload: any) { + let flipperServerCompanion: FlipperServerCompanion | undefined; + if (req.url) { + const params = new URLSearchParams(req.url.slice(1)); + + if (params.get('server_companion')) { + flipperServerCompanion = new FlipperServerCompanion( + flipperServer, + getLogger(), + companionEnv.pluginInitializer.loadedPlugins, + ); + } + } + + async function onServerEvent(event: string, payload: any) { + if (flipperServerCompanion) { + switch (event) { + case 'client-message': { + const client = flipperServerCompanion.getClient(payload.id); + if (!client) { + console.warn( + 'flipperServerCompanion.handleClientMessage -> unknown client', + event, + payload, + ); + return; + } + client.onMessage(payload.message); + return; + } + case 'client-disconnected': { + if (flipperServerCompanion.getClient(payload.id)) { + flipperServerCompanion.destroyClient(payload.id); + } + // We use "break" here instead of "return" because a flipper desktop client still might be interested in the "client-disconnect" event to update its list of active clients + break; + } + case 'device-disconnected': { + if (flipperServerCompanion.getDevice(payload.id)) { + flipperServerCompanion.destroyDevice(payload.id); + } + // We use "break" here instead of "return" because a flipper desktop client still might be interested in the "device-disconnect" event to update its list of active devices + break; + } + } + } + const message = { event: 'server-event', payload: { @@ -85,8 +137,11 @@ export function startSocketServer( return; } - flipperServer - .exec(command, ...args) + const execRes = flipperServerCompanion?.canHandleCommand(command) + ? flipperServerCompanion.exec(command, ...args) + : flipperServer.exec(command, ...args); + + execRes .then((result: any) => { if (connected) { const response: ExecResponseWebSocketMessage = { @@ -138,12 +193,14 @@ export function startSocketServer( console.log(chalk.red(`Client disconnected ${clientAddress}`)); connected = false; flipperServer.offAny(onServerEvent); + flipperServerCompanion?.destroyAll(); }); client.on('error', (e) => { console.error(chalk.red(`Socket error ${clientAddress}`), e); connected = false; flipperServer.offAny(onServerEvent); + flipperServerCompanion?.destroyAll(); }); }); } diff --git a/desktop/flipper-server/tsconfig.json b/desktop/flipper-server/tsconfig.json index 9657c61f7..215a4c1f9 100644 --- a/desktop/flipper-server/tsconfig.json +++ b/desktop/flipper-server/tsconfig.json @@ -3,6 +3,7 @@ "compilerOptions": { "outDir": "lib", "rootDir": "src", + "lib": ["ES2019"], "types": ["../types/flipperGlobals", "../types/metro-resolver", "../types/metro"] }, "include": ["./src/*"], @@ -13,6 +14,9 @@ { "path": "../flipper-server-core" }, + { + "path": "../flipper-server-companion" + }, { "path": "../pkg-lib" }