From db976d5113f026089ff2a91546f0c0d98729e858 Mon Sep 17 00:00:00 2001 From: Andrey Goncharov Date: Mon, 28 Feb 2022 03:50:34 -0800 Subject: [PATCH] Implement sending messages from a server add-on Reviewed By: mweststrate Differential Revision: D34074383 fbshipit-source-id: de85e7a22dc9bb780163fc5b522708e8bc976df3 --- desktop/flipper-common/src/server-types.tsx | 4 +- .../src/FlipperServerImpl.tsx | 2 +- .../src/plugins/PluginManager.tsx | 10 ++++- .../src/plugins/ServerAddOn.tsx | 22 +++++++--- .../ServerAddOnDesktopToModuleConnection.tsx | 41 +++++++++++++++++-- .../ServerAddOnModuleToDesktopConnection.tsx | 22 ++++++++-- 6 files changed, 82 insertions(+), 19 deletions(-) diff --git a/desktop/flipper-common/src/server-types.tsx b/desktop/flipper-common/src/server-types.tsx index 932411d76..8bc801685 100644 --- a/desktop/flipper-common/src/server-types.tsx +++ b/desktop/flipper-common/src/server-types.tsx @@ -125,9 +125,7 @@ export type FlipperServerEvents = { id: string; message: string; }; - 'plugins-server-add-on-message': { - payload: ExecuteMessage; - }; + 'plugins-server-add-on-message': ExecuteMessage; 'download-file-update': DownloadFileUpdate; }; diff --git a/desktop/flipper-server-core/src/FlipperServerImpl.tsx b/desktop/flipper-server-core/src/FlipperServerImpl.tsx index 3abd61d62..d5bb6dd8b 100644 --- a/desktop/flipper-server-core/src/FlipperServerImpl.tsx +++ b/desktop/flipper-server-core/src/FlipperServerImpl.tsx @@ -88,7 +88,7 @@ export class FlipperServerImpl implements FlipperServer { // given flipper-dump, it might make more sense to have the plugin command // handling (like download, install, etc) moved to flipper-server & app, // but let's keep things simple for now - this.pluginManager = new PluginManager(); + this.pluginManager = new PluginManager(this); server.addListener('error', (err) => { this.emit('server-error', err); diff --git a/desktop/flipper-server-core/src/plugins/PluginManager.tsx b/desktop/flipper-server-core/src/plugins/PluginManager.tsx index 1dddee932..f3a604f12 100644 --- a/desktop/flipper-server-core/src/plugins/PluginManager.tsx +++ b/desktop/flipper-server-core/src/plugins/PluginManager.tsx @@ -32,6 +32,7 @@ import { installPluginFromNpm, } from 'flipper-plugin-lib'; import {ServerAddOn} from './ServerAddOn'; +import {FlipperServerForServerAddOn} from './ServerAddOnDesktopToModuleConnection'; const maxInstalledPluginVersionsToKeep = 2; @@ -50,6 +51,8 @@ const isExecuteMessage = (message: object): message is ExecuteMessage => export class PluginManager { private readonly serverAddOns = new Map(); + constructor(private readonly flipperServer: FlipperServerForServerAddOn) {} + async start() { // This needn't happen immediately and is (light) I/O work. setTimeout(() => { @@ -183,8 +186,11 @@ export class PluginManager { return; } - const newServerAddOn = await ServerAddOn.start(pluginName, owner, () => - this.serverAddOns.delete(pluginName), + const newServerAddOn = await ServerAddOn.start( + pluginName, + owner, + () => this.serverAddOns.delete(pluginName), + this.flipperServer, ); this.serverAddOns.set(pluginName, newServerAddOn); } diff --git a/desktop/flipper-server-core/src/plugins/ServerAddOn.tsx b/desktop/flipper-server-core/src/plugins/ServerAddOn.tsx index f9ba9a2f2..fc9471e37 100644 --- a/desktop/flipper-server-core/src/plugins/ServerAddOn.tsx +++ b/desktop/flipper-server-core/src/plugins/ServerAddOn.tsx @@ -9,13 +9,17 @@ import assert from 'assert'; import {assertNotNull} from '../comms/Utilities'; -import {ServerAddOnDesktopToModuleConnection} from './ServerAddOnDesktopToModuleConnection'; +import { + ServerAddOnDesktopToModuleConnection, + FlipperServerForServerAddOn, +} from './ServerAddOnDesktopToModuleConnection'; import {ServerAddOnModuleToDesktopConnection} from './ServerAddOnModuleToDesktopConnection'; type ServerAddOnCleanup = () => Promise; interface ServerAddOnModule { serverAddOn?: ( connection: ServerAddOnModuleToDesktopConnection, + {flipperServer}: {flipperServer: FlipperServerForServerAddOn}, ) => Promise; } @@ -34,13 +38,14 @@ export class ServerAddOn { public readonly connection: ServerAddOnDesktopToModuleConnection, initialOwner: string, ) { - this.owners = new Set(initialOwner); + this.owners = new Set([initialOwner]); } static async start( pluginName: string, initialOwner: string, onStop: () => void, + flipperServer: FlipperServerForServerAddOn, ): Promise { console.info('ServerAddOn.start', pluginName); @@ -54,7 +59,9 @@ export class ServerAddOn { const serverAddOnModuleToDesktopConnection = new ServerAddOnModuleToDesktopConnection(); - const cleanup = await serverAddOn(serverAddOnModuleToDesktopConnection); + const cleanup = await serverAddOn(serverAddOnModuleToDesktopConnection, { + flipperServer, + }); assert( typeof cleanup === 'function', `ServerAddOn ${pluginName} must return a clean up function, instead it returned ${typeof cleanup}.`, @@ -65,12 +72,15 @@ export class ServerAddOn { await cleanup(); }; + const desktopToModuleConnection = new ServerAddOnDesktopToModuleConnection( + serverAddOnModuleToDesktopConnection, + flipperServer, + ); + return new ServerAddOn( pluginName, onStopCombined, - new ServerAddOnDesktopToModuleConnection( - serverAddOnModuleToDesktopConnection, - ), + desktopToModuleConnection, initialOwner, ); } diff --git a/desktop/flipper-server-core/src/plugins/ServerAddOnDesktopToModuleConnection.tsx b/desktop/flipper-server-core/src/plugins/ServerAddOnDesktopToModuleConnection.tsx index 9ffa4b278..9ed7af565 100644 --- a/desktop/flipper-server-core/src/plugins/ServerAddOnDesktopToModuleConnection.tsx +++ b/desktop/flipper-server-core/src/plugins/ServerAddOnDesktopToModuleConnection.tsx @@ -8,13 +8,37 @@ */ import assert from 'assert'; -import {ClientResponseType, ExecuteMessage} from 'flipper-common'; -import {ServerAddOnModuleToDesktopConnection} from './ServerAddOnModuleToDesktopConnection'; +import { + ClientResponseType, + ExecuteMessage, + FlipperServer, + FlipperServerEvents, +} from 'flipper-common'; +import {ServerDevice} from '../devices/ServerDevice'; +import { + ServerAddOnModuleToDesktopConnection, + ServerAddOnModuleToDesktopConnectionEvents, +} from './ServerAddOnModuleToDesktopConnection'; + +export interface FlipperServerForServerAddOn extends FlipperServer { + emit( + event: 'plugins-server-add-on-message', + payload: FlipperServerEvents['plugins-server-add-on-message'], + ): void; + registerDevice(device: ServerDevice): void; + unregisterDevice(serial: string): void; + getDevice(serial: string): ServerDevice; + getDeviceSerials(): string[]; + getDevices(): ServerDevice[]; +} export class ServerAddOnDesktopToModuleConnection { constructor( private readonly moduleToDesktopConnection: ServerAddOnModuleToDesktopConnection, - ) {} + private readonly flipperServer: FlipperServerForServerAddOn, + ) { + this.subscribeToMessagesFromServerAddOn(); + } async sendExpectResponse({ method, @@ -34,4 +58,15 @@ export class ServerAddOnDesktopToModuleConnection { length, }; } + + private subscribeToMessagesFromServerAddOn() { + const event = 'message'; + const onMessage = ( + message: ServerAddOnModuleToDesktopConnectionEvents[typeof event], + ) => { + this.flipperServer.emit('plugins-server-add-on-message', message); + }; + + this.moduleToDesktopConnection.on(event, onMessage); + } } diff --git a/desktop/flipper-server-core/src/plugins/ServerAddOnModuleToDesktopConnection.tsx b/desktop/flipper-server-core/src/plugins/ServerAddOnModuleToDesktopConnection.tsx index 92693352e..eb44e6281 100644 --- a/desktop/flipper-server-core/src/plugins/ServerAddOnModuleToDesktopConnection.tsx +++ b/desktop/flipper-server-core/src/plugins/ServerAddOnModuleToDesktopConnection.tsx @@ -7,7 +7,8 @@ * @format */ -import {ResponseMessage, ClientErrorType} from 'flipper-common'; +import EventEmitter from 'events'; +import {ResponseMessage, ClientErrorType, ExecuteMessage} from 'flipper-common'; import {safeJSONStringify} from '../utils/safeJSONStringify'; // TODO: Share with js-flipper? Is it worth it? @@ -24,11 +25,24 @@ type FlipperPluginReceiver = ( data: any, ) => FlipperPluginReceiverRes | Promise; -export class ServerAddOnModuleToDesktopConnection { +export type ServerAddOnModuleToDesktopConnectionEvents = { + message: ExecuteMessage; +}; + +export class ServerAddOnModuleToDesktopConnection extends EventEmitter { private subscriptions: Map = new Map(); - send() { - // TODO: Implement me + send(method: string, params: unknown) { + const event = 'message'; + const message: ServerAddOnModuleToDesktopConnectionEvents[typeof event] = { + method: 'execute', + params: { + method, + params, + api: '', // TODO: Consider using here pluginId and validate it + }, + }; + this.emit('message', message); } receive(method: string, receiver: FlipperPluginReceiver) {