Move devices to server folder

Summary:
This is the first of many diffs that extracts the connection, device, client detection out of the flipper core, to create a reusable flipper-server library that can be used in e.g. flipper-dump.

To keep diffs a little smaller, the current connection logic is first moved to the `server/` directory, and decoupled manually from the rest of the core, before moving it over to a separate package.

This first diffs moves the `comms/`, `devices/` and certificate utilities to the `server` directory.

Further untangling will follow in next diffs

Reviewed By: timur-valiev

Differential Revision: D30246551

fbshipit-source-id: c84259bfb1239119b3267a51b015e30c3c080866
This commit is contained in:
Michel Weststrate
2021-08-12 05:42:32 -07:00
committed by Facebook GitHub Bot
parent 5e350add4f
commit 5e8c968222
86 changed files with 273 additions and 172 deletions

View File

@@ -8,7 +8,7 @@
*/ */
import {PluginDefinition} from './plugin'; import {PluginDefinition} from './plugin';
import BaseDevice, {OS} from './devices/BaseDevice'; import BaseDevice, {OS} from './server/devices/BaseDevice';
import {Logger} from './fb-interfaces/Logger'; import {Logger} from './fb-interfaces/Logger';
import {Store} from './reducers/index'; import {Store} from './reducers/index';
import {performance} from 'perf_hooks'; import {performance} from 'perf_hooks';
@@ -16,10 +16,9 @@ import {reportPluginFailures} from './utils/metrics';
import {default as isProduction} from './utils/isProduction'; import {default as isProduction} from './utils/isProduction';
import {EventEmitter} from 'events'; import {EventEmitter} from 'events';
import invariant from 'invariant'; import invariant from 'invariant';
import { import {getPluginKey} from './utils/pluginKey';
getPluginKey,
defaultEnabledBackgroundPlugins, import {defaultEnabledBackgroundPlugins} from './utils/pluginUtils';
} from './utils/pluginUtils';
import {processMessagesLater} from './utils/messageQueue'; import {processMessagesLater} from './utils/messageQueue';
import {emitBytesReceived} from './dispatcher/tracking'; import {emitBytesReceived} from './dispatcher/tracking';
import {debounce} from 'lodash'; import {debounce} from 'lodash';
@@ -36,7 +35,7 @@ import {
ConnectionStatus, ConnectionStatus,
ErrorType, ErrorType,
ClientConnection, ClientConnection,
} from './comms/ClientConnection'; } from './server/comms/ClientConnection';
type Plugins = Set<string>; type Plugins = Set<string>;
type PluginsArr = Array<string>; type PluginsArr = Array<string>;

View File

@@ -9,8 +9,8 @@
import {FlipperPlugin, FlipperDevicePlugin} from './plugin'; import {FlipperPlugin, FlipperDevicePlugin} from './plugin';
import {Logger} from './fb-interfaces/Logger'; import {Logger} from './fb-interfaces/Logger';
import BaseDevice from './devices/BaseDevice'; import BaseDevice from './server/devices/BaseDevice';
import {pluginKey as getPluginKey} from './utils/pluginUtils'; import {pluginKey as getPluginKey} from './utils/pluginKey';
import Client from './Client'; import Client from './Client';
import { import {
ErrorBoundary, ErrorBoundary,

View File

@@ -7,7 +7,7 @@
* @format * @format
*/ */
import {default as BaseDevice} from '../devices/BaseDevice'; import {default as BaseDevice} from '../server/devices/BaseDevice';
import {createMockFlipperWithPlugin} from '../test-utils/createMockFlipperWithPlugin'; import {createMockFlipperWithPlugin} from '../test-utils/createMockFlipperWithPlugin';
import { import {
TestUtils, TestUtils,

View File

@@ -11,7 +11,7 @@ import {Button} from '../ui';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import {State as Store} from '../reducers'; import {State as Store} from '../reducers';
import {launchJsEmulator} from '../utils/js-client-server-utils/serverUtils'; import {launchJsEmulator} from '../server/utils/js-client-server-utils/serverUtils';
import {updateSettings, Action} from '../reducers/settings'; import {updateSettings, Action} from '../reducers/settings';
import {Settings} from '../reducers/settings'; import {Settings} from '../reducers/settings';
import {Collapse, Form, Input as AntInput} from 'antd'; import {Collapse, Form, Input as AntInput} from 'antd';

View File

@@ -8,7 +8,7 @@
*/ */
import React, {useCallback, useEffect, useState} from 'react'; import React, {useCallback, useEffect, useState} from 'react';
import MetroDevice, {MetroReportableEvent} from '../devices/MetroDevice'; import MetroDevice, {MetroReportableEvent} from '../server/devices/MetroDevice';
import {useStore} from '../utils/useStore'; import {useStore} from '../utils/useStore';
import {Button as AntButton} from 'antd'; import {Button as AntButton} from 'antd';
import {MenuOutlined, ReloadOutlined} from '@ant-design/icons'; import {MenuOutlined, ReloadOutlined} from '@ant-design/icons';

View File

@@ -8,7 +8,7 @@
*/ */
import React, {Component} from 'react'; import React, {Component} from 'react';
import BaseDevice from '../devices/BaseDevice'; import BaseDevice from '../server/devices/BaseDevice';
import {Button, Glyph, colors} from '../ui'; import {Button, Glyph, colors} from '../ui';
import path from 'path'; import path from 'path';
import os from 'os'; import os from 'os';

View File

@@ -14,7 +14,7 @@ import {
import configureStore from 'redux-mock-store'; import configureStore from 'redux-mock-store';
import {State, createRootReducer} from '../../reducers/index'; import {State, createRootReducer} from '../../reducers/index';
import {getInstance} from '../../fb-stubs/Logger'; import {getInstance} from '../../fb-stubs/Logger';
import {IOSBridge} from '../../utils/IOSBridge'; import {IOSBridge} from '../../server/utils/IOSBridge';
const mockStore = configureStore<State, {}>([])( const mockStore = configureStore<State, {}>([])(
createRootReducer()(undefined, {type: 'INIT'}), createRootReducer()(undefined, {type: 'INIT'}),

View File

@@ -22,7 +22,7 @@ import {_SandyPluginDefinition as SandyPluginDefinition} from 'flipper-plugin';
import MockFlipper from '../../test-utils/MockFlipper'; import MockFlipper from '../../test-utils/MockFlipper';
import Client from '../../Client'; import Client from '../../Client';
import React from 'react'; import React from 'react';
import BaseDevice from '../../devices/BaseDevice'; import BaseDevice from '../../server/devices/BaseDevice';
const pluginDetails1 = TestUtils.createMockPluginDetails({ const pluginDetails1 = TestUtils.createMockPluginDetails({
id: 'plugin1', id: 'plugin1',

View File

@@ -7,13 +7,13 @@
* @format * @format
*/ */
import AndroidDevice from '../devices/AndroidDevice'; import AndroidDevice from '../server/devices/AndroidDevice';
import KaiOSDevice from '../devices/KaiOSDevice'; import KaiOSDevice from '../server/devices/KaiOSDevice';
import child_process from 'child_process'; import child_process from 'child_process';
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import BaseDevice from '../devices/BaseDevice'; import BaseDevice from '../server/devices/BaseDevice';
import {Logger} from '../fb-interfaces/Logger'; import {Logger} from '../fb-interfaces/Logger';
import {getAdbClient} from '../utils/adbClient'; import {getAdbClient} from '../server/utils/adbClient';
import which from 'which'; import which from 'which';
import {promisify} from 'util'; import {promisify} from 'util';
import {ServerPorts} from '../reducers/application'; import {ServerPorts} from '../reducers/application';
@@ -105,7 +105,7 @@ function createDevice(
export async function getActiveAndroidDevices( export async function getActiveAndroidDevices(
store: Store, store: Store,
): Promise<Array<BaseDevice>> { ): Promise<Array<BaseDevice>> {
const client = await getAdbClient(store); const client = await getAdbClient(store.getState().settingsState);
const androidDevices = await client.listDevices(); const androidDevices = await client.listDevices();
const devices = await Promise.all( const devices = await Promise.all(
androidDevices.map((device) => createDevice(client, device, store)), androidDevices.map((device) => createDevice(client, device, store)),
@@ -169,7 +169,7 @@ export default (store: Store, logger: Logger) => {
console.warn('Failed to query AVDs:', err); console.warn('Failed to query AVDs:', err);
}); });
return getAdbClient(store) return getAdbClient(store.getState().settingsState)
.then((client) => { .then((client) => {
client client
.trackDevices() .trackDevices()
@@ -282,7 +282,7 @@ export default (store: Store, logger: Logger) => {
// cleanup method // cleanup method
return () => return () =>
getAdbClient(store).then((client) => { getAdbClient(store.getState().settingsState).then((client) => {
client.kill(); client.kill();
}); });
}; };

View File

@@ -10,7 +10,7 @@
import {remote, ipcRenderer, IpcRendererEvent} from 'electron'; import {remote, ipcRenderer, IpcRendererEvent} from 'electron';
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import {Logger} from '../fb-interfaces/Logger'; import {Logger} from '../fb-interfaces/Logger';
import {parseFlipperPorts} from '../utils/environmentVariables'; import {parseFlipperPorts} from '../server/utils/environmentVariables';
import { import {
importFileToStore, importFileToStore,
IMPORT_FLIPPER_TRACE_EVENT, IMPORT_FLIPPER_TRACE_EVENT,

View File

@@ -10,8 +10,8 @@
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import {Logger} from '../fb-interfaces/Logger'; import {Logger} from '../fb-interfaces/Logger';
import MacDevice from '../devices/MacDevice'; import MacDevice from '../server/devices/MacDevice';
import WindowsDevice from '../devices/WindowsDevice'; import WindowsDevice from '../server/devices/WindowsDevice';
export default (store: Store, _logger: Logger) => { export default (store: Store, _logger: Logger) => {
let device; let device;

View File

@@ -16,8 +16,8 @@ import {promisify} from 'util';
import path from 'path'; import path from 'path';
import child_process from 'child_process'; import child_process from 'child_process';
const execFile = child_process.execFile; const execFile = child_process.execFile;
import iosUtil from '../utils/iOSContainerUtility'; import iosUtil from '../server/utils/iOSContainerUtility';
import IOSDevice from '../devices/IOSDevice'; import IOSDevice from '../server/devices/IOSDevice';
import {addErrorNotification} from '../reducers/notifications'; import {addErrorNotification} from '../reducers/notifications';
import {getStaticPath} from '../utils/pathUtils'; import {getStaticPath} from '../utils/pathUtils';
import {destroyDevice} from '../reducers/connections'; import {destroyDevice} from '../reducers/connections';
@@ -25,7 +25,7 @@ import {
ERR_NO_IDB_OR_XCODE_AVAILABLE, ERR_NO_IDB_OR_XCODE_AVAILABLE,
IOSBridge, IOSBridge,
makeIOSBridge, makeIOSBridge,
} from '../utils/IOSBridge'; } from '../server/utils/IOSBridge';
type iOSSimulatorDevice = { type iOSSimulatorDevice = {
state: 'Booted' | 'Shutdown' | 'Shutting Down'; state: 'Booted' | 'Shutdown' | 'Shutting Down';

View File

@@ -9,11 +9,11 @@
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import {Logger} from '../fb-interfaces/Logger'; import {Logger} from '../fb-interfaces/Logger';
import MetroDevice from '../devices/MetroDevice'; import MetroDevice from '../server/devices/MetroDevice';
import http from 'http'; import http from 'http';
import {addErrorNotification} from '../reducers/notifications'; import {addErrorNotification} from '../reducers/notifications';
import {destroyDevice} from '../reducers/connections'; import {destroyDevice} from '../reducers/connections';
import {parseEnvironmentVariableAsNumber} from '../utils/environmentVariables'; import {parseEnvironmentVariableAsNumber} from '../server/utils/environmentVariables';
const METRO_HOST = 'localhost'; const METRO_HOST = 'localhost';
const METRO_PORT = parseEnvironmentVariableAsNumber('METRO_SERVER_PORT', 8081); const METRO_PORT = parseEnvironmentVariableAsNumber('METRO_SERVER_PORT', 8081);

View File

@@ -44,10 +44,10 @@ import {
import {deconstructClientId} from '../utils/clientUtils'; import {deconstructClientId} from '../utils/clientUtils';
import {clearMessageQueue} from '../reducers/pluginMessageQueue'; import {clearMessageQueue} from '../reducers/pluginMessageQueue';
import { import {
getPluginKey,
isDevicePluginDefinition, isDevicePluginDefinition,
defaultEnabledBackgroundPlugins, defaultEnabledBackgroundPlugins,
} from '../utils/pluginUtils'; } from '../utils/pluginUtils';
import {getPluginKey} from '../utils/pluginKey';
const maxInstalledPluginVersionsToKeep = 2; const maxInstalledPluginVersionsToKeep = 2;

View File

@@ -8,7 +8,7 @@
*/ */
import {remote} from 'electron'; import {remote} from 'electron';
import MetroDevice from '../devices/MetroDevice'; import MetroDevice from '../server/devices/MetroDevice';
import {Store} from '../reducers'; import {Store} from '../reducers';
type ShortcutEventCommand = type ShortcutEventCommand =

View File

@@ -7,14 +7,14 @@
* @format * @format
*/ */
import ServerController from '../comms/ServerController'; import ServerController from '../server/comms/ServerController';
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import {Logger} from '../fb-interfaces/Logger'; import {Logger} from '../fb-interfaces/Logger';
import Client from '../Client'; import Client from '../Client';
import {UninitializedClient} from '../UninitializedClient'; import {UninitializedClient} from '../UninitializedClient';
import {addErrorNotification} from '../reducers/notifications'; import {addErrorNotification} from '../reducers/notifications';
import {CertificateExchangeMedium} from '../utils/CertificateProvider'; import {CertificateExchangeMedium} from '../server/utils/CertificateProvider';
import {selectClient, selectDevice} from '../reducers/connections'; import {selectClient, selectDevice} from '../reducers/connections';
import {isLoggedIn} from '../fb-stubs/user'; import {isLoggedIn} from '../fb-stubs/user';
import React from 'react'; import React from 'react';

View File

@@ -25,7 +25,7 @@ import {
selectionChanged, selectionChanged,
} from '../reducers/usageTracking'; } from '../reducers/usageTracking';
import produce from 'immer'; import produce from 'immer';
import BaseDevice from '../devices/BaseDevice'; import BaseDevice from '../server/devices/BaseDevice';
import {deconstructClientId} from '../utils/clientUtils'; import {deconstructClientId} from '../utils/clientUtils';
import {getCPUUsage} from 'process'; import {getCPUUsage} from 'process';
import {sideEffect} from '../utils/sideEffect'; import {sideEffect} from '../utils/sideEffect';

View File

@@ -7,7 +7,7 @@
* @format * @format
*/ */
import {OS} from '../devices/BaseDevice'; import {OS} from '../server/devices/BaseDevice';
export default Object.freeze({ export default Object.freeze({
GRAPH_APP_ID: '', GRAPH_APP_ID: '',

View File

@@ -30,19 +30,19 @@ export {reportUsage} from './utils/metrics';
export {default as promiseTimeout} from './utils/promiseTimeout'; export {default as promiseTimeout} from './utils/promiseTimeout';
export {clipboard, remote, OpenDialogOptions} from 'electron'; export {clipboard, remote, OpenDialogOptions} from 'electron';
export {bufferToBlob} from './utils/screenshot'; export {bufferToBlob} from './utils/screenshot';
export {getPluginKey} from './utils/pluginUtils'; export {getPluginKey} from './utils/pluginKey';
export {Notification, Idler} from 'flipper-plugin'; export {Notification, Idler} from 'flipper-plugin';
export {IdlerImpl} from './utils/Idler'; export {IdlerImpl} from './utils/Idler';
export {Store, State as ReduxState} from './reducers/index'; export {Store, State as ReduxState} from './reducers/index';
export {default as BaseDevice} from './devices/BaseDevice'; export {default as BaseDevice} from './server/devices/BaseDevice';
export {default as isProduction} from './utils/isProduction'; export {default as isProduction} from './utils/isProduction';
export {DetailSidebar} from 'flipper-plugin'; export {DetailSidebar} from 'flipper-plugin';
export {default as Device} from './devices/BaseDevice'; export {default as Device} from './server/devices/BaseDevice';
export {default as AndroidDevice} from './devices/AndroidDevice'; export {default as AndroidDevice} from './server/devices/AndroidDevice';
export {default as ArchivedDevice} from './devices/ArchivedDevice'; export {default as ArchivedDevice} from './server/devices/ArchivedDevice';
export {default as IOSDevice} from './devices/IOSDevice'; export {default as IOSDevice} from './server/devices/IOSDevice';
export {default as KaiOSDevice} from './devices/KaiOSDevice'; export {default as KaiOSDevice} from './server/devices/KaiOSDevice';
export {OS} from './devices/BaseDevice'; export {OS} from './server/devices/BaseDevice';
export {default as Button} from './ui/components/Button'; export {default as Button} from './ui/components/Button';
export {default as ToggleButton} from './ui/components/ToggleSwitch'; export {default as ToggleButton} from './ui/components/ToggleSwitch';
export {default as ButtonGroup} from './ui/components/ButtonGroup'; export {default as ButtonGroup} from './ui/components/ButtonGroup';
@@ -129,7 +129,7 @@ export {Rect} from './utils/geometry';
export {Logger} from './fb-interfaces/Logger'; export {Logger} from './fb-interfaces/Logger';
export {getInstance as getLogger} from './fb-stubs/Logger'; export {getInstance as getLogger} from './fb-stubs/Logger';
export {callVSCode} from './utils/vscodeUtils'; export {callVSCode} from './utils/vscodeUtils';
export {checkIdbIsInstalled} from './utils/iOSContainerUtility'; export {checkIdbIsInstalled} from './server/utils/iOSContainerUtility';
export {IDEFileResolver, IDEType} from './fb-stubs/IDEFileResolver'; export {IDEFileResolver, IDEType} from './fb-stubs/IDEFileResolver';
export {renderMockFlipperWithPlugin} from './test-utils/createMockFlipperWithPlugin'; export {renderMockFlipperWithPlugin} from './test-utils/createMockFlipperWithPlugin';
export {Tracked} from 'flipper-plugin'; // To be able to use it in legacy plugins export {Tracked} from 'flipper-plugin'; // To be able to use it in legacy plugins

View File

@@ -11,7 +11,7 @@ import {KeyboardActions} from './MenuBar';
import {Logger} from './fb-interfaces/Logger'; import {Logger} from './fb-interfaces/Logger';
import Client from './Client'; import Client from './Client';
import {Component} from 'react'; import {Component} from 'react';
import BaseDevice from './devices/BaseDevice'; import BaseDevice from './server/devices/BaseDevice';
import {StaticView} from './reducers/connections'; import {StaticView} from './reducers/connections';
import {State as ReduxState} from './reducers'; import {State as ReduxState} from './reducers';
import {DEFAULT_MAX_QUEUE_SIZE} from './reducers/pluginMessageQueue'; import {DEFAULT_MAX_QUEUE_SIZE} from './reducers/pluginMessageQueue';

View File

@@ -9,10 +9,10 @@
import reducer from '../connections'; import reducer from '../connections';
import {State, selectPlugin} from '../connections'; import {State, selectPlugin} from '../connections';
import BaseDevice from '../../devices/BaseDevice'; import BaseDevice from '../../server/devices/BaseDevice';
import MacDevice from '../../devices/MacDevice'; import MacDevice from '../../server/devices/MacDevice';
import {FlipperDevicePlugin} from '../../plugin'; import {FlipperDevicePlugin} from '../../plugin';
import MetroDevice from '../../devices/MetroDevice'; import MetroDevice from '../../server/devices/MetroDevice';
import {TestUtils, _setFlipperLibImplementation} from 'flipper-plugin'; import {TestUtils, _setFlipperLibImplementation} from 'flipper-plugin';
import {wrapSandy} from '../../test-utils/createMockFlipperWithPlugin'; import {wrapSandy} from '../../test-utils/createMockFlipperWithPlugin';
import {createMockFlipperLib} from 'flipper-plugin/src/test-utils/test-utils'; import {createMockFlipperLib} from 'flipper-plugin/src/test-utils/test-utils';

View File

@@ -10,18 +10,20 @@
import {ComponentType} from 'react'; import {ComponentType} from 'react';
import {produce} from 'immer'; import {produce} from 'immer';
import type BaseDevice from '../devices/BaseDevice'; import type BaseDevice from '../server/devices/BaseDevice';
import MacDevice from '../devices/MacDevice'; import MacDevice from '../server/devices/MacDevice';
import type Client from '../Client'; import type Client from '../Client';
import type {UninitializedClient} from '../UninitializedClient'; import type {UninitializedClient} from '../UninitializedClient';
import {isEqual} from 'lodash'; import {isEqual} from 'lodash';
import {performance} from 'perf_hooks'; import {performance} from 'perf_hooks';
import type {Actions, Store} from '.'; import type {Actions, Store} from '.';
import {WelcomeScreenStaticView} from '../sandy-chrome/WelcomeScreen'; import {WelcomeScreenStaticView} from '../sandy-chrome/WelcomeScreen';
import {getPluginKey, isDevicePluginDefinition} from '../utils/pluginUtils'; import {isDevicePluginDefinition} from '../utils/pluginUtils';
import {getPluginKey} from '../utils/pluginKey';
import {deconstructClientId} from '../utils/clientUtils'; import {deconstructClientId} from '../utils/clientUtils';
import type {RegisterPluginAction} from './plugins'; import type {RegisterPluginAction} from './plugins';
import MetroDevice from '../devices/MetroDevice'; import MetroDevice from '../server/devices/MetroDevice';
import {Logger} from 'flipper-plugin'; import {Logger} from 'flipper-plugin';
export type StaticViewProps = {logger: Logger}; export type StaticViewProps = {logger: Logger};

View File

@@ -18,7 +18,7 @@ import constants from '../fb-stubs/constants';
import {getInstance} from '../fb-stubs/Logger'; import {getInstance} from '../fb-stubs/Logger';
import {logPlatformSuccessRate} from '../utils/metrics'; import {logPlatformSuccessRate} from '../utils/metrics';
export const SUPPORT_FORM_PREFIX = 'support-form-v2'; export const SUPPORT_FORM_PREFIX = 'support-form-v2';
import {OS} from '../devices/BaseDevice'; import {OS} from '../server/devices/BaseDevice';
import {getExportablePlugins} from '../selectors/connections'; import {getExportablePlugins} from '../selectors/connections';
const {DEFAULT_SUPPORT_GROUP} = constants; const {DEFAULT_SUPPORT_GROUP} = constants;

View File

@@ -18,7 +18,7 @@ import ScreenCaptureButtons from '../../chrome/ScreenCaptureButtons';
import MetroButton from '../../chrome/MetroButton'; import MetroButton from '../../chrome/MetroButton';
import {BookmarkSection} from './BookmarkSection'; import {BookmarkSection} from './BookmarkSection';
import Client from '../../Client'; import Client from '../../Client';
import BaseDevice from '../../devices/BaseDevice'; import BaseDevice from '../../server/devices/BaseDevice';
import {ExclamationCircleOutlined, FieldTimeOutlined} from '@ant-design/icons'; import {ExclamationCircleOutlined, FieldTimeOutlined} from '@ant-design/icons';
import {useSelector} from 'react-redux'; import {useSelector} from 'react-redux';
import { import {

View File

@@ -25,7 +25,7 @@ import {
selectClient, selectClient,
selectDevice, selectDevice,
} from '../../reducers/connections'; } from '../../reducers/connections';
import BaseDevice, {OS} from '../../devices/BaseDevice'; import BaseDevice, {OS} from '../../server/devices/BaseDevice';
import Client from '../../Client'; import Client from '../../Client';
import {State} from '../../reducers'; import {State} from '../../reducers';
import {brandColors, brandIcons, colors} from '../../ui/components/colors'; import {brandColors, brandIcons, colors} from '../../ui/components/colors';

View File

@@ -17,7 +17,7 @@ import {
} from '@ant-design/icons'; } from '@ant-design/icons';
import {Store} from '../../reducers'; import {Store} from '../../reducers';
import {useStore} from '../../utils/useStore'; import {useStore} from '../../utils/useStore';
import {launchEmulator} from '../../devices/AndroidDevice'; import {launchEmulator} from '../../server/devices/AndroidDevice';
import {Layout, renderReactRoot, withTrackingScope} from 'flipper-plugin'; import {Layout, renderReactRoot, withTrackingScope} from 'flipper-plugin';
import {Provider} from 'react-redux'; import {Provider} from 'react-redux';
import { import {

View File

@@ -23,9 +23,9 @@ import {useDispatch, useStore} from '../../utils/useStore';
import {getPluginTitle, getPluginTooltip} from '../../utils/pluginUtils'; import {getPluginTitle, getPluginTooltip} from '../../utils/pluginUtils';
import {selectPlugin} from '../../reducers/connections'; import {selectPlugin} from '../../reducers/connections';
import Client from '../../Client'; import Client from '../../Client';
import BaseDevice from '../../devices/BaseDevice'; import BaseDevice from '../../server/devices/BaseDevice';
import {DownloadablePluginDetails} from 'flipper-plugin-lib'; import {DownloadablePluginDetails} from 'flipper-plugin-lib';
import MetroDevice from '../../devices/MetroDevice'; import MetroDevice from '../../server/devices/MetroDevice';
import { import {
DownloadablePluginState, DownloadablePluginState,
PluginDownloadStatus, PluginDownloadStatus,

View File

@@ -17,11 +17,11 @@ import {createRootReducer} from '../../../reducers';
import {act} from 'react-dom/test-utils'; import {act} from 'react-dom/test-utils';
import {sleep} from 'flipper-plugin'; import {sleep} from 'flipper-plugin';
jest.mock('../../../devices/AndroidDevice', () => ({ jest.mock('../../../server/devices/AndroidDevice', () => ({
launchEmulator: jest.fn(() => Promise.resolve([])), launchEmulator: jest.fn(() => Promise.resolve([])),
})); }));
import {launchEmulator} from '../../../devices/AndroidDevice'; import {launchEmulator} from '../../../server/devices/AndroidDevice';
test('Can render and launch android apps', async () => { test('Can render and launch android apps', async () => {
const store = createStore(createRootReducer()); const store = createStore(createRootReducer());

View File

@@ -12,8 +12,8 @@ import {
MockFlipperResult, MockFlipperResult,
} from '../../../test-utils/createMockFlipperWithPlugin'; } from '../../../test-utils/createMockFlipperWithPlugin';
import {FlipperPlugin} from '../../../plugin'; import {FlipperPlugin} from '../../../plugin';
import MetroDevice from '../../../devices/MetroDevice'; import MetroDevice from '../../../server/devices/MetroDevice';
import BaseDevice from '../../../devices/BaseDevice'; import BaseDevice from '../../../server/devices/BaseDevice';
import {_SandyPluginDefinition} from 'flipper-plugin'; import {_SandyPluginDefinition} from 'flipper-plugin';
import {TestUtils} from 'flipper-plugin'; import {TestUtils} from 'flipper-plugin';
import {selectPlugin} from '../../../reducers/connections'; import {selectPlugin} from '../../../reducers/connections';

View File

@@ -7,7 +7,7 @@
* @format * @format
*/ */
import MetroDevice from '../devices/MetroDevice'; import MetroDevice from '../server/devices/MetroDevice';
import {State} from '../reducers'; import {State} from '../reducers';
import { import {
computePluginLists, computePluginLists,

View File

@@ -0,0 +1,31 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
/**
* A set of utilities that should be provided by the hosting environment
*/
export interface FlipperServerHost {}
let instance: FlipperServerHost | undefined;
export function getFlipperServerHost(): FlipperServerHost {
if (!instance) {
throw new Error(
'FlipperServerHost not set, call setFlipperServerHost first',
);
}
return instance;
}
export function setFlipperServerHost(impl: FlipperServerHost) {
if (instance) {
throw new Error('FlipperServerHost was already set');
}
instance = impl;
}

View File

@@ -11,7 +11,7 @@ import {
CertificateExchangeMedium, CertificateExchangeMedium,
SecureServerConfig, SecureServerConfig,
} from '../utils/CertificateProvider'; } from '../utils/CertificateProvider';
import Client, {ClientQuery} from '../Client'; import Client, {ClientQuery} from '../../Client';
import {ClientConnection} from './ClientConnection'; import {ClientConnection} from './ClientConnection';
import {transformCertificateExchangeMediumToType} from './Utilities'; import {transformCertificateExchangeMediumToType} from './Utilities';

View File

@@ -8,23 +8,23 @@
*/ */
import {CertificateExchangeMedium} from '../utils/CertificateProvider'; import {CertificateExchangeMedium} from '../utils/CertificateProvider';
import {Logger} from '../fb-interfaces/Logger'; import {Logger} from '../../fb-interfaces/Logger';
import {ClientQuery} from '../Client'; import {ClientQuery} from '../../Client';
import {Store, State} from '../reducers/index'; import {Store, State} from '../../reducers/index';
import CertificateProvider from '../utils/CertificateProvider'; import CertificateProvider from '../utils/CertificateProvider';
import Client from '../Client'; import Client from '../../Client';
import {ClientConnection, ConnectionStatus} from './ClientConnection'; import {ClientConnection, ConnectionStatus} from './ClientConnection';
import {UninitializedClient} from '../UninitializedClient'; import {UninitializedClient} from '../../UninitializedClient';
import {reportPlatformFailures} from '../utils/metrics'; import {reportPlatformFailures} from '../../utils/metrics';
import {EventEmitter} from 'events'; import {EventEmitter} from 'events';
import invariant from 'invariant'; import invariant from 'invariant';
import GK from '../fb-stubs/GK'; import GK from '../../fb-stubs/GK';
import {initJsEmulatorIPC} from '../utils/js-client-server-utils/serverUtils'; import {initJsEmulatorIPC} from '../utils/js-client-server-utils/serverUtils';
import {buildClientId} from '../utils/clientUtils'; import {buildClientId} from '../../utils/clientUtils';
import JSDevice from '../devices/JSDevice'; import JSDevice from '../../server/devices/JSDevice';
import DummyDevice from '../devices/DummyDevice'; import DummyDevice from '../../server/devices/DummyDevice';
import BaseDevice from '../devices/BaseDevice'; import BaseDevice from '../../server/devices/BaseDevice';
import {sideEffect} from '../utils/sideEffect'; import {sideEffect} from '../../utils/sideEffect';
import { import {
appNameWithUpdateHint, appNameWithUpdateHint,
transformCertificateExchangeMediumToType, transformCertificateExchangeMediumToType,
@@ -79,7 +79,11 @@ class ServerController extends EventEmitter implements ServerEventsListener {
super(); super();
this.logger = logger; this.logger = logger;
this.connections = new Map(); this.connections = new Map();
this.certificateProvider = new CertificateProvider(this, logger, store); this.certificateProvider = new CertificateProvider(
this,
logger,
store.getState().settingsState,
);
this.connectionTracker = new ConnectionTracker(logger); this.connectionTracker = new ConnectionTracker(logger);
this.secureServer = null; this.secureServer = null;
this.insecureServer = null; this.insecureServer = null;

View File

@@ -7,7 +7,7 @@
* @format * @format
*/ */
import GK from '../fb-stubs/GK'; import GK from '../../fb-stubs/GK';
import {SecureServerConfig} from '../utils/CertificateProvider'; import {SecureServerConfig} from '../utils/CertificateProvider';
import ServerAdapter, {ServerEventsListener} from './ServerAdapter'; import ServerAdapter, {ServerEventsListener} from './ServerAdapter';
import ServerRSocket from './ServerRSocket'; import ServerRSocket from './ServerRSocket';

View File

@@ -17,7 +17,7 @@ import net, {Socket} from 'net';
import {RSocketServer} from 'rsocket-core'; import {RSocketServer} from 'rsocket-core';
import RSocketTCPServer from 'rsocket-tcp-server'; import RSocketTCPServer from 'rsocket-tcp-server';
import {Payload, ReactiveSocket, Responder} from 'rsocket-types'; import {Payload, ReactiveSocket, Responder} from 'rsocket-types';
import Client, {ClientQuery} from '../Client'; import Client, {ClientQuery} from '../../Client';
import {Single} from 'rsocket-flowable'; import {Single} from 'rsocket-flowable';
import { import {
ClientConnection, ClientConnection,

View File

@@ -12,7 +12,7 @@ import WebSocket from 'ws';
import ws from 'ws'; import ws from 'ws';
import {SecureClientQuery, ServerEventsListener} from './ServerAdapter'; import {SecureClientQuery, ServerEventsListener} from './ServerAdapter';
import querystring from 'querystring'; import querystring from 'querystring';
import Client, {ClientQuery} from '../Client'; import Client, {ClientQuery} from '../../Client';
import {OS} from '../devices/BaseDevice'; import {OS} from '../devices/BaseDevice';
import { import {
ClientConnection, ClientConnection,

View File

@@ -10,10 +10,10 @@
import ServerWebSocketBase from './ServerWebSocketBase'; import ServerWebSocketBase from './ServerWebSocketBase';
import WebSocket from 'ws'; import WebSocket from 'ws';
import querystring from 'querystring'; import querystring from 'querystring';
import Client, {ClientQuery} from '../Client'; import Client, {ClientQuery} from '../../Client';
import {BrowserClientFlipperConnection} from './BrowserClientFlipperConnection'; import {BrowserClientFlipperConnection} from './BrowserClientFlipperConnection';
import {ServerEventsListener} from './ServerAdapter'; import {ServerEventsListener} from './ServerAdapter';
import constants from '../fb-stubs/constants'; import constants from '../../fb-stubs/constants';
import ws from 'ws'; import ws from 'ws';
import {IncomingMessage} from 'http'; import {IncomingMessage} from 'http';

View File

@@ -8,7 +8,7 @@
*/ */
import {CertificateExchangeMedium} from '../utils/CertificateProvider'; import {CertificateExchangeMedium} from '../utils/CertificateProvider';
import {ClientQuery} from '../Client'; import {ClientQuery} from '../../Client';
/** /**
* Transforms the certificate exchange medium type as number to the * Transforms the certificate exchange medium type as number to the

View File

@@ -10,7 +10,7 @@
import BaseDevice from './BaseDevice'; import BaseDevice from './BaseDevice';
import type {DeviceType} from 'flipper-plugin'; import type {DeviceType} from 'flipper-plugin';
import {OS, DeviceShell} from './BaseDevice'; import {OS, DeviceShell} from './BaseDevice';
import {SupportFormRequestDetailsState} from '../reducers/supportForm'; import {SupportFormRequestDetailsState} from '../../reducers/supportForm';
export default class ArchivedDevice extends BaseDevice { export default class ArchivedDevice extends BaseDevice {
isArchived = true; isArchived = true;

View File

@@ -18,8 +18,8 @@ import {
createState, createState,
getFlipperLib, getFlipperLib,
} from 'flipper-plugin'; } from 'flipper-plugin';
import {PluginDefinition, DevicePluginMap} from '../plugin';
import {DeviceSpec, OS as PluginOS, PluginDetails} from 'flipper-plugin-lib'; import {DeviceSpec, OS as PluginOS, PluginDetails} from 'flipper-plugin-lib';
import {getPluginKey} from '../../utils/pluginKey';
export type DeviceShell = { export type DeviceShell = {
stdout: stream.Readable; stdout: stream.Readable;
@@ -29,6 +29,9 @@ export type DeviceShell = {
export type OS = PluginOS | 'Windows' | 'MacOS' | 'JSWebApp'; export type OS = PluginOS | 'Windows' | 'MacOS' | 'JSWebApp';
type PluginDefinition = _SandyPluginDefinition;
type PluginMap = Map<string, PluginDefinition>;
export type DeviceExport = { export type DeviceExport = {
os: OS; os: OS;
title: string; title: string;
@@ -80,6 +83,7 @@ export default class BaseDevice {
// if imported, stores the original source location // if imported, stores the original source location
source = ''; source = '';
// TODO: ideally we don't want BasePlugin to know about the concept of plugins
sandyPluginStates: Map<string, _SandyDevicePluginInstance> = new Map< sandyPluginStates: Map<string, _SandyDevicePluginInstance> = new Map<
string, string,
_SandyDevicePluginInstance _SandyDevicePluginInstance
@@ -221,7 +225,7 @@ export default class BaseDevice {
} }
loadDevicePlugins( loadDevicePlugins(
devicePlugins: DevicePluginMap, devicePlugins: PluginMap,
enabledDevicePlugins: Set<string>, enabledDevicePlugins: Set<string>,
pluginStates?: Record<string, any>, pluginStates?: Record<string, any>,
) { ) {
@@ -249,11 +253,7 @@ export default class BaseDevice {
plugin, plugin,
this, this,
// break circular dep, one of those days again... // break circular dep, one of those days again...
require('../utils/pluginUtils').getPluginKey( getPluginKey(undefined, {serial: this.serial}, plugin.id),
undefined,
{serial: this.serial},
plugin.id,
),
initialState, initialState,
), ),
); );

View File

@@ -7,13 +7,12 @@
* @format * @format
*/ */
import type {LogLevel, DeviceLogEntry, DeviceType} from 'flipper-plugin'; import {LogLevel, DeviceLogEntry, DeviceType, timeout} from 'flipper-plugin';
import child_process, {ChildProcess} from 'child_process'; import child_process, {ChildProcess} from 'child_process';
import BaseDevice from './BaseDevice'; import BaseDevice from './BaseDevice';
import JSONStream from 'JSONStream'; import JSONStream from 'JSONStream';
import {Transform} from 'stream'; import {Transform} from 'stream';
import {exec} from 'promisify-child-process'; import {exec} from 'promisify-child-process';
import {default as promiseTimeout} from '../utils/promiseTimeout';
import { import {
ERR_PHYSICAL_DEVICE_LOGS_WITHOUT_IDB, ERR_PHYSICAL_DEVICE_LOGS_WITHOUT_IDB,
IOSBridge, IOSBridge,
@@ -230,7 +229,7 @@ export default class IOSDevice extends BaseDevice {
this.recordingProcess!.kill('SIGINT'); this.recordingProcess!.kill('SIGINT');
}); });
const output: string | null = await promiseTimeout<void>( const output: string | null = await timeout<void>(
5000, 5000,
prom, prom,
'Timed out to stop a screen capture.', 'Timed out to stop a screen capture.',

View File

@@ -8,11 +8,11 @@
*/ */
import BaseDevice from '../BaseDevice'; import BaseDevice from '../BaseDevice';
import * as DeviceTestPluginModule from '../../test-utils/DeviceTestPlugin'; import * as DeviceTestPluginModule from '../../../test-utils/DeviceTestPlugin';
import {TestUtils, _SandyPluginDefinition} from 'flipper-plugin'; import {TestUtils, _SandyPluginDefinition} from 'flipper-plugin';
import ArchivedDevice from '../ArchivedDevice'; import ArchivedDevice from '../ArchivedDevice';
import DummyDevice from '../DummyDevice'; import DummyDevice from '../DummyDevice';
import {createMockFlipperWithPlugin} from '../../test-utils/createMockFlipperWithPlugin'; import {createMockFlipperWithPlugin} from '../../../test-utils/createMockFlipperWithPlugin';
const physicalDevicePluginDetails = TestUtils.createMockPluginDetails({ const physicalDevicePluginDetails = TestUtils.createMockPluginDetails({
id: 'physicalDevicePlugin', id: 'physicalDevicePlugin',

View File

@@ -7,8 +7,8 @@
* @format * @format
*/ */
import {Logger} from '../fb-interfaces/Logger'; import {Logger} from '../../fb-interfaces/Logger';
import {internGraphPOSTAPIRequest} from '../fb-stubs/user'; import {internGraphPOSTAPIRequest} from '../../fb-stubs/user';
import ServerController from '../comms/ServerController'; import ServerController from '../comms/ServerController';
import {promisify} from 'util'; import {promisify} from 'util';
import fs from 'fs'; import fs from 'fs';
@@ -21,14 +21,13 @@ import {
import path from 'path'; import path from 'path';
import tmp, {DirOptions, FileOptions} from 'tmp'; import tmp, {DirOptions, FileOptions} from 'tmp';
import iosUtil from './iOSContainerUtility'; import iosUtil from './iOSContainerUtility';
import {reportPlatformFailures} from './metrics'; import {reportPlatformFailures} from '../../utils/metrics';
import {getAdbClient} from './adbClient'; import {getAdbClient} from './adbClient';
import * as androidUtil from './androidContainerUtility'; import * as androidUtil from './androidContainerUtility';
import os from 'os'; import os from 'os';
import {Client as ADBClient} from 'adbkit'; import {Client as ADBClient} from 'adbkit';
import {Store} from '../reducers/index';
import archiver from 'archiver'; import archiver from 'archiver';
import promiseTimeout from '../utils/promiseTimeout'; import {timeout} from 'flipper-plugin';
import {v4 as uuid} from 'uuid'; import {v4 as uuid} from 'uuid';
export type CertificateExchangeMedium = 'FS_ACCESS' | 'WWW'; export type CertificateExchangeMedium = 'FS_ACCESS' | 'WWW';
@@ -71,6 +70,12 @@ export type SecureServerConfig = {
rejectUnauthorized: boolean; rejectUnauthorized: boolean;
}; };
type CertificateProviderConfig = {
idbPath: string;
androidHome: string;
enablePhysicalIOS: boolean;
};
/* /*
* This class is responsible for generating and deploying server and client * This class is responsible for generating and deploying server and client
* certificates to allow for secure communication between Flipper and apps. * certificates to allow for secure communication between Flipper and apps.
@@ -86,17 +91,21 @@ export default class CertificateProvider {
logger: Logger; logger: Logger;
adb: Promise<ADBClient>; adb: Promise<ADBClient>;
certificateSetup: Promise<void>; certificateSetup: Promise<void>;
store: Store; config: CertificateProviderConfig;
server: ServerController; server: ServerController;
constructor(server: ServerController, logger: Logger, store: Store) { constructor(
server: ServerController,
logger: Logger,
config: CertificateProviderConfig,
) {
this.logger = logger; this.logger = logger;
this.adb = getAdbClient(store); this.adb = getAdbClient(config);
this.certificateSetup = reportPlatformFailures( this.certificateSetup = reportPlatformFailures(
this.ensureServerCertExists(), this.ensureServerCertExists(),
'ensureServerCertExists', 'ensureServerCertExists',
); );
this.store = store; this.config = config;
this.server = server; this.server = server;
} }
@@ -104,7 +113,7 @@ export default class CertificateProvider {
const buff = await fsExtra.readFile(zipPath); const buff = await fsExtra.readFile(zipPath);
const file = new File([buff], 'certs.zip'); const file = new File([buff], 'certs.zip');
return reportPlatformFailures( return reportPlatformFailures(
promiseTimeout( timeout(
5 * 60 * 1000, 5 * 60 * 1000,
internGraphPOSTAPIRequest('flipper/certificates', { internGraphPOSTAPIRequest('flipper/certificates', {
certificate_zip: file, certificate_zip: file,
@@ -345,7 +354,7 @@ export default class CertificateProvider {
filePath, filePath,
bundleId, bundleId,
destination, destination,
this.store.getState().settingsState.idbPath, this.config.idbPath,
), ),
); );
}); });
@@ -421,10 +430,7 @@ export default class CertificateProvider {
return Promise.resolve(matches[1]); return Promise.resolve(matches[1]);
} }
return iosUtil return iosUtil
.targets( .targets(this.config.idbPath, this.config.enablePhysicalIOS)
this.store.getState().settingsState.idbPath,
this.store.getState().settingsState.enablePhysicalIOS,
)
.then((targets) => { .then((targets) => {
if (targets.length === 0) { if (targets.length === 0) {
throw new Error('No iOS devices found'); throw new Error('No iOS devices found');
@@ -493,7 +499,7 @@ export default class CertificateProvider {
originalFile, originalFile,
bundleId, bundleId,
path.join(dir, csrFileName), path.join(dir, csrFileName),
this.store.getState().settingsState.idbPath, this.config.idbPath,
) )
.then(() => dir); .then(() => dir);
}) })

View File

@@ -13,7 +13,7 @@ import {DeviceType} from 'flipper-plugin-lib';
import {v1 as uuid} from 'uuid'; import {v1 as uuid} from 'uuid';
import path from 'path'; import path from 'path';
import {exec} from 'promisify-child-process'; import {exec} from 'promisify-child-process';
import {getAppTempPath} from '../utils/pathUtils'; import {getAppTempPath} from '../../utils/pathUtils';
export const ERR_NO_IDB_OR_XCODE_AVAILABLE = export const ERR_NO_IDB_OR_XCODE_AVAILABLE =
'Neither Xcode nor idb available. Cannot provide iOS device functionality.'; 'Neither Xcode nor idb available. Cannot provide iOS device functionality.';

View File

@@ -7,20 +7,23 @@
* @format * @format
*/ */
import {reportPlatformFailures} from './metrics'; import {reportPlatformFailures} from '../../utils/metrics';
import {execFile} from 'promisify-child-process'; import {execFile} from 'promisify-child-process';
import promiseRetry from 'promise-retry'; import promiseRetry from 'promise-retry';
import adbConfig from '../utils/adbConfig'; import adbConfig from '../utils/adbConfig';
import adbkit, {Client} from 'adbkit'; import adbkit, {Client} from 'adbkit';
import {Store} from '../reducers/index';
import path from 'path'; import path from 'path';
const MAX_RETRIES = 5; const MAX_RETRIES = 5;
let instance: Promise<Client>; let instance: Promise<Client>;
export function getAdbClient(store: Store): Promise<Client> { type Config = {
androidHome: string;
};
export function getAdbClient(config: Config): Promise<Client> {
if (!instance) { if (!instance) {
instance = reportPlatformFailures(createClient(store), 'createADBClient'); instance = reportPlatformFailures(createClient(config), 'createADBClient');
} }
return instance; return instance;
} }
@@ -28,8 +31,8 @@ export function getAdbClient(store: Store): Promise<Client> {
/* Adbkit will attempt to start the adb server if it's not already running, /* Adbkit will attempt to start the adb server if it's not already running,
however, it sometimes fails with ENOENT errors. So instead, we start it however, it sometimes fails with ENOENT errors. So instead, we start it
manually before requesting a client. */ manually before requesting a client. */
function createClient(store: Store): Promise<Client> { function createClient(config: Config): Promise<Client> {
const androidHome = store.getState().settingsState.androidHome; const androidHome = config.androidHome;
const adbPath = path.resolve(androidHome, 'platform-tools/adb'); const adbPath = path.resolve(androidHome, 'platform-tools/adb');
return reportPlatformFailures<Client>( return reportPlatformFailures<Client>(
execFile(adbPath, ['start-server']).then(() => execFile(adbPath, ['start-server']).then(() =>

View File

@@ -12,7 +12,7 @@
* opaque types will ensure the commands are only ever run on validated * opaque types will ensure the commands are only ever run on validated
* arguments. * arguments.
*/ */
import {UnsupportedError} from './metrics'; import {UnsupportedError} from '../../utils/metrics';
import adbkit, {Client} from 'adbkit'; import adbkit, {Client} from 'adbkit';
const allowedAppNameRegex = /^[\w.-]+$/; const allowedAppNameRegex = /^[\w.-]+$/;

View File

@@ -11,7 +11,7 @@ import React from 'react';
import {Mutex} from 'async-mutex'; import {Mutex} from 'async-mutex';
import {exec as unsafeExec, Output} from 'promisify-child-process'; import {exec as unsafeExec, Output} from 'promisify-child-process';
import {killOrphanedInstrumentsProcesses} from './processCleanup'; import {killOrphanedInstrumentsProcesses} from './processCleanup';
import {reportPlatformFailures} from './metrics'; import {reportPlatformFailures} from '../../utils/metrics';
import {promises, constants} from 'fs'; import {promises, constants} from 'fs';
import memoize from 'lodash.memoize'; import memoize from 'lodash.memoize';
import {notNull} from './typeUtils'; import {notNull} from './typeUtils';
@@ -19,7 +19,7 @@ import {promisify} from 'util';
import child_process from 'child_process'; import child_process from 'child_process';
import fs from 'fs-extra'; import fs from 'fs-extra';
import path from 'path'; import path from 'path';
import fbConfig from '../fb-stubs/config'; import fbConfig from '../../fb-stubs/config';
import {notification, Typography} from 'antd'; import {notification, Typography} from 'antd';
const exec = promisify(child_process.exec); const exec = promisify(child_process.exec);

View File

@@ -7,7 +7,7 @@
* @format * @format
*/ */
import Client, {ClientQuery} from '../../Client'; import Client, {ClientQuery} from '../../../Client';
import { import {
ClientConnection, ClientConnection,
ConnectionStatus, ConnectionStatus,
@@ -16,11 +16,11 @@ import {
} from '../../comms/ClientConnection'; } from '../../comms/ClientConnection';
import {ipcRenderer, remote, IpcRendererEvent} from 'electron'; import {ipcRenderer, remote, IpcRendererEvent} from 'electron';
import JSDevice from '../../devices/JSDevice'; import JSDevice from '../../devices/JSDevice';
import {Store} from '../../reducers'; import {Store} from '../../../reducers';
import {Logger} from '../../fb-interfaces/Logger'; import {Logger} from '../../../fb-interfaces/Logger';
import ServerController from '../../comms/ServerController'; import ServerController from '../../comms/ServerController';
import {buildClientId} from '../clientUtils'; import {buildClientId} from '../../../utils/clientUtils';
import {destroyDevice} from '../../reducers/connections'; import {destroyDevice} from '../../../reducers/connections';
const connections: Map<number, JSClientFlipperConnection> = new Map(); const connections: Map<number, JSClientFlipperConnection> = new Map();

View File

@@ -0,0 +1,14 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
// Typescript doesn't know Array.filter(Boolean) won't contain nulls.
// So use Array.filter(notNull) instead.
export function notNull<T>(x: T | null | undefined): x is T {
return x !== null && x !== undefined;
}

View File

@@ -8,14 +8,14 @@
*/ */
import {createStore} from 'redux'; import {createStore} from 'redux';
import BaseDevice from '../devices/BaseDevice'; import BaseDevice from '../server/devices/BaseDevice';
import {createRootReducer} from '../reducers'; import {createRootReducer} from '../reducers';
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import Client, {ClientQuery} from '../Client'; import Client, {ClientQuery} from '../Client';
import { import {
ClientConnection, ClientConnection,
ConnectionStatusChange, ConnectionStatusChange,
} from '../comms/ClientConnection'; } from '../server/comms/ClientConnection';
import {buildClientId} from '../utils/clientUtils'; import {buildClientId} from '../utils/clientUtils';
import {Logger} from '../fb-interfaces/Logger'; import {Logger} from '../fb-interfaces/Logger';
import {PluginDefinition} from '../plugin'; import {PluginDefinition} from '../plugin';
@@ -24,7 +24,7 @@ import {getInstance} from '../fb-stubs/Logger';
import {initializeFlipperLibImplementation} from '../utils/flipperLibImplementation'; import {initializeFlipperLibImplementation} from '../utils/flipperLibImplementation';
import pluginManager from '../dispatcher/pluginManager'; import pluginManager from '../dispatcher/pluginManager';
import {PluginDetails} from 'flipper-plugin-lib'; import {PluginDetails} from 'flipper-plugin-lib';
import ArchivedDevice from '../devices/ArchivedDevice'; import ArchivedDevice from '../server/devices/ArchivedDevice';
export interface AppOptions { export interface AppOptions {
plugins?: PluginDefinition[]; plugins?: PluginDefinition[];

View File

@@ -21,7 +21,7 @@ import {
selectDevice, selectDevice,
selectClient, selectClient,
} from '../reducers/connections'; } from '../reducers/connections';
import BaseDevice from '../devices/BaseDevice'; import BaseDevice from '../server/devices/BaseDevice';
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import Client, {ClientQuery} from '../Client'; import Client, {ClientQuery} from '../Client';
@@ -29,7 +29,9 @@ import Client, {ClientQuery} from '../Client';
import {Logger} from '../fb-interfaces/Logger'; import {Logger} from '../fb-interfaces/Logger';
import {FlipperDevicePlugin, FlipperPlugin, PluginDefinition} from '../plugin'; import {FlipperDevicePlugin, FlipperPlugin, PluginDefinition} from '../plugin';
import PluginContainer from '../PluginContainer'; import PluginContainer from '../PluginContainer';
import {getPluginKey, isDevicePluginDefinition} from '../utils/pluginUtils'; import {isDevicePluginDefinition} from '../utils/pluginUtils';
import {getPluginKey} from '../utils/pluginKey';
import MockFlipper from './MockFlipper'; import MockFlipper from './MockFlipper';
import {switchPlugin} from '../reducers/pluginManager'; import {switchPlugin} from '../reducers/pluginManager';
import {createSandyPluginFromClassicPlugin} from '../dispatcher/plugins'; import {createSandyPluginFromClassicPlugin} from '../dispatcher/plugins';

View File

@@ -9,8 +9,8 @@
import {State} from '../../reducers/index'; import {State} from '../../reducers/index';
import configureStore from 'redux-mock-store'; import configureStore from 'redux-mock-store';
import {default as BaseDevice} from '../../devices/BaseDevice'; import {default as BaseDevice} from '../../server/devices/BaseDevice';
import {default as ArchivedDevice} from '../../devices/ArchivedDevice'; import {default as ArchivedDevice} from '../../server/devices/ArchivedDevice';
import { import {
processStore, processStore,
determinePluginsToProcess, determinePluginsToProcess,

View File

@@ -19,7 +19,7 @@ import {
selectDevice, selectDevice,
} from '../../reducers/connections'; } from '../../reducers/connections';
import {processMessageQueue} from '../messageQueue'; import {processMessageQueue} from '../messageQueue';
import {getPluginKey} from '../pluginUtils'; import {getPluginKey} from '../pluginKey';
import {TestIdler} from '../Idler'; import {TestIdler} from '../Idler';
import {registerPlugins} from '../../reducers/plugins'; import {registerPlugins} from '../../reducers/plugins';
import { import {

View File

@@ -7,7 +7,7 @@
* @format * @format
*/ */
import {getPluginKey} from '../pluginUtils'; import {getPluginKey} from '../pluginKey';
import {FlipperPlugin, FlipperDevicePlugin} from '../../plugin'; import {FlipperPlugin, FlipperDevicePlugin} from '../../plugin';
import {createMockFlipperWithPlugin} from '../../test-utils/createMockFlipperWithPlugin'; import {createMockFlipperWithPlugin} from '../../test-utils/createMockFlipperWithPlugin';
import {getExportablePlugins} from '../../selectors/connections'; import {getExportablePlugins} from '../../selectors/connections';

View File

@@ -8,7 +8,7 @@
*/ */
import type Client from '../Client'; import type Client from '../Client';
import type BaseDevice from '../devices/BaseDevice'; import type BaseDevice from '../server/devices/BaseDevice';
/* A Client uniuely identifies an app running on some device. /* A Client uniuely identifies an app running on some device.

View File

@@ -12,15 +12,15 @@ import path from 'path';
import electron from 'electron'; import electron from 'electron';
import {getInstance as getLogger} from '../fb-stubs/Logger'; import {getInstance as getLogger} from '../fb-stubs/Logger';
import {Store, MiddlewareAPI} from '../reducers'; import {Store, MiddlewareAPI} from '../reducers';
import {DeviceExport} from '../devices/BaseDevice'; import {DeviceExport} from '../server/devices/BaseDevice';
import {State as PluginsState} from '../reducers/plugins'; import {State as PluginsState} from '../reducers/plugins';
import {PluginNotification} from '../reducers/notifications'; import {PluginNotification} from '../reducers/notifications';
import Client, {ClientExport, ClientQuery} from '../Client'; import Client, {ClientExport, ClientQuery} from '../Client';
import {getAppVersion} from './info'; import {getAppVersion} from './info';
import {pluginKey} from '../utils/pluginUtils'; import {pluginKey} from '../utils/pluginKey';
import {DevicePluginMap, ClientPluginMap} from '../plugin'; import {DevicePluginMap, ClientPluginMap} from '../plugin';
import {default as BaseDevice} from '../devices/BaseDevice'; import {default as BaseDevice} from '../server/devices/BaseDevice';
import {default as ArchivedDevice} from '../devices/ArchivedDevice'; import {default as ArchivedDevice} from '../server/devices/ArchivedDevice';
import fs from 'fs'; import fs from 'fs';
import {v4 as uuidv4} from 'uuid'; import {v4 as uuidv4} from 'uuid';
import {remote, OpenDialogOptions} from 'electron'; import {remote, OpenDialogOptions} from 'electron';

View File

@@ -12,7 +12,7 @@ import type {Logger} from '../fb-interfaces/Logger';
import type {Store} from '../reducers'; import type {Store} from '../reducers';
import createPaste from '../fb-stubs/createPaste'; import createPaste from '../fb-stubs/createPaste';
import GK from '../fb-stubs/GK'; import GK from '../fb-stubs/GK';
import type BaseDevice from '../devices/BaseDevice'; import type BaseDevice from '../server/devices/BaseDevice';
import {clipboard, shell} from 'electron'; import {clipboard, shell} from 'electron';
import constants from '../fb-stubs/constants'; import constants from '../fb-stubs/constants';
import {addNotification} from '../reducers/notifications'; import {addNotification} from '../reducers/notifications';

View File

@@ -0,0 +1,27 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
export function getPluginKey(
selectedAppId: string | null | undefined,
baseDevice: {serial: string} | null | undefined,
pluginID: string,
): string {
if (selectedAppId) {
return `${selectedAppId}#${pluginID}`;
}
if (baseDevice) {
// If selected App is not defined, then the plugin is a device plugin
return `${baseDevice.serial}#${pluginID}`;
}
return `unknown#${pluginID}`;
}
export const pluginKey = (serial: string, pluginName: string): string => {
return `${serial}#${pluginName}`;
};

View File

@@ -10,7 +10,7 @@
import type {PluginDefinition} from '../plugin'; import type {PluginDefinition} from '../plugin';
import type {State} from '../reducers'; import type {State} from '../reducers';
import type {State as PluginsState} from '../reducers/plugins'; import type {State as PluginsState} from '../reducers/plugins';
import type BaseDevice from '../devices/BaseDevice'; import type BaseDevice from '../server/devices/BaseDevice';
import type Client from '../Client'; import type Client from '../Client';
import type { import type {
ActivatablePluginDetails, ActivatablePluginDetails,
@@ -19,6 +19,7 @@ import type {
PluginDetails, PluginDetails,
} from 'flipper-plugin-lib'; } from 'flipper-plugin-lib';
import {getLatestCompatibleVersionOfEachPlugin} from '../dispatcher/plugins'; import {getLatestCompatibleVersionOfEachPlugin} from '../dispatcher/plugins';
import {getPluginKey} from './pluginKey';
export type PluginLists = { export type PluginLists = {
devicePlugins: PluginDefinition[]; devicePlugins: PluginDefinition[];
@@ -63,25 +64,6 @@ export function pluginsClassMap(
]); ]);
} }
export function getPluginKey(
selectedAppId: string | null | undefined,
baseDevice: {serial: string} | null | undefined,
pluginID: string,
): string {
if (selectedAppId) {
return `${selectedAppId}#${pluginID}`;
}
if (baseDevice) {
// If selected App is not defined, then the plugin is a device plugin
return `${baseDevice.serial}#${pluginID}`;
}
return `unknown#${pluginID}`;
}
export const pluginKey = (serial: string, pluginName: string): string => {
return `${serial}#${pluginName}`;
};
export function computeExportablePlugins( export function computeExportablePlugins(
state: Pick<State, 'plugins' | 'connections' | 'pluginMessageQueue'>, state: Pick<State, 'plugins' | 'connections' | 'pluginMessageQueue'>,
device: BaseDevice | null, device: BaseDevice | null,

View File

@@ -7,21 +7,22 @@
* @format * @format
*/ */
import {sleep} from 'flipper-plugin'; import {timeout} from 'flipper-plugin';
import {StatusMessageType} from '../reducers/application'; import {StatusMessageType} from '../reducers/application';
/**
* @deprecated use timeout from flipper-plugin
* @param ms @
* @param promise
* @param timeoutMessage
* @returns
*/
export default function promiseTimeout<T>( export default function promiseTimeout<T>(
ms: number, ms: number,
promise: Promise<T>, promise: Promise<T>,
timeoutMessage?: string, timeoutMessage?: string,
): Promise<T> { ): Promise<T> {
// Create a promise that rejects in <ms> milliseconds return timeout(ms, promise, timeoutMessage);
const timeout = sleep(ms).then(() => {
throw new Error(timeoutMessage || `Timed out in ${ms} ms.`);
});
// Returns a race between our timeout and the passed in promise
return Promise.race([promise, timeout]);
} }
export function showStatusUpdatesForPromise<T>( export function showStatusUpdatesForPromise<T>(

View File

@@ -8,7 +8,7 @@
*/ */
import {State} from '../reducers/index'; import {State} from '../reducers/index';
import {DeviceExport} from '../devices/BaseDevice'; import {DeviceExport} from '../server/devices/BaseDevice';
export const stateSanitizer = (state: State) => { export const stateSanitizer = (state: State) => {
if (state.connections && state.connections.devices) { if (state.connections && state.connections.devices) {

View File

@@ -9,7 +9,7 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import BaseDevice from '../devices/BaseDevice'; import BaseDevice from '../server/devices/BaseDevice';
import {reportPlatformFailures} from './metrics'; import {reportPlatformFailures} from './metrics';
import expandTilde from 'expand-tilde'; import expandTilde from 'expand-tilde';
import {remote} from 'electron'; import {remote} from 'electron';

View File

@@ -61,6 +61,7 @@ test('Correct top level API exposed', () => {
"styled", "styled",
"textContent", "textContent",
"theme", "theme",
"timeout",
"useLocalStorageState", "useLocalStorageState",
"useLogger", "useLogger",
"useMemoize", "useMemoize",

View File

@@ -76,6 +76,8 @@ export {
export {DataFormatter} from './ui/DataFormatter'; export {DataFormatter} from './ui/DataFormatter';
export {sleep} from './utils/sleep'; export {sleep} from './utils/sleep';
export {timeout} from './utils/timeout';
export { export {
LogTypes, LogTypes,
TrackType, TrackType,

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) Facebook, Inc. and its 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 {sleep} from './sleep';
export function timeout<T>(
ms: number,
promise: Promise<T>,
timeoutMessage?: string,
): Promise<T> {
// Create a promise that rejects in <ms> milliseconds
const timeout = sleep(ms).then(() => {
throw new Error(timeoutMessage || `Timed out in ${ms} ms.`);
});
// Returns a race between our timeout and the passed in promise
return Promise.race([promise, timeout]);
}

View File

@@ -1044,6 +1044,10 @@ Usage: `await sleep(1000)`
Creates a promise that automatically resolves after the specified amount of milliseconds. Creates a promise that automatically resolves after the specified amount of milliseconds.
## timeout
Usage `await timeout(1000, promise, message?)`
## styled ## styled
A convenience re-export of `styled` from [emotion](https://emotion.sh/docs/styled). A convenience re-export of `styled` from [emotion](https://emotion.sh/docs/styled).