Implement sending messages from a server add-on
Reviewed By: mweststrate Differential Revision: D34074383 fbshipit-source-id: de85e7a22dc9bb780163fc5b522708e8bc976df3
This commit is contained in:
committed by
Facebook GitHub Bot
parent
842b2c810a
commit
db976d5113
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<string, ServerAddOn>();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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<void>;
|
||||
interface ServerAddOnModule {
|
||||
serverAddOn?: (
|
||||
connection: ServerAddOnModuleToDesktopConnection,
|
||||
{flipperServer}: {flipperServer: FlipperServerForServerAddOn},
|
||||
) => Promise<ServerAddOnCleanup>;
|
||||
}
|
||||
|
||||
@@ -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<ServerAddOn> {
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<FlipperPluginReceiverRes>;
|
||||
|
||||
export class ServerAddOnModuleToDesktopConnection {
|
||||
export type ServerAddOnModuleToDesktopConnectionEvents = {
|
||||
message: ExecuteMessage;
|
||||
};
|
||||
|
||||
export class ServerAddOnModuleToDesktopConnection extends EventEmitter {
|
||||
private subscriptions: Map<string, FlipperPluginReceiver> = 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) {
|
||||
|
||||
Reference in New Issue
Block a user