Move flipper-server client to flipper-frontend-core

Summary: ^

Reviewed By: aigoncharov

Differential Revision: D36410944

fbshipit-source-id: 2adb5904cd0f5f15d08be22c611d6774e7533f94
This commit is contained in:
Lorenzo Blasa
2022-05-17 03:54:16 -07:00
committed by Facebook GitHub Bot
parent ce83f2c01b
commit bfcdb82b43
6 changed files with 186 additions and 3 deletions

View File

@@ -16,7 +16,8 @@
"immer": "^9.0.12", "immer": "^9.0.12",
"js-base64": "^3.7.2", "js-base64": "^3.7.2",
"p-map": "^5.3.0", "p-map": "^5.3.0",
"semver": "^7.3.7" "semver": "^7.3.7",
"reconnecting-websocket": "^4.4.0"
}, },
"devDependencies": { "devDependencies": {
"flipper-test-utils": "0.0.0" "flipper-test-utils": "0.0.0"

View File

@@ -0,0 +1,163 @@
/**
* 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 EventEmitter from 'eventemitter3';
import {
ExecWebSocketMessage,
FlipperServer,
ServerWebSocketMessage,
} from 'flipper-common';
import ReconnectingWebSocket from 'reconnecting-websocket';
const CONNECTION_TIMEOUT = 30 * 1000;
const EXEC_TIMOUT = 30 * 1000;
export enum FlipperServerState {
CONNECTING,
CONNECTED,
DISCONNECTED,
}
export function createFlipperServer(
onStateChange: (state: FlipperServerState) => void,
): Promise<FlipperServer> {
onStateChange(FlipperServerState.CONNECTING);
return new Promise<FlipperServer>((resolve, reject) => {
let initialConnectionTimeout: number | undefined = window.setTimeout(() => {
reject(
new Error('Failed to connect to flipper-server in a timely manner'),
);
}, CONNECTION_TIMEOUT);
const eventEmitter = new EventEmitter();
const socket = new ReconnectingWebSocket(`ws://${location.host}`);
const pendingRequests: Map<
number,
{
resolve: (data: any) => void;
reject: (data: any) => void;
timeout: ReturnType<typeof setTimeout>;
}
> = new Map();
let requestId = 0;
let connected = false;
socket.addEventListener('open', () => {
if (initialConnectionTimeout) {
resolve(flipperServer);
clearTimeout(initialConnectionTimeout);
initialConnectionTimeout = undefined;
}
onStateChange(FlipperServerState.CONNECTED);
connected = true;
});
socket.addEventListener('close', () => {
onStateChange(FlipperServerState.DISCONNECTED);
connected = false;
pendingRequests.forEach((r) =>
r.reject(new Error('flipper-server disconnected')),
);
pendingRequests.clear();
});
socket.addEventListener('message', ({data}) => {
const {event, payload} = JSON.parse(
data.toString(),
) as ServerWebSocketMessage;
switch (event) {
case 'exec-response': {
console.debug('flipper-server: 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(
'flipper-server: exec <<< [SERVER ERROR]',
payload.id,
payload.data,
);
const entry = pendingRequests.get(payload.id);
if (!entry) {
console.warn(`flipper-server: 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(
'flipper-server: received unknown message type',
data.toString(),
);
}
}
});
const flipperServer: FlipperServer = {
async connect() {},
close() {},
exec(command, ...args): any {
if (connected) {
const id = ++requestId;
return new Promise<any>((resolve, reject) => {
console.debug('flipper-server: exec >>>', id, command, args);
pendingRequests.set(id, {
resolve,
reject,
timeout: setInterval(() => {
pendingRequests.delete(id);
reject(
new Error(`flipper-server: timeout for command '${command}'`),
);
}, EXEC_TIMOUT),
});
const execMessage = {
event: 'exec',
payload: {
id,
command,
args,
},
} as ExecWebSocketMessage;
socket.send(JSON.stringify(execMessage));
});
} else {
throw new Error('Not connected to Flipper server');
}
},
on(event, callback) {
eventEmitter.on(event, callback);
},
off(event, callback) {
eventEmitter.off(event, callback);
},
};
});
}

View File

@@ -14,3 +14,4 @@ export {default as BaseDevice} from './devices/BaseDevice';
export * from './globalObject'; export * from './globalObject';
export * from './plugins'; export * from './plugins';
export * from './flipperLibImplementation'; export * from './flipperLibImplementation';
export * from './client/FlipperServerClient';

View File

@@ -15,6 +15,7 @@
"devDependencies": { "devDependencies": {
"eventemitter3": "^4.0.7", "eventemitter3": "^4.0.7",
"flipper-common": "0.0.0", "flipper-common": "0.0.0",
"flipper-frontend-core": "0.0.0",
"flipper-ui-core": "0.0.0", "flipper-ui-core": "0.0.0",
"invariant": "^2.2.4", "invariant": "^2.2.4",
"metro-runtime": "^0.70.2", "metro-runtime": "^0.70.2",

View File

@@ -9,7 +9,7 @@
import {getLogger, Logger, setLoggerInstance} from 'flipper-common'; import {getLogger, Logger, setLoggerInstance} from 'flipper-common';
import {initializeRenderHost} from './initializeRenderHost'; import {initializeRenderHost} from './initializeRenderHost';
import {createFlipperServer} from './flipperServerConnection'; import {createFlipperServer, FlipperServerState} from 'flipper-frontend-core';
document.getElementById('root')!.innerText = 'flipper-ui-browser started'; document.getElementById('root')!.innerText = 'flipper-ui-browser started';
@@ -27,7 +27,21 @@ async function start() {
const logger = createDelegatedLogger(); const logger = createDelegatedLogger();
setLoggerInstance(logger); setLoggerInstance(logger);
const flipperServer = await createFlipperServer(); const flipperServer = await createFlipperServer(
(state: FlipperServerState) => {
switch (state) {
case FlipperServerState.CONNECTING:
window.flipperShowError?.('Connecting to flipper-server...');
break;
case FlipperServerState.CONNECTED:
window?.flipperHideError?.();
break;
case FlipperServerState.DISCONNECTED:
window?.flipperShowError?.('Lost connection to flipper-server');
break;
}
},
);
await flipperServer.connect(); await flipperServer.connect();
const flipperServerConfig = await flipperServer.exec('get-config'); const flipperServerConfig = await flipperServer.exec('get-config');

View File

@@ -10,6 +10,9 @@
{ {
"path": "../flipper-common" "path": "../flipper-common"
}, },
{
"path": "../flipper-frontend-core"
},
{ {
"path": "../flipper-ui-core" "path": "../flipper-ui-core"
} }