Move app/server to flipper-server-core
Summary: moved `app/src/server` to `flipper-server-core/src` and fixed any fallout from that (aka integration points I missed on the preparing diffs). Reviewed By: passy Differential Revision: D31541378 fbshipit-source-id: 8a7e0169ebefa515781f6e5e0f7b926415d4b7e9
This commit is contained in:
committed by
Facebook GitHub Bot
parent
3e7a6b1b4b
commit
d88b28330a
@@ -22,7 +22,6 @@
|
|||||||
"@tanishiking/aho-corasick": "^0.0.1",
|
"@tanishiking/aho-corasick": "^0.0.1",
|
||||||
"@types/archiver": "^5.1.1",
|
"@types/archiver": "^5.1.1",
|
||||||
"@types/uuid": "^8.3.1",
|
"@types/uuid": "^8.3.1",
|
||||||
"JSONStream": "^1.3.1",
|
|
||||||
"adbkit": "^2.11.1",
|
"adbkit": "^2.11.1",
|
||||||
"adbkit-logcat": "^2.0.1",
|
"adbkit-logcat": "^2.0.1",
|
||||||
"antd": "4.16.8",
|
"antd": "4.16.8",
|
||||||
@@ -69,12 +68,7 @@
|
|||||||
"redux": "^4.1.1",
|
"redux": "^4.1.1",
|
||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
"reselect": "^4.0.0",
|
"reselect": "^4.0.0",
|
||||||
"rsocket-core": "^0.0.27",
|
|
||||||
"rsocket-flowable": "^0.0.27",
|
|
||||||
"rsocket-tcp-server": "^0.0.25",
|
|
||||||
"rsocket-types": "^0.0.25",
|
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.5",
|
||||||
"split2": "^3.2.2",
|
|
||||||
"tmp": "^0.2.1",
|
"tmp": "^0.2.1",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"which": "^2.0.1",
|
"which": "^2.0.1",
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ const handleError = (
|
|||||||
crashReporterPlugin.instanceApi.reportCrash(payload);
|
crashReporterPlugin.instanceApi.reportCrash(payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ClientConnection {
|
export interface ClientConnection {
|
||||||
send(data: any): void;
|
send(data: any): void;
|
||||||
sendExpectResponse(data: any): Promise<ClientResponseType>;
|
sendExpectResponse(data: any): Promise<ClientResponseType>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,12 @@ Object {
|
|||||||
"TestPlugin",
|
"TestPlugin",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"flipperServer": undefined,
|
"flipperServer": Object {
|
||||||
|
"close": [MockFunction],
|
||||||
|
"exec": [MockFunction],
|
||||||
|
"off": [MockFunction],
|
||||||
|
"on": [MockFunction],
|
||||||
|
},
|
||||||
"selectedAppId": "TestApp#Android#MockAndroidDevice#serial",
|
"selectedAppId": "TestApp#Android#MockAndroidDevice#serial",
|
||||||
"selectedAppPluginListRevision": 0,
|
"selectedAppPluginListRevision": 0,
|
||||||
"selectedDevice": Object {
|
"selectedDevice": Object {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {useCallback, useEffect, useState} from 'react';
|
import React, {useCallback, useEffect, useState} from 'react';
|
||||||
import {MetroReportableEvent} from '../server/devices/metro/MetroDevice';
|
import {MetroReportableEvent} from 'flipper-common';
|
||||||
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';
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ type OwnProps = {
|
|||||||
type StateFromProps = {
|
type StateFromProps = {
|
||||||
settings: Settings;
|
settings: Settings;
|
||||||
launcherSettings: LauncherSettings;
|
launcherSettings: LauncherSettings;
|
||||||
isXcodeDetected: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type DispatchFromProps = {
|
type DispatchFromProps = {
|
||||||
@@ -356,11 +355,9 @@ class SettingsSheet extends Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
|
export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
|
||||||
({settingsState, launcherSettingsState, connections}) => ({
|
({settingsState, launcherSettingsState}) => ({
|
||||||
settings: settingsState,
|
settings: settingsState,
|
||||||
launcherSettings: launcherSettingsState,
|
launcherSettings: launcherSettingsState,
|
||||||
isXcodeDetected:
|
|
||||||
connections.flipperServer?.ios.xcodeCommandLineToolsDetected ?? false,
|
|
||||||
}),
|
}),
|
||||||
{updateSettings, updateLauncherSettings},
|
{updateSettings, updateLauncherSettings},
|
||||||
)(withTrackingScope(SettingsSheet));
|
)(withTrackingScope(SettingsSheet));
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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 {createMockFlipperWithPlugin} from '../../../test-utils/createMockFlipperWithPlugin';
|
import {createMockFlipperWithPlugin} from '../../test-utils/createMockFlipperWithPlugin';
|
||||||
import {TestDevice} from '../../../test-utils/TestDevice';
|
import {TestDevice} from '../../test-utils/TestDevice';
|
||||||
import ArchivedDevice from '../../../devices/ArchivedDevice';
|
import ArchivedDevice from '../../devices/ArchivedDevice';
|
||||||
|
|
||||||
const physicalDevicePluginDetails = TestUtils.createMockPluginDetails({
|
const physicalDevicePluginDetails = TestUtils.createMockPluginDetails({
|
||||||
id: 'physicalDevicePlugin',
|
id: 'physicalDevicePlugin',
|
||||||
@@ -12,7 +12,6 @@
|
|||||||
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 'flipper-common';
|
import {Logger} from 'flipper-common';
|
||||||
import {parseFlipperPorts} from '../server/utils/environmentVariables';
|
|
||||||
import {
|
import {
|
||||||
importFileToStore,
|
importFileToStore,
|
||||||
IMPORT_FLIPPER_TRACE_EVENT,
|
IMPORT_FLIPPER_TRACE_EVENT,
|
||||||
@@ -80,36 +79,4 @@ export default (store: Store, logger: Logger) => {
|
|||||||
}, `${IMPORT_FLIPPER_TRACE_EVENT}:Deeplink`);
|
}, `${IMPORT_FLIPPER_TRACE_EVENT}:Deeplink`);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (process.env.FLIPPER_PORTS) {
|
|
||||||
const portOverrides = parseFlipperPorts(process.env.FLIPPER_PORTS);
|
|
||||||
if (portOverrides) {
|
|
||||||
store.dispatch({
|
|
||||||
type: 'SET_SERVER_PORTS',
|
|
||||||
payload: portOverrides,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error(
|
|
||||||
`Ignoring malformed FLIPPER_PORTS env variable:
|
|
||||||
"${process.env.FLIPPER_PORTS || ''}".
|
|
||||||
Example expected format: "1111,2222".`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.env.FLIPPER_ALT_PORTS) {
|
|
||||||
const portOverrides = parseFlipperPorts(process.env.FLIPPER_ALT_PORTS);
|
|
||||||
if (portOverrides) {
|
|
||||||
store.dispatch({
|
|
||||||
type: 'SET_ALT_SERVER_PORTS',
|
|
||||||
payload: portOverrides,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error(
|
|
||||||
`Ignoring malformed FLIPPER_ALT_PORTS env variable:
|
|
||||||
"${process.env.FLIPPER_ALT_PORTS || ''}".
|
|
||||||
Example expected format: "1111,2222".`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,10 +10,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {State, Store} from '../reducers/index';
|
import {State, Store} from '../reducers/index';
|
||||||
import {Logger} from 'flipper-common';
|
import {Logger} from 'flipper-common';
|
||||||
import {
|
import {FlipperServerImpl, setFlipperServerConfig} from 'flipper-server-core';
|
||||||
FlipperServerConfig,
|
|
||||||
FlipperServerImpl,
|
|
||||||
} from '../server/FlipperServerImpl';
|
|
||||||
import {selectClient} from '../reducers/connections';
|
import {selectClient} from '../reducers/connections';
|
||||||
import Client from '../Client';
|
import Client from '../Client';
|
||||||
import {notification} from 'antd';
|
import {notification} from 'antd';
|
||||||
@@ -21,22 +18,23 @@ import BaseDevice from '../devices/BaseDevice';
|
|||||||
import {ClientDescription, timeout} from 'flipper-common';
|
import {ClientDescription, timeout} from 'flipper-common';
|
||||||
import {reportPlatformFailures} from 'flipper-common';
|
import {reportPlatformFailures} from 'flipper-common';
|
||||||
import {sideEffect} from '../utils/sideEffect';
|
import {sideEffect} from '../utils/sideEffect';
|
||||||
|
import {getAppTempPath, getStaticPath} from '../utils/pathUtils';
|
||||||
|
import constants from '../fb-stubs/constants';
|
||||||
|
|
||||||
export default async (store: Store, logger: Logger) => {
|
export default async (store: Store, logger: Logger) => {
|
||||||
const {enableAndroid, androidHome, idbPath, enableIOS, enablePhysicalIOS} =
|
const {enableAndroid, androidHome, idbPath, enableIOS, enablePhysicalIOS} =
|
||||||
store.getState().settingsState;
|
store.getState().settingsState;
|
||||||
const server = new FlipperServerImpl(
|
setFlipperServerConfig({
|
||||||
{
|
enableAndroid,
|
||||||
enableAndroid,
|
androidHome,
|
||||||
androidHome,
|
idbPath,
|
||||||
idbPath,
|
enableIOS,
|
||||||
enableIOS,
|
enablePhysicalIOS,
|
||||||
enablePhysicalIOS,
|
staticPath: getStaticPath(),
|
||||||
serverPorts: store.getState().application.serverPorts,
|
tmpPath: getAppTempPath(),
|
||||||
altServerPorts: store.getState().application.altServerPorts,
|
validWebSocketOrigins: constants.VALID_WEB_SOCKET_REQUEST_ORIGIN_PREFIXES,
|
||||||
} as FlipperServerConfig,
|
});
|
||||||
logger,
|
const server = new FlipperServerImpl(logger);
|
||||||
);
|
|
||||||
|
|
||||||
store.dispatch({
|
store.dispatch({
|
||||||
type: 'SET_FLIPPER_SERVER',
|
type: 'SET_FLIPPER_SERVER',
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import {
|
|||||||
getClientsByAppName,
|
getClientsByAppName,
|
||||||
getAllClients,
|
getAllClients,
|
||||||
} from '../reducers/connections';
|
} from '../reducers/connections';
|
||||||
import {deconstructClientId} from '../utils/clientUtils';
|
import {deconstructClientId} from 'flipper-common';
|
||||||
import {clearMessageQueue} from '../reducers/pluginMessageQueue';
|
import {clearMessageQueue} from '../reducers/pluginMessageQueue';
|
||||||
import {
|
import {
|
||||||
isDevicePluginDefinition,
|
isDevicePluginDefinition,
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import {
|
|||||||
} from '../reducers/usageTracking';
|
} from '../reducers/usageTracking';
|
||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import BaseDevice from '../devices/BaseDevice';
|
import BaseDevice from '../devices/BaseDevice';
|
||||||
import {deconstructClientId} from '../utils/clientUtils';
|
import {deconstructClientId} from 'flipper-common';
|
||||||
import {getCPUUsage} from 'process';
|
import {getCPUUsage} from 'process';
|
||||||
import {sideEffect} from '../utils/sideEffect';
|
import {sideEffect} from '../utils/sideEffect';
|
||||||
import {getSelectionInfo} from '../utils/info';
|
import {getSelectionInfo} from '../utils/info';
|
||||||
|
|||||||
@@ -126,7 +126,6 @@ export {Rect} from './utils/geometry';
|
|||||||
export {Logger} from 'flipper-common';
|
export {Logger} from 'flipper-common';
|
||||||
export {getLogger} from 'flipper-common';
|
export {getLogger} from 'flipper-common';
|
||||||
export {callVSCode} from './utils/vscodeUtils';
|
export {callVSCode} from './utils/vscodeUtils';
|
||||||
export {checkIdbIsInstalled} from './server/devices/ios/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
|
||||||
|
|||||||
@@ -51,12 +51,13 @@ import {getVersionString} from './utils/versionString';
|
|||||||
import {PersistGate} from 'redux-persist/integration/react';
|
import {PersistGate} from 'redux-persist/integration/react';
|
||||||
// eslint-disable-next-line flipper/no-electron-remote-imports
|
// eslint-disable-next-line flipper/no-electron-remote-imports
|
||||||
import {ipcRenderer, remote} from 'electron';
|
import {ipcRenderer, remote} from 'electron';
|
||||||
import {helloWorld} from 'flipper-server-core';
|
import {
|
||||||
import {setLoggerInstance, setUserSessionManagerInstance} from 'flipper-common';
|
setLoggerInstance,
|
||||||
|
setUserSessionManagerInstance,
|
||||||
|
GK as flipperCommonGK,
|
||||||
|
} from 'flipper-common';
|
||||||
import {internGraphPOSTAPIRequest} from './fb-stubs/user';
|
import {internGraphPOSTAPIRequest} from './fb-stubs/user';
|
||||||
|
|
||||||
helloWorld();
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development' && os.platform() === 'darwin') {
|
if (process.env.NODE_ENV === 'development' && os.platform() === 'darwin') {
|
||||||
// By default Node.JS has its internal certificate storage and doesn't use
|
// By default Node.JS has its internal certificate storage and doesn't use
|
||||||
// the system store. Because of this, it's impossible to access ondemand / devserver
|
// the system store. Because of this, it's impossible to access ondemand / devserver
|
||||||
@@ -186,6 +187,8 @@ function setProcessState(store: Store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
// TODO: centralise all those initialisations in a single configuration call
|
||||||
|
flipperCommonGK.get = (name) => GK.get(name);
|
||||||
const store = getStore();
|
const store = getStore();
|
||||||
const logger = initLogger(store);
|
const logger = initLogger(store);
|
||||||
setLoggerInstance(logger);
|
setLoggerInstance(logger);
|
||||||
|
|||||||
@@ -17,10 +17,6 @@ export type LauncherMsg = {
|
|||||||
message: string;
|
message: string;
|
||||||
severity: 'warning' | 'error';
|
severity: 'warning' | 'error';
|
||||||
};
|
};
|
||||||
export type ServerPorts = {
|
|
||||||
insecure: number;
|
|
||||||
secure: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type StatusMessageType = {
|
export type StatusMessageType = {
|
||||||
msg: string;
|
msg: string;
|
||||||
@@ -49,8 +45,6 @@ export type State = {
|
|||||||
windowIsFocused: boolean;
|
windowIsFocused: boolean;
|
||||||
share: ShareType | null;
|
share: ShareType | null;
|
||||||
sessionId: string | null;
|
sessionId: string | null;
|
||||||
serverPorts: ServerPorts;
|
|
||||||
altServerPorts: ServerPorts;
|
|
||||||
launcherMsg: LauncherMsg;
|
launcherMsg: LauncherMsg;
|
||||||
statusMessages: Array<string>;
|
statusMessages: Array<string>;
|
||||||
};
|
};
|
||||||
@@ -69,20 +63,6 @@ export type Action =
|
|||||||
type: 'windowIsFocused';
|
type: 'windowIsFocused';
|
||||||
payload: {isFocused: boolean; time: number};
|
payload: {isFocused: boolean; time: number};
|
||||||
}
|
}
|
||||||
| {
|
|
||||||
type: 'SET_SERVER_PORTS';
|
|
||||||
payload: {
|
|
||||||
insecure: number;
|
|
||||||
secure: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'SET_ALT_SERVER_PORTS';
|
|
||||||
payload: {
|
|
||||||
insecure: number;
|
|
||||||
secure: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
| {
|
| {
|
||||||
type: 'LAUNCHER_MSG';
|
type: 'LAUNCHER_MSG';
|
||||||
payload: {
|
payload: {
|
||||||
@@ -107,14 +87,6 @@ export const initialState: () => State = () => ({
|
|||||||
activeSheet: null,
|
activeSheet: null,
|
||||||
share: null,
|
share: null,
|
||||||
sessionId: uuidv1(),
|
sessionId: uuidv1(),
|
||||||
serverPorts: {
|
|
||||||
insecure: 8089,
|
|
||||||
secure: 8088,
|
|
||||||
},
|
|
||||||
altServerPorts: {
|
|
||||||
insecure: 9089,
|
|
||||||
secure: 9088,
|
|
||||||
},
|
|
||||||
launcherMsg: {
|
launcherMsg: {
|
||||||
severity: 'warning',
|
severity: 'warning',
|
||||||
message: '',
|
message: '',
|
||||||
@@ -163,16 +135,6 @@ export default function reducer(
|
|||||||
...state,
|
...state,
|
||||||
windowIsFocused: action.payload.isFocused,
|
windowIsFocused: action.payload.isFocused,
|
||||||
};
|
};
|
||||||
} else if (action.type === 'SET_SERVER_PORTS') {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
serverPorts: action.payload,
|
|
||||||
};
|
|
||||||
} else if (action.type === 'SET_ALT_SERVER_PORTS') {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
altServerPorts: action.payload,
|
|
||||||
};
|
|
||||||
} else if (action.type === 'LAUNCHER_MSG') {
|
} else if (action.type === 'LAUNCHER_MSG') {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|||||||
@@ -12,16 +12,20 @@ import {produce} from 'immer';
|
|||||||
|
|
||||||
import type BaseDevice from '../devices/BaseDevice';
|
import type BaseDevice from '../devices/BaseDevice';
|
||||||
import type Client from '../Client';
|
import type Client from '../Client';
|
||||||
import type {UninitializedClient, DeviceOS, Logger} from 'flipper-common';
|
import type {
|
||||||
|
UninitializedClient,
|
||||||
|
DeviceOS,
|
||||||
|
Logger,
|
||||||
|
FlipperServer,
|
||||||
|
} from 'flipper-common';
|
||||||
import {performance} from 'perf_hooks';
|
import {performance} from 'perf_hooks';
|
||||||
import type {Actions} from '.';
|
import type {Actions} from '.';
|
||||||
import {WelcomeScreenStaticView} from '../sandy-chrome/WelcomeScreen';
|
import {WelcomeScreenStaticView} from '../sandy-chrome/WelcomeScreen';
|
||||||
import {isDevicePluginDefinition} from '../utils/pluginUtils';
|
import {isDevicePluginDefinition} from '../utils/pluginUtils';
|
||||||
import {getPluginKey} from '../utils/pluginKey';
|
import {getPluginKey} from '../utils/pluginKey';
|
||||||
|
|
||||||
import {deconstructClientId} from '../utils/clientUtils';
|
import {deconstructClientId} from 'flipper-common';
|
||||||
import type {RegisterPluginAction} from './plugins';
|
import type {RegisterPluginAction} from './plugins';
|
||||||
import {FlipperServerImpl} from '../server/FlipperServerImpl';
|
|
||||||
import {shallowEqual} from 'react-redux';
|
import {shallowEqual} from 'react-redux';
|
||||||
|
|
||||||
export type StaticViewProps = {logger: Logger};
|
export type StaticViewProps = {logger: Logger};
|
||||||
@@ -74,7 +78,7 @@ type StateV2 = {
|
|||||||
deepLinkPayload: unknown;
|
deepLinkPayload: unknown;
|
||||||
staticView: StaticView;
|
staticView: StaticView;
|
||||||
selectedAppPluginListRevision: number;
|
selectedAppPluginListRevision: number;
|
||||||
flipperServer: FlipperServerImpl | undefined;
|
flipperServer: FlipperServer | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
type StateV1 = Omit<StateV2, 'enabledPlugins' | 'enabledDevicePlugins'> & {
|
type StateV1 = Omit<StateV2, 'enabledPlugins' | 'enabledDevicePlugins'> & {
|
||||||
@@ -158,7 +162,7 @@ export type Action =
|
|||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'SET_FLIPPER_SERVER';
|
type: 'SET_FLIPPER_SERVER';
|
||||||
payload: FlipperServerImpl;
|
payload: FlipperServer;
|
||||||
}
|
}
|
||||||
| RegisterPluginAction;
|
| RegisterPluginAction;
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import {deconstructPluginKey} from '../utils/clientUtils';
|
import {deconstructPluginKey} from 'flipper-common';
|
||||||
|
|
||||||
export const DEFAULT_MAX_QUEUE_SIZE = 10000;
|
export const DEFAULT_MAX_QUEUE_SIZE = 10000;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
import {Actions, Store} from './';
|
import {Actions, Store} from './';
|
||||||
import {setStaticView} from './connections';
|
import {setStaticView} from './connections';
|
||||||
import {deconstructClientId} from '../utils/clientUtils';
|
import {deconstructClientId} from 'flipper-common';
|
||||||
import {switchPlugin} from './pluginManager';
|
import {switchPlugin} from './pluginManager';
|
||||||
import {showStatusUpdatesForDuration} from '../utils/promiseTimeout';
|
import {showStatusUpdatesForDuration} from '../utils/promiseTimeout';
|
||||||
import {selectedPlugins as setSelectedPlugins} from './plugins';
|
import {selectedPlugins as setSelectedPlugins} from './plugins';
|
||||||
|
|||||||
@@ -17,13 +17,9 @@ 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 '../../server/devices/android/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 {IOSDeviceParams} from 'flipper-common';
|
||||||
launchSimulator, // TODO: move to iOSDeviceManager
|
|
||||||
IOSDeviceParams,
|
|
||||||
} from '../../server/devices/ios/iOSDeviceManager';
|
|
||||||
|
|
||||||
const COLD_BOOT = 'cold-boot';
|
const COLD_BOOT = 'cold-boot';
|
||||||
|
|
||||||
@@ -36,26 +32,12 @@ export function showEmulatorLauncher(store: Store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function LaunchEmulatorContainer({onClose}: {onClose: () => void}) {
|
function LaunchEmulatorContainer({onClose}: {onClose: () => void}) {
|
||||||
const flipperServer = useStore((state) => state.connections.flipperServer);
|
return <LaunchEmulatorDialog onClose={onClose} />;
|
||||||
return (
|
|
||||||
<LaunchEmulatorDialog
|
|
||||||
onClose={onClose}
|
|
||||||
getSimulators={() => flipperServer!.ios.getSimulators(false)}
|
|
||||||
getEmulators={() => flipperServer!.android.getAndroidEmulators()}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LaunchEmulatorDialog = withTrackingScope(
|
export const LaunchEmulatorDialog = withTrackingScope(
|
||||||
function LaunchEmulatorDialog({
|
function LaunchEmulatorDialog({onClose}: {onClose: () => void}) {
|
||||||
onClose,
|
const flipperServer = useStore((state) => state.connections.flipperServer);
|
||||||
getSimulators,
|
|
||||||
getEmulators,
|
|
||||||
}: {
|
|
||||||
onClose: () => void;
|
|
||||||
getSimulators: () => Promise<IOSDeviceParams[]>;
|
|
||||||
getEmulators: () => Promise<string[]>;
|
|
||||||
}) {
|
|
||||||
const iosEnabled = useStore((state) => state.settingsState.enableIOS);
|
const iosEnabled = useStore((state) => state.settingsState.enableIOS);
|
||||||
const androidEnabled = useStore(
|
const androidEnabled = useStore(
|
||||||
(state) => state.settingsState.enableAndroid,
|
(state) => state.settingsState.enableAndroid,
|
||||||
@@ -63,12 +45,12 @@ export const LaunchEmulatorDialog = withTrackingScope(
|
|||||||
const [iosEmulators, setIosEmulators] = useState<IOSDeviceParams[]>([]);
|
const [iosEmulators, setIosEmulators] = useState<IOSDeviceParams[]>([]);
|
||||||
const [androidEmulators, setAndroidEmulators] = useState<string[]>([]);
|
const [androidEmulators, setAndroidEmulators] = useState<string[]>([]);
|
||||||
|
|
||||||
const store = useStore();
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!iosEnabled) {
|
if (!iosEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getSimulators()
|
flipperServer!
|
||||||
|
.exec('ios-get-simulators', false)
|
||||||
.then((emulators) => {
|
.then((emulators) => {
|
||||||
setIosEmulators(
|
setIosEmulators(
|
||||||
emulators.filter(
|
emulators.filter(
|
||||||
@@ -81,20 +63,21 @@ export const LaunchEmulatorDialog = withTrackingScope(
|
|||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.warn('Failed to find simulators', e);
|
console.warn('Failed to find simulators', e);
|
||||||
});
|
});
|
||||||
}, [iosEnabled, getSimulators, store]);
|
}, [iosEnabled, flipperServer]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!androidEnabled) {
|
if (!androidEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getEmulators()
|
flipperServer!
|
||||||
|
.exec('android-get-emulators')
|
||||||
.then((emulators) => {
|
.then((emulators) => {
|
||||||
setAndroidEmulators(emulators);
|
setAndroidEmulators(emulators);
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.warn('Failed to find emulators', e);
|
console.warn('Failed to find emulators', e);
|
||||||
});
|
});
|
||||||
}, [androidEnabled, getEmulators]);
|
}, [androidEnabled, flipperServer]);
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
...(androidEmulators.length > 0
|
...(androidEmulators.length > 0
|
||||||
@@ -102,7 +85,8 @@ export const LaunchEmulatorDialog = withTrackingScope(
|
|||||||
: []),
|
: []),
|
||||||
...androidEmulators.map((name) => {
|
...androidEmulators.map((name) => {
|
||||||
const launch = (coldBoot: boolean) => {
|
const launch = (coldBoot: boolean) => {
|
||||||
launchEmulator(name, coldBoot)
|
flipperServer!
|
||||||
|
.exec('android-launch-emulator', name, coldBoot)
|
||||||
.then(onClose)
|
.then(onClose)
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error('Failed to start emulator: ', e);
|
console.error('Failed to start emulator: ', e);
|
||||||
@@ -139,7 +123,8 @@ export const LaunchEmulatorDialog = withTrackingScope(
|
|||||||
<Button
|
<Button
|
||||||
key={device.udid}
|
key={device.udid}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
launchSimulator(device.udid)
|
flipperServer!
|
||||||
|
.exec('ios-launch-simulator', device.udid)
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error('Failed to start simulator: ', e);
|
console.error('Failed to start simulator: ', e);
|
||||||
message.error('Failed to start simulator: ' + e);
|
message.error('Failed to start simulator: ' + e);
|
||||||
|
|||||||
@@ -15,23 +15,23 @@ import {LaunchEmulatorDialog} from '../LaunchEmulator';
|
|||||||
|
|
||||||
import {createRootReducer} from '../../../reducers';
|
import {createRootReducer} from '../../../reducers';
|
||||||
import {sleep} from 'flipper-plugin';
|
import {sleep} from 'flipper-plugin';
|
||||||
|
import {createFlipperServerMock} from '../../../test-utils/createFlipperServerMock';
|
||||||
import {launchEmulator} from '../../../server/devices/android/AndroidDevice';
|
|
||||||
jest.mock('../../../server/devices/android/AndroidDevice', () => ({
|
|
||||||
launchEmulator: jest.fn(() => Promise.resolve([])),
|
|
||||||
}));
|
|
||||||
|
|
||||||
test('Can render and launch android apps - empty', async () => {
|
test('Can render and launch android apps - empty', async () => {
|
||||||
const store = createStore(createRootReducer());
|
const store = createStore(createRootReducer());
|
||||||
|
const mockServer = createFlipperServerMock({
|
||||||
|
'ios-get-simulators': () => Promise.resolve([]),
|
||||||
|
'android-get-emulators': () => Promise.resolve([]),
|
||||||
|
});
|
||||||
|
store.dispatch({
|
||||||
|
type: 'SET_FLIPPER_SERVER',
|
||||||
|
payload: mockServer,
|
||||||
|
});
|
||||||
const onClose = jest.fn();
|
const onClose = jest.fn();
|
||||||
|
|
||||||
const renderer = render(
|
const renderer = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<LaunchEmulatorDialog
|
<LaunchEmulatorDialog onClose={onClose} />
|
||||||
onClose={onClose}
|
|
||||||
getSimulators={() => Promise.resolve([])}
|
|
||||||
getEmulators={() => Promise.resolve([])}
|
|
||||||
/>
|
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -45,7 +45,21 @@ test('Can render and launch android apps - empty', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Can render and launch android apps', async () => {
|
test('Can render and launch android apps', async () => {
|
||||||
|
let p: Promise<any> | undefined = undefined;
|
||||||
|
|
||||||
const store = createStore(createRootReducer());
|
const store = createStore(createRootReducer());
|
||||||
|
const launch = jest.fn().mockImplementation(() => Promise.resolve());
|
||||||
|
const mockServer = createFlipperServerMock({
|
||||||
|
'ios-get-simulators': () => Promise.resolve([]),
|
||||||
|
'android-get-emulators': () =>
|
||||||
|
(p = Promise.resolve(['emulator1', 'emulator2'])),
|
||||||
|
'android-launch-emulator': launch,
|
||||||
|
});
|
||||||
|
store.dispatch({
|
||||||
|
type: 'SET_FLIPPER_SERVER',
|
||||||
|
payload: mockServer,
|
||||||
|
});
|
||||||
|
|
||||||
store.dispatch({
|
store.dispatch({
|
||||||
type: 'UPDATE_SETTINGS',
|
type: 'UPDATE_SETTINGS',
|
||||||
payload: {
|
payload: {
|
||||||
@@ -55,15 +69,9 @@ test('Can render and launch android apps', async () => {
|
|||||||
});
|
});
|
||||||
const onClose = jest.fn();
|
const onClose = jest.fn();
|
||||||
|
|
||||||
let p: Promise<any> | undefined = undefined;
|
|
||||||
|
|
||||||
const renderer = render(
|
const renderer = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<LaunchEmulatorDialog
|
<LaunchEmulatorDialog onClose={onClose} />
|
||||||
onClose={onClose}
|
|
||||||
getSimulators={() => Promise.resolve([])}
|
|
||||||
getEmulators={() => (p = Promise.resolve(['emulator1', 'emulator2']))}
|
|
||||||
/>
|
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -84,5 +92,5 @@ test('Can render and launch android apps', async () => {
|
|||||||
fireEvent.click(renderer.getByText('emulator2'));
|
fireEvent.click(renderer.getByText('emulator2'));
|
||||||
await sleep(1000);
|
await sleep(1000);
|
||||||
expect(onClose).toBeCalled();
|
expect(onClose).toBeCalled();
|
||||||
expect(launchEmulator).toBeCalledWith('emulator2', false);
|
expect(launch).toBeCalledWith('emulator2', false);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
@@ -11,13 +11,8 @@ import {createStore} from 'redux';
|
|||||||
import BaseDevice from '../devices/BaseDevice';
|
import BaseDevice from '../devices/BaseDevice';
|
||||||
import {createRootReducer} from '../reducers';
|
import {createRootReducer} from '../reducers';
|
||||||
import {Store} from '../reducers/index';
|
import {Store} from '../reducers/index';
|
||||||
import Client from '../Client';
|
import Client, {ClientConnection} from '../Client';
|
||||||
import {
|
import {Logger, buildClientId, FlipperServer} from 'flipper-common';
|
||||||
ClientConnection,
|
|
||||||
ConnectionStatusChange,
|
|
||||||
} from '../server/comms/ClientConnection';
|
|
||||||
import {buildClientId} from '../utils/clientUtils';
|
|
||||||
import {Logger} from 'flipper-common';
|
|
||||||
import {PluginDefinition} from '../plugin';
|
import {PluginDefinition} from '../plugin';
|
||||||
import {registerPlugins} from '../reducers/plugins';
|
import {registerPlugins} from '../reducers/plugins';
|
||||||
import {getLogger} from 'flipper-common';
|
import {getLogger} from 'flipper-common';
|
||||||
@@ -27,6 +22,7 @@ import {PluginDetails} from 'flipper-plugin-lib';
|
|||||||
import ArchivedDevice from '../devices/ArchivedDevice';
|
import ArchivedDevice from '../devices/ArchivedDevice';
|
||||||
import {ClientQuery, DeviceOS} from 'flipper-common';
|
import {ClientQuery, DeviceOS} from 'flipper-common';
|
||||||
import {TestDevice} from './TestDevice';
|
import {TestDevice} from './TestDevice';
|
||||||
|
import {createFlipperServerMock} from './createFlipperServerMock';
|
||||||
|
|
||||||
export interface AppOptions {
|
export interface AppOptions {
|
||||||
plugins?: PluginDefinition[];
|
plugins?: PluginDefinition[];
|
||||||
@@ -56,6 +52,7 @@ export default class MockFlipper {
|
|||||||
private _clients: Client[] = [];
|
private _clients: Client[] = [];
|
||||||
private _deviceCounter: number = 0;
|
private _deviceCounter: number = 0;
|
||||||
private _clientCounter: number = 0;
|
private _clientCounter: number = 0;
|
||||||
|
private _flipperServer: FlipperServer = createFlipperServerMock();
|
||||||
|
|
||||||
public get store(): Store {
|
public get store(): Store {
|
||||||
return this._store;
|
return this._store;
|
||||||
@@ -89,6 +86,10 @@ export default class MockFlipper {
|
|||||||
});
|
});
|
||||||
initializeFlipperLibImplementation(this._store, this._logger);
|
initializeFlipperLibImplementation(this._store, this._logger);
|
||||||
this._store.dispatch(registerPlugins(plugins ?? []));
|
this._store.dispatch(registerPlugins(plugins ?? []));
|
||||||
|
this._store.dispatch({
|
||||||
|
type: 'SET_FLIPPER_SERVER',
|
||||||
|
payload: this._flipperServer,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async initWithDeviceAndClient(
|
public async initWithDeviceAndClient(
|
||||||
@@ -237,12 +238,9 @@ export default class MockFlipper {
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function createStubConnection(): ClientConnection | null | undefined {
|
|
||||||
|
function createStubConnection(): ClientConnection {
|
||||||
return {
|
return {
|
||||||
subscribeToEvents(_: ConnectionStatusChange) {},
|
|
||||||
close() {
|
|
||||||
throw new Error('Should not be called in test');
|
|
||||||
},
|
|
||||||
send(_: any) {
|
send(_: any) {
|
||||||
throw new Error('Should not be called in test');
|
throw new Error('Should not be called in test');
|
||||||
},
|
},
|
||||||
|
|||||||
32
desktop/app/src/test-utils/createFlipperServerMock.tsx
Normal file
32
desktop/app/src/test-utils/createFlipperServerMock.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* 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 {FlipperServer, FlipperServerCommands} from 'flipper-common';
|
||||||
|
|
||||||
|
export function createFlipperServerMock(
|
||||||
|
overrides?: Partial<FlipperServerCommands>,
|
||||||
|
): FlipperServer {
|
||||||
|
return {
|
||||||
|
on: jest.fn(),
|
||||||
|
off: jest.fn(),
|
||||||
|
exec: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(
|
||||||
|
(cmd: keyof FlipperServerCommands, ...args: any[]) => {
|
||||||
|
if (overrides?.[cmd]) {
|
||||||
|
return (overrides[cmd] as any)(...args);
|
||||||
|
}
|
||||||
|
return Promise.reject(
|
||||||
|
new Error(`FlipperServerMock exec not implemented: ${cmd}}`),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
close: jest.fn(),
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -7,39 +7,10 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {deconstructClientId} from 'flipper-common';
|
||||||
import type Client from '../Client';
|
import type Client from '../Client';
|
||||||
import type BaseDevice from '../devices/BaseDevice';
|
import type BaseDevice from '../devices/BaseDevice';
|
||||||
|
|
||||||
/* A Client uniuely identifies an app running on some device.
|
|
||||||
|
|
||||||
Always use this utility to construct and parse clientId strings.
|
|
||||||
*/
|
|
||||||
export type ClientIdConstituents = {
|
|
||||||
app: string;
|
|
||||||
os: string;
|
|
||||||
device: string;
|
|
||||||
device_id: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* A plugin key is a string uniquely identifying an instance of a plugin.
|
|
||||||
This can be a device plugin for a particular device, or a client plugin for a particular client (app).
|
|
||||||
In the device plugin case, the "client" is the device it's connected to.
|
|
||||||
In the client plugin case (normal plugins), the "client" is the app it's connected to.
|
|
||||||
|
|
||||||
Always use this utility to construct and parse pluginKey strings.
|
|
||||||
*/
|
|
||||||
type PluginKeyConstituents =
|
|
||||||
| {
|
|
||||||
type: 'device';
|
|
||||||
pluginName: string;
|
|
||||||
client: string;
|
|
||||||
}
|
|
||||||
| ({
|
|
||||||
type: 'client';
|
|
||||||
pluginName: string;
|
|
||||||
client: string;
|
|
||||||
} & ClientIdConstituents);
|
|
||||||
|
|
||||||
export function currentActiveApps(
|
export function currentActiveApps(
|
||||||
clients: Array<Client>,
|
clients: Array<Client>,
|
||||||
selectedDevice: null | BaseDevice,
|
selectedDevice: null | BaseDevice,
|
||||||
@@ -56,65 +27,3 @@ export function currentActiveApps(
|
|||||||
.map((client) => client.appName);
|
.map((client) => client.appName);
|
||||||
return currentActiveApps;
|
return currentActiveApps;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildClientId(clientInfo: {
|
|
||||||
app: string;
|
|
||||||
os: string;
|
|
||||||
device: string;
|
|
||||||
device_id: string;
|
|
||||||
}): string {
|
|
||||||
// N.B.: device_id can be empty, which designates the host device
|
|
||||||
for (const key of ['app', 'os', 'device'] as Array<
|
|
||||||
keyof ClientIdConstituents
|
|
||||||
>) {
|
|
||||||
if (!clientInfo[key]) {
|
|
||||||
console.error(
|
|
||||||
`Attempted to build clientId with invalid ${key}: "${clientInfo[key]}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const escapedName = escape(clientInfo.app);
|
|
||||||
return `${escapedName}#${clientInfo.os}#${clientInfo.device}#${clientInfo.device_id}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deconstructClientId(clientId: string): ClientIdConstituents {
|
|
||||||
if (!clientId || clientId.split('#').length !== 4) {
|
|
||||||
console.error(`Attempted to deconstruct invalid clientId: "${clientId}"`);
|
|
||||||
}
|
|
||||||
let [app, os, device, device_id] = clientId.split('#');
|
|
||||||
app = unescape(app);
|
|
||||||
return {
|
|
||||||
app,
|
|
||||||
os,
|
|
||||||
device,
|
|
||||||
device_id,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deconstructPluginKey(pluginKey: string): PluginKeyConstituents {
|
|
||||||
const parts = pluginKey.split('#');
|
|
||||||
if (parts.length === 2) {
|
|
||||||
// Device plugin
|
|
||||||
return {
|
|
||||||
type: 'device',
|
|
||||||
client: parts[0],
|
|
||||||
pluginName: parts[1],
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// Client plugin
|
|
||||||
const lastHashIndex = pluginKey.lastIndexOf('#');
|
|
||||||
const clientId = pluginKey.slice(0, lastHashIndex);
|
|
||||||
const pluginName = pluginKey.slice(lastHashIndex + 1);
|
|
||||||
if (!pluginName) {
|
|
||||||
console.error(
|
|
||||||
`Attempted to deconstruct invalid pluginKey: "${pluginKey}"`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
type: 'client',
|
|
||||||
...deconstructClientId(clientId),
|
|
||||||
client: clientId,
|
|
||||||
pluginName: pluginName,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import {
|
|||||||
resetSupportFormV2State,
|
resetSupportFormV2State,
|
||||||
SupportFormRequestDetailsState,
|
SupportFormRequestDetailsState,
|
||||||
} from '../reducers/supportForm';
|
} from '../reducers/supportForm';
|
||||||
import {deconstructClientId} from '../utils/clientUtils';
|
import {deconstructClientId} from 'flipper-common';
|
||||||
import {performance} from 'perf_hooks';
|
import {performance} from 'perf_hooks';
|
||||||
import {processMessageQueue} from './messageQueue';
|
import {processMessageQueue} from './messageQueue';
|
||||||
import {getPluginTitle} from './pluginUtils';
|
import {getPluginTitle} from './pluginUtils';
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import type BaseDevice from '../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';
|
||||||
import {deconstructPluginKey} from './clientUtils';
|
import {deconstructPluginKey} from 'flipper-common';
|
||||||
import {DetailSidebarImpl} from '../sandy-chrome/DetailSidebarImpl';
|
import {DetailSidebarImpl} from '../sandy-chrome/DetailSidebarImpl';
|
||||||
|
|
||||||
export function initializeFlipperLibImplementation(
|
export function initializeFlipperLibImplementation(
|
||||||
|
|||||||
@@ -12,9 +12,8 @@ import isProduction from './isProduction';
|
|||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import {getStaticPath} from './pathUtils';
|
import {getStaticPath} from './pathUtils';
|
||||||
import type {State, Store} from '../reducers/index';
|
import type {State, Store} from '../reducers/index';
|
||||||
import {deconstructClientId} from './clientUtils';
|
|
||||||
import {sideEffect} from './sideEffect';
|
import {sideEffect} from './sideEffect';
|
||||||
import {Logger, isTest} from 'flipper-common';
|
import {Logger, isTest, deconstructClientId} from 'flipper-common';
|
||||||
|
|
||||||
type PlatformInfo = {
|
type PlatformInfo = {
|
||||||
arch: string;
|
arch: string;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
} from '../reducers/pluginMessageQueue';
|
} from '../reducers/pluginMessageQueue';
|
||||||
import {IdlerImpl} from './Idler';
|
import {IdlerImpl} from './Idler';
|
||||||
import {isPluginEnabled, getSelectedPluginKey} from '../reducers/connections';
|
import {isPluginEnabled, getSelectedPluginKey} from '../reducers/connections';
|
||||||
import {deconstructPluginKey} from './clientUtils';
|
import {deconstructPluginKey} from 'flipper-common';
|
||||||
import {defaultEnabledBackgroundPlugins} from './pluginUtils';
|
import {defaultEnabledBackgroundPlugins} from './pluginUtils';
|
||||||
import {batch, Idler, _SandyPluginInstance} from 'flipper-plugin';
|
import {batch, Idler, _SandyPluginInstance} from 'flipper-plugin';
|
||||||
import {addBackgroundStat} from './pluginStats';
|
import {addBackgroundStat} from './pluginStats';
|
||||||
|
|||||||
14
desktop/flipper-common/src/GK.tsx
Normal file
14
desktop/flipper-common/src/GK.tsx
Normal 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const GK = {
|
||||||
|
get(_name: string): boolean {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
};
|
||||||
100
desktop/flipper-common/src/clientUtils.tsx
Normal file
100
desktop/flipper-common/src/clientUtils.tsx
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/**
|
||||||
|
* 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 Client uniuely identifies an app running on some device.
|
||||||
|
|
||||||
|
Always use this utility to construct and parse clientId strings.
|
||||||
|
*/
|
||||||
|
export type ClientIdConstituents = {
|
||||||
|
app: string;
|
||||||
|
os: string;
|
||||||
|
device: string;
|
||||||
|
device_id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* A plugin key is a string uniquely identifying an instance of a plugin.
|
||||||
|
This can be a device plugin for a particular device, or a client plugin for a particular client (app).
|
||||||
|
In the device plugin case, the "client" is the device it's connected to.
|
||||||
|
In the client plugin case (normal plugins), the "client" is the app it's connected to.
|
||||||
|
|
||||||
|
Always use this utility to construct and parse pluginKey strings.
|
||||||
|
*/
|
||||||
|
type PluginKeyConstituents =
|
||||||
|
| {
|
||||||
|
type: 'device';
|
||||||
|
pluginName: string;
|
||||||
|
client: string;
|
||||||
|
}
|
||||||
|
| ({
|
||||||
|
type: 'client';
|
||||||
|
pluginName: string;
|
||||||
|
client: string;
|
||||||
|
} & ClientIdConstituents);
|
||||||
|
|
||||||
|
export function buildClientId(clientInfo: {
|
||||||
|
app: string;
|
||||||
|
os: string;
|
||||||
|
device: string;
|
||||||
|
device_id: string;
|
||||||
|
}): string {
|
||||||
|
// N.B.: device_id can be empty, which designates the host device
|
||||||
|
for (const key of ['app', 'os', 'device'] as Array<
|
||||||
|
keyof ClientIdConstituents
|
||||||
|
>) {
|
||||||
|
if (!clientInfo[key]) {
|
||||||
|
console.error(
|
||||||
|
`Attempted to build clientId with invalid ${key}: "${clientInfo[key]}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const escapedName = escape(clientInfo.app);
|
||||||
|
return `${escapedName}#${clientInfo.os}#${clientInfo.device}#${clientInfo.device_id}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deconstructClientId(clientId: string): ClientIdConstituents {
|
||||||
|
if (!clientId || clientId.split('#').length !== 4) {
|
||||||
|
console.error(`Attempted to deconstruct invalid clientId: "${clientId}"`);
|
||||||
|
}
|
||||||
|
let [app, os, device, device_id] = clientId.split('#');
|
||||||
|
app = unescape(app);
|
||||||
|
return {
|
||||||
|
app,
|
||||||
|
os,
|
||||||
|
device,
|
||||||
|
device_id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deconstructPluginKey(pluginKey: string): PluginKeyConstituents {
|
||||||
|
const parts = pluginKey.split('#');
|
||||||
|
if (parts.length === 2) {
|
||||||
|
// Device plugin
|
||||||
|
return {
|
||||||
|
type: 'device',
|
||||||
|
client: parts[0],
|
||||||
|
pluginName: parts[1],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Client plugin
|
||||||
|
const lastHashIndex = pluginKey.lastIndexOf('#');
|
||||||
|
const clientId = pluginKey.slice(0, lastHashIndex);
|
||||||
|
const pluginName = pluginKey.slice(lastHashIndex + 1);
|
||||||
|
if (!pluginName) {
|
||||||
|
console.error(
|
||||||
|
`Attempted to deconstruct invalid pluginKey: "${pluginKey}"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: 'client',
|
||||||
|
...deconstructClientId(clientId),
|
||||||
|
client: clientId,
|
||||||
|
pluginName: pluginName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,3 +41,5 @@ export {
|
|||||||
getErrorFromErrorLike,
|
getErrorFromErrorLike,
|
||||||
} from './utils/errors';
|
} from './utils/errors';
|
||||||
export * from './user-session';
|
export * from './user-session';
|
||||||
|
export * from './GK';
|
||||||
|
export * from './clientUtils';
|
||||||
|
|||||||
@@ -112,6 +112,14 @@ export type FlipperServerEvents = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type IOSDeviceParams = {
|
||||||
|
udid: string;
|
||||||
|
type: DeviceType;
|
||||||
|
name: string;
|
||||||
|
deviceTypeIdentifier?: string;
|
||||||
|
state?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type FlipperServerCommands = {
|
export type FlipperServerCommands = {
|
||||||
'device-start-logging': (serial: string) => Promise<void>;
|
'device-start-logging': (serial: string) => Promise<void>;
|
||||||
'device-stop-logging': (serial: string) => Promise<void>;
|
'device-stop-logging': (serial: string) => Promise<void>;
|
||||||
@@ -137,6 +145,10 @@ export type FlipperServerCommands = {
|
|||||||
clientId: string,
|
clientId: string,
|
||||||
payload: any,
|
payload: any,
|
||||||
) => Promise<ClientResponseType>;
|
) => Promise<ClientResponseType>;
|
||||||
|
'android-get-emulators': () => Promise<string[]>;
|
||||||
|
'android-launch-emulator': (name: string, coldboot: boolean) => Promise<void>;
|
||||||
|
'ios-get-simulators': (bootedOnly: boolean) => Promise<IOSDeviceParams[]>;
|
||||||
|
'ios-launch-simulator': (udid: string) => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface FlipperServer {
|
export interface FlipperServer {
|
||||||
@@ -154,3 +166,95 @@ export interface FlipperServer {
|
|||||||
): ReturnType<FlipperServerCommands[Event]>;
|
): ReturnType<FlipperServerCommands[Event]>;
|
||||||
close(): void;
|
close(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// From xplat/js/metro/packages/metro/src/lib/reporting.js
|
||||||
|
export type MetroBundleDetails = {
|
||||||
|
entryFile: string;
|
||||||
|
platform?: string;
|
||||||
|
dev: boolean;
|
||||||
|
minify: boolean;
|
||||||
|
bundleType: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// From xplat/js/metro/packages/metro/src/lib/reporting.js
|
||||||
|
export type MetroGlobalCacheDisabledReason =
|
||||||
|
| 'too_many_errors'
|
||||||
|
| 'too_many_misses';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tagged union of all the actions that may happen and we may want to
|
||||||
|
* report to the tool user.
|
||||||
|
*
|
||||||
|
* Based on xplat/js/metro/packages/metro/src/lib/TerminalReporter.js
|
||||||
|
*/
|
||||||
|
export type MetroReportableEvent =
|
||||||
|
| {
|
||||||
|
port: number;
|
||||||
|
projectRoots: ReadonlyArray<string>;
|
||||||
|
type: 'initialize_started';
|
||||||
|
}
|
||||||
|
| {type: 'initialize_done'}
|
||||||
|
| {
|
||||||
|
type: 'initialize_failed';
|
||||||
|
port: number;
|
||||||
|
error: Error;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
buildID: string;
|
||||||
|
type: 'bundle_build_done';
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
buildID: string;
|
||||||
|
type: 'bundle_build_failed';
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
buildID: string;
|
||||||
|
bundleDetails: MetroBundleDetails;
|
||||||
|
type: 'bundle_build_started';
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
error: Error;
|
||||||
|
type: 'bundling_error';
|
||||||
|
}
|
||||||
|
| {type: 'dep_graph_loading'}
|
||||||
|
| {type: 'dep_graph_loaded'}
|
||||||
|
| {
|
||||||
|
buildID: string;
|
||||||
|
type: 'bundle_transform_progressed';
|
||||||
|
transformedFileCount: number;
|
||||||
|
totalFileCount: number;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'global_cache_error';
|
||||||
|
error: Error;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'global_cache_disabled';
|
||||||
|
reason: MetroGlobalCacheDisabledReason;
|
||||||
|
}
|
||||||
|
| {type: 'transform_cache_reset'}
|
||||||
|
| {
|
||||||
|
type: 'worker_stdout_chunk';
|
||||||
|
chunk: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'worker_stderr_chunk';
|
||||||
|
chunk: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'hmr_client_error';
|
||||||
|
error: Error;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'client_log';
|
||||||
|
level:
|
||||||
|
| 'trace'
|
||||||
|
| 'info'
|
||||||
|
| 'warn'
|
||||||
|
| 'log'
|
||||||
|
| 'group'
|
||||||
|
| 'groupCollapsed'
|
||||||
|
| 'groupEnd'
|
||||||
|
| 'debug';
|
||||||
|
data: Array<any>;
|
||||||
|
};
|
||||||
|
|||||||
@@ -9,7 +9,29 @@
|
|||||||
"types": "lib/index.d.ts",
|
"types": "lib/index.d.ts",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bugs": "https://github.com/facebook/flipper/issues",
|
"bugs": "https://github.com/facebook/flipper/issues",
|
||||||
"dependencies": {},
|
"dependencies": {
|
||||||
|
"JSONStream": "^1.3.1",
|
||||||
|
"adbkit": "^2.11.1",
|
||||||
|
"adbkit-logcat": "^2.0.1",
|
||||||
|
"archiver": "^5.3.0",
|
||||||
|
"async-mutex": "^0.3.2",
|
||||||
|
"flipper-common": "0.0.0",
|
||||||
|
"fs-extra": "^10.0.0",
|
||||||
|
"invariant": "^2.2.4",
|
||||||
|
"js-base64": "^3.7.2",
|
||||||
|
"lodash.memoize": "^4.1.2",
|
||||||
|
"openssl-wrapper": "^0.3.4",
|
||||||
|
"promisify-child-process": "^4.1.1",
|
||||||
|
"rsocket-core": "^0.0.27",
|
||||||
|
"rsocket-flowable": "^0.0.27",
|
||||||
|
"rsocket-tcp-server": "^0.0.25",
|
||||||
|
"rsocket-types": "^0.0.25",
|
||||||
|
"split2": "^3.2.2",
|
||||||
|
"tmp": "^0.2.1",
|
||||||
|
"uuid": "^8.3.2",
|
||||||
|
"which": "^2.0.2",
|
||||||
|
"ws": "^8.2.3"
|
||||||
|
},
|
||||||
"devDependencies": {},
|
"devDependencies": {},
|
||||||
"peerDependencies": {},
|
"peerDependencies": {},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
93
desktop/flipper-server-core/src/FlipperServerConfig.tsx
Normal file
93
desktop/flipper-server-core/src/FlipperServerConfig.tsx
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/**
|
||||||
|
* 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 {isTest} from 'flipper-common';
|
||||||
|
import {parseFlipperPorts} from './utils/environmentVariables';
|
||||||
|
|
||||||
|
export interface FlipperServerConfig {
|
||||||
|
enableAndroid: boolean;
|
||||||
|
androidHome: string;
|
||||||
|
enableIOS: boolean;
|
||||||
|
idbPath: string;
|
||||||
|
enablePhysicalIOS: boolean;
|
||||||
|
validWebSocketOrigins: string[];
|
||||||
|
staticPath: string;
|
||||||
|
tmpPath: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaultConfig should be used for testing only, and disables by default all features
|
||||||
|
const testConfig: FlipperServerConfig = {
|
||||||
|
androidHome: '',
|
||||||
|
enableAndroid: false,
|
||||||
|
enableIOS: false,
|
||||||
|
enablePhysicalIOS: false,
|
||||||
|
idbPath: '',
|
||||||
|
validWebSocketOrigins: [],
|
||||||
|
staticPath: '/static/',
|
||||||
|
tmpPath: '/temp/',
|
||||||
|
};
|
||||||
|
|
||||||
|
let currentConfig: FlipperServerConfig | undefined = undefined;
|
||||||
|
|
||||||
|
export function getFlipperServerConfig(): FlipperServerConfig {
|
||||||
|
if (!currentConfig) {
|
||||||
|
if (isTest()) return testConfig;
|
||||||
|
throw new Error('FlipperServerConfig has not been set');
|
||||||
|
}
|
||||||
|
return currentConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setFlipperServerConfig(config: FlipperServerConfig) {
|
||||||
|
currentConfig = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerPorts = {
|
||||||
|
insecure: number;
|
||||||
|
secure: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getServerPortsConfig(): {
|
||||||
|
serverPorts: ServerPorts;
|
||||||
|
altServerPorts: ServerPorts;
|
||||||
|
} {
|
||||||
|
let portOverrides: ServerPorts | undefined;
|
||||||
|
if (process.env.FLIPPER_PORTS) {
|
||||||
|
portOverrides = parseFlipperPorts(process.env.FLIPPER_PORTS);
|
||||||
|
if (!portOverrides) {
|
||||||
|
console.error(
|
||||||
|
`Ignoring malformed FLIPPER_PORTS env variable:
|
||||||
|
"${process.env.FLIPPER_PORTS || ''}".
|
||||||
|
Example expected format: "1111,2222".`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let portAltOverrides: ServerPorts | undefined;
|
||||||
|
if (process.env.FLIPPER_ALT_PORTS) {
|
||||||
|
portAltOverrides = parseFlipperPorts(process.env.FLIPPER_ALT_PORTS);
|
||||||
|
if (!portAltOverrides) {
|
||||||
|
console.error(
|
||||||
|
`Ignoring malformed FLIPPER_ALT_PORTS env variable:
|
||||||
|
"${process.env.FLIPPER_ALT_PORTS || ''}".
|
||||||
|
Example expected format: "1111,2222".`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
serverPorts: portOverrides ?? {
|
||||||
|
insecure: 8089,
|
||||||
|
secure: 8088,
|
||||||
|
},
|
||||||
|
altServerPorts: portAltOverrides ?? {
|
||||||
|
insecure: 9089,
|
||||||
|
secure: 9088,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -11,9 +11,11 @@ import EventEmitter from 'events';
|
|||||||
import {Logger} from 'flipper-common';
|
import {Logger} from 'flipper-common';
|
||||||
import ServerController from './comms/ServerController';
|
import ServerController from './comms/ServerController';
|
||||||
import {CertificateExchangeMedium} from './utils/CertificateProvider';
|
import {CertificateExchangeMedium} from './utils/CertificateProvider';
|
||||||
import {ServerPorts} from '../reducers/application';
|
|
||||||
import {AndroidDeviceManager} from './devices/android/androidDeviceManager';
|
import {AndroidDeviceManager} from './devices/android/androidDeviceManager';
|
||||||
import {IOSDeviceManager} from './devices/ios/iOSDeviceManager';
|
import {
|
||||||
|
IOSDeviceManager,
|
||||||
|
launchSimulator,
|
||||||
|
} from './devices/ios/iOSDeviceManager';
|
||||||
import metroDevice from './devices/metro/metroDeviceManager';
|
import metroDevice from './devices/metro/metroDeviceManager';
|
||||||
import desktopDevice from './devices/desktop/desktopDeviceManager';
|
import desktopDevice from './devices/desktop/desktopDeviceManager';
|
||||||
import {
|
import {
|
||||||
@@ -26,33 +28,8 @@ import {
|
|||||||
import {ServerDevice} from './devices/ServerDevice';
|
import {ServerDevice} from './devices/ServerDevice';
|
||||||
import {Base64} from 'js-base64';
|
import {Base64} from 'js-base64';
|
||||||
import MetroDevice from './devices/metro/MetroDevice';
|
import MetroDevice from './devices/metro/MetroDevice';
|
||||||
|
import {launchEmulator} from './devices/android/AndroidDevice';
|
||||||
export interface FlipperServerConfig {
|
import {getFlipperServerConfig} from './FlipperServerConfig';
|
||||||
enableAndroid: boolean;
|
|
||||||
androidHome: string;
|
|
||||||
enableIOS: boolean;
|
|
||||||
idbPath: string;
|
|
||||||
enablePhysicalIOS: boolean;
|
|
||||||
serverPorts: ServerPorts;
|
|
||||||
altServerPorts: ServerPorts;
|
|
||||||
}
|
|
||||||
|
|
||||||
// defaultConfig should be used for testing only, and disables by default all features
|
|
||||||
const defaultConfig: FlipperServerConfig = {
|
|
||||||
androidHome: '',
|
|
||||||
enableAndroid: false,
|
|
||||||
enableIOS: false,
|
|
||||||
enablePhysicalIOS: false,
|
|
||||||
idbPath: '',
|
|
||||||
serverPorts: {
|
|
||||||
insecure: -1,
|
|
||||||
secure: -1,
|
|
||||||
},
|
|
||||||
altServerPorts: {
|
|
||||||
insecure: -1,
|
|
||||||
secure: -1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FlipperServer takes care of all incoming device & client connections.
|
* FlipperServer takes care of all incoming device & client connections.
|
||||||
@@ -63,8 +40,6 @@ const defaultConfig: FlipperServerConfig = {
|
|||||||
* using '.on'. All events are strongly typed.
|
* using '.on'. All events are strongly typed.
|
||||||
*/
|
*/
|
||||||
export class FlipperServerImpl implements FlipperServer {
|
export class FlipperServerImpl implements FlipperServer {
|
||||||
public config: FlipperServerConfig;
|
|
||||||
|
|
||||||
private readonly events = new EventEmitter();
|
private readonly events = new EventEmitter();
|
||||||
// server handles the incoming RSocket / WebSocket connections from Flipper clients
|
// server handles the incoming RSocket / WebSocket connections from Flipper clients
|
||||||
readonly server: ServerController;
|
readonly server: ServerController;
|
||||||
@@ -74,8 +49,8 @@ export class FlipperServerImpl implements FlipperServer {
|
|||||||
android: AndroidDeviceManager;
|
android: AndroidDeviceManager;
|
||||||
ios: IOSDeviceManager;
|
ios: IOSDeviceManager;
|
||||||
|
|
||||||
constructor(config: Partial<FlipperServerConfig>, public logger: Logger) {
|
constructor(public logger: Logger) {
|
||||||
this.config = {...defaultConfig, ...config};
|
getFlipperServerConfig(); // Config should be available at this point!
|
||||||
const server = (this.server = new ServerController(this));
|
const server = (this.server = new ServerController(this));
|
||||||
this.android = new AndroidDeviceManager(this);
|
this.android = new AndroidDeviceManager(this);
|
||||||
this.ios = new IOSDeviceManager(this);
|
this.ios = new IOSDeviceManager(this);
|
||||||
@@ -239,6 +214,12 @@ export class FlipperServerImpl implements FlipperServer {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
'android-get-emulators': async () => this.android.getAndroidEmulators(),
|
||||||
|
'android-launch-emulator': async (name, coldBoot) =>
|
||||||
|
launchEmulator(name, coldBoot),
|
||||||
|
'ios-get-simulators': async (bootedOnly) =>
|
||||||
|
this.ios.getSimulators(bootedOnly),
|
||||||
|
'ios-launch-simulator': async (udid) => launchSimulator(udid),
|
||||||
};
|
};
|
||||||
|
|
||||||
registerDevice(device: ServerDevice) {
|
registerDevice(device: ServerDevice) {
|
||||||
@@ -9,16 +9,20 @@
|
|||||||
|
|
||||||
import {CertificateExchangeMedium} from '../utils/CertificateProvider';
|
import {CertificateExchangeMedium} from '../utils/CertificateProvider';
|
||||||
import {Logger} from 'flipper-common';
|
import {Logger} from 'flipper-common';
|
||||||
import {ClientDescription, ClientQuery, isTest} from 'flipper-common';
|
import {
|
||||||
|
ClientDescription,
|
||||||
|
ClientQuery,
|
||||||
|
isTest,
|
||||||
|
GK,
|
||||||
|
buildClientId,
|
||||||
|
} from 'flipper-common';
|
||||||
import CertificateProvider from '../utils/CertificateProvider';
|
import CertificateProvider from '../utils/CertificateProvider';
|
||||||
import {ClientConnection, ConnectionStatus} from './ClientConnection';
|
import {ClientConnection, ConnectionStatus} from './ClientConnection';
|
||||||
import {UninitializedClient} from 'flipper-common';
|
import {UninitializedClient} from 'flipper-common';
|
||||||
import {reportPlatformFailures} from 'flipper-common';
|
import {reportPlatformFailures} from 'flipper-common';
|
||||||
import {EventEmitter} from 'events';
|
import {EventEmitter} from 'events';
|
||||||
import invariant from 'invariant';
|
import invariant from 'invariant';
|
||||||
import GK from '../../fb-stubs/GK';
|
import DummyDevice from '../devices/DummyDevice';
|
||||||
import {buildClientId} from '../../utils/clientUtils';
|
|
||||||
import DummyDevice from '../../server/devices/DummyDevice';
|
|
||||||
import {
|
import {
|
||||||
appNameWithUpdateHint,
|
appNameWithUpdateHint,
|
||||||
transformCertificateExchangeMediumToType,
|
transformCertificateExchangeMediumToType,
|
||||||
@@ -33,6 +37,10 @@ import {
|
|||||||
TransportType,
|
TransportType,
|
||||||
} from './ServerFactory';
|
} from './ServerFactory';
|
||||||
import {FlipperServerImpl} from '../FlipperServerImpl';
|
import {FlipperServerImpl} from '../FlipperServerImpl';
|
||||||
|
import {
|
||||||
|
getServerPortsConfig,
|
||||||
|
getFlipperServerConfig,
|
||||||
|
} from '../FlipperServerConfig';
|
||||||
|
|
||||||
type ClientInfo = {
|
type ClientInfo = {
|
||||||
connection: ClientConnection | null | undefined;
|
connection: ClientConnection | null | undefined;
|
||||||
@@ -80,7 +88,7 @@ class ServerController extends EventEmitter implements ServerEventsListener {
|
|||||||
this.certificateProvider = new CertificateProvider(
|
this.certificateProvider = new CertificateProvider(
|
||||||
this,
|
this,
|
||||||
this.logger,
|
this.logger,
|
||||||
this.flipperServer.config,
|
getFlipperServerConfig(),
|
||||||
);
|
);
|
||||||
this.connectionTracker = new ConnectionTracker(this.logger);
|
this.connectionTracker = new ConnectionTracker(this.logger);
|
||||||
this.secureServer = null;
|
this.secureServer = null;
|
||||||
@@ -111,7 +119,7 @@ class ServerController extends EventEmitter implements ServerEventsListener {
|
|||||||
if (isTest()) {
|
if (isTest()) {
|
||||||
throw new Error('Spawing new server is not supported in test');
|
throw new Error('Spawing new server is not supported in test');
|
||||||
}
|
}
|
||||||
const {insecure, secure} = this.flipperServer.config.serverPorts;
|
const {insecure, secure} = getServerPortsConfig().serverPorts;
|
||||||
|
|
||||||
this.initialized = this.certificateProvider
|
this.initialized = this.certificateProvider
|
||||||
.loadSecureServerConfig()
|
.loadSecureServerConfig()
|
||||||
@@ -119,7 +127,7 @@ class ServerController extends EventEmitter implements ServerEventsListener {
|
|||||||
console.info('[conn] secure server listening at port: ', secure);
|
console.info('[conn] secure server listening at port: ', secure);
|
||||||
this.secureServer = createServer(secure, this, options);
|
this.secureServer = createServer(secure, this, options);
|
||||||
if (GK.get('flipper_websocket_server')) {
|
if (GK.get('flipper_websocket_server')) {
|
||||||
const {secure: altSecure} = this.flipperServer.config.altServerPorts;
|
const {secure: altSecure} = getServerPortsConfig().altServerPorts;
|
||||||
console.info(
|
console.info(
|
||||||
'[conn] secure server (ws) listening at port: ',
|
'[conn] secure server (ws) listening at port: ',
|
||||||
altSecure,
|
altSecure,
|
||||||
@@ -136,8 +144,7 @@ class ServerController extends EventEmitter implements ServerEventsListener {
|
|||||||
console.info('[conn] insecure server listening at port: ', insecure);
|
console.info('[conn] insecure server listening at port: ', insecure);
|
||||||
this.insecureServer = createServer(insecure, this);
|
this.insecureServer = createServer(insecure, this);
|
||||||
if (GK.get('flipper_websocket_server')) {
|
if (GK.get('flipper_websocket_server')) {
|
||||||
const {insecure: altInsecure} =
|
const {insecure: altInsecure} = getServerPortsConfig().altServerPorts;
|
||||||
this.flipperServer.config.altServerPorts;
|
|
||||||
console.info(
|
console.info(
|
||||||
'[conn] insecure server (ws) listening at port: ',
|
'[conn] insecure server (ws) listening at port: ',
|
||||||
altInsecure,
|
altInsecure,
|
||||||
@@ -214,13 +221,13 @@ class ServerController extends EventEmitter implements ServerEventsListener {
|
|||||||
|
|
||||||
const {os, app, device_id} = clientQuery;
|
const {os, app, device_id} = clientQuery;
|
||||||
// without these checks, the user might see a connection timeout error instead, which would be much harder to track down
|
// without these checks, the user might see a connection timeout error instead, which would be much harder to track down
|
||||||
if (os === 'iOS' && !this.flipperServer.config.enableIOS) {
|
if (os === 'iOS' && !getFlipperServerConfig().enableIOS) {
|
||||||
console.error(
|
console.error(
|
||||||
`Refusing connection from ${app} on ${device_id}, since iOS support is disabled in settings`,
|
`Refusing connection from ${app} on ${device_id}, since iOS support is disabled in settings`,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (os === 'Android' && !this.flipperServer.config.enableAndroid) {
|
if (os === 'Android' && !getFlipperServerConfig().enableAndroid) {
|
||||||
console.error(
|
console.error(
|
||||||
`Refusing connection from ${app} on ${device_id}, since Android support is disabled in settings`,
|
`Refusing connection from ${app} on ${device_id}, since Android support is disabled in settings`,
|
||||||
);
|
);
|
||||||
@@ -12,10 +12,10 @@ import WebSocket from 'ws';
|
|||||||
import querystring from 'querystring';
|
import querystring from 'querystring';
|
||||||
import {BrowserClientFlipperConnection} from './BrowserClientFlipperConnection';
|
import {BrowserClientFlipperConnection} from './BrowserClientFlipperConnection';
|
||||||
import {ServerEventsListener} from './ServerAdapter';
|
import {ServerEventsListener} from './ServerAdapter';
|
||||||
import constants from '../../fb-stubs/constants';
|
|
||||||
import ws from 'ws';
|
import ws from 'ws';
|
||||||
import {IncomingMessage} from 'http';
|
import {IncomingMessage} from 'http';
|
||||||
import {ClientDescription, ClientQuery} from 'flipper-common';
|
import {ClientDescription, ClientQuery} from 'flipper-common';
|
||||||
|
import {getFlipperServerConfig} from '../FlipperServerConfig';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WebSocket-based server which uses a connect/disconnect handshake over an insecure channel.
|
* WebSocket-based server which uses a connect/disconnect handshake over an insecure channel.
|
||||||
@@ -27,7 +27,7 @@ class ServerWebSocketBrowser extends ServerWebSocketBase {
|
|||||||
|
|
||||||
verifyClient(): ws.VerifyClientCallbackSync {
|
verifyClient(): ws.VerifyClientCallbackSync {
|
||||||
return (info: {origin: string; req: IncomingMessage; secure: boolean}) => {
|
return (info: {origin: string; req: IncomingMessage; secure: boolean}) => {
|
||||||
const ok = constants.VALID_WEB_SOCKET_REQUEST_ORIGIN_PREFIXES.some(
|
const ok = getFlipperServerConfig().validWebSocketOrigins.some(
|
||||||
(validPrefix) => info.origin.startsWith(validPrefix),
|
(validPrefix) => info.origin.startsWith(validPrefix),
|
||||||
);
|
);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@@ -17,6 +17,10 @@ import {Client as ADBClient, Device} from 'adbkit';
|
|||||||
import {join} from 'path';
|
import {join} from 'path';
|
||||||
import {FlipperServerImpl} from '../../FlipperServerImpl';
|
import {FlipperServerImpl} from '../../FlipperServerImpl';
|
||||||
import {notNull} from '../../utils/typeUtils';
|
import {notNull} from '../../utils/typeUtils';
|
||||||
|
import {
|
||||||
|
getServerPortsConfig,
|
||||||
|
getFlipperServerConfig,
|
||||||
|
} from '../../FlipperServerConfig';
|
||||||
|
|
||||||
export class AndroidDeviceManager {
|
export class AndroidDeviceManager {
|
||||||
// cache emulator path
|
// cache emulator path
|
||||||
@@ -58,12 +62,10 @@ export class AndroidDeviceManager {
|
|||||||
abiList,
|
abiList,
|
||||||
sdkVersion,
|
sdkVersion,
|
||||||
);
|
);
|
||||||
if (this.flipperServer.config.serverPorts) {
|
const ports = getServerPortsConfig();
|
||||||
|
if (ports.serverPorts) {
|
||||||
await androidLikeDevice
|
await androidLikeDevice
|
||||||
.reverse([
|
.reverse([ports.serverPorts.secure, ports.serverPorts.insecure])
|
||||||
this.flipperServer.config.serverPorts.secure,
|
|
||||||
this.flipperServer.config.serverPorts.insecure,
|
|
||||||
])
|
|
||||||
// We may not be able to establish a reverse connection, e.g. for old Android SDKs.
|
// We may not be able to establish a reverse connection, e.g. for old Android SDKs.
|
||||||
// This is *generally* fine, because we hard-code the ports on the SDK side.
|
// This is *generally* fine, because we hard-code the ports on the SDK side.
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
@@ -177,7 +179,7 @@ export class AndroidDeviceManager {
|
|||||||
|
|
||||||
async watchAndroidDevices() {
|
async watchAndroidDevices() {
|
||||||
try {
|
try {
|
||||||
const client = await getAdbClient(this.flipperServer.config);
|
const client = await getAdbClient(getFlipperServerConfig());
|
||||||
client
|
client
|
||||||
.trackDevices()
|
.trackDevices()
|
||||||
.then((tracker) => {
|
.then((tracker) => {
|
||||||
@@ -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 {getFlipperServerConfig} from '../../FlipperServerConfig';
|
||||||
|
|
||||||
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.';
|
||||||
@@ -98,8 +98,7 @@ export function xcrunStartLogListener(udid: string, deviceType: DeviceType) {
|
|||||||
|
|
||||||
function makeTempScreenshotFilePath() {
|
function makeTempScreenshotFilePath() {
|
||||||
const imageName = uuid() + '.png';
|
const imageName = uuid() + '.png';
|
||||||
const directory = getAppTempPath();
|
return path.join(getFlipperServerConfig().tmpPath, imageName);
|
||||||
return path.join(directory, imageName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runScreenshotCommand(
|
async function runScreenshotCommand(
|
||||||
@@ -10,20 +10,16 @@
|
|||||||
import {makeIOSBridge} from '../IOSBridge';
|
import {makeIOSBridge} from '../IOSBridge';
|
||||||
import childProcess from 'child_process';
|
import childProcess from 'child_process';
|
||||||
import * as promisifyChildProcess from 'promisify-child-process';
|
import * as promisifyChildProcess from 'promisify-child-process';
|
||||||
import {mocked} from 'ts-jest/utils';
|
|
||||||
|
|
||||||
jest.mock('child_process');
|
jest.mock('child_process');
|
||||||
const spawn = mocked(childProcess.spawn);
|
|
||||||
|
|
||||||
jest.mock('promisify-child-process');
|
jest.mock('promisify-child-process');
|
||||||
const exec = mocked(promisifyChildProcess.exec);
|
|
||||||
|
|
||||||
test('uses xcrun with no idb when xcode is detected', async () => {
|
test('uses xcrun with no idb when xcode is detected', async () => {
|
||||||
const ib = await makeIOSBridge('', true);
|
const ib = await makeIOSBridge('', true);
|
||||||
|
|
||||||
ib.startLogListener('deadbeef', 'emulator');
|
ib.startLogListener('deadbeef', 'emulator');
|
||||||
|
|
||||||
expect(spawn).toHaveBeenCalledWith(
|
expect(childProcess.spawn).toHaveBeenCalledWith(
|
||||||
'xcrun',
|
'xcrun',
|
||||||
[
|
[
|
||||||
'simctl',
|
'simctl',
|
||||||
@@ -47,7 +43,7 @@ test('uses idb when present and xcode detected', async () => {
|
|||||||
|
|
||||||
ib.startLogListener('deadbeef', 'emulator');
|
ib.startLogListener('deadbeef', 'emulator');
|
||||||
|
|
||||||
expect(spawn).toHaveBeenCalledWith(
|
expect(childProcess.spawn).toHaveBeenCalledWith(
|
||||||
'/usr/local/bin/idb',
|
'/usr/local/bin/idb',
|
||||||
[
|
[
|
||||||
'log',
|
'log',
|
||||||
@@ -70,7 +66,7 @@ test('uses idb when present and xcode detected and physical device connected', a
|
|||||||
|
|
||||||
ib.startLogListener('deadbeef', 'physical');
|
ib.startLogListener('deadbeef', 'physical');
|
||||||
|
|
||||||
expect(spawn).toHaveBeenCalledWith(
|
expect(childProcess.spawn).toHaveBeenCalledWith(
|
||||||
'/usr/local/bin/idb',
|
'/usr/local/bin/idb',
|
||||||
[
|
[
|
||||||
'log',
|
'log',
|
||||||
@@ -101,7 +97,7 @@ test.unix(
|
|||||||
|
|
||||||
ib.screenshot('deadbeef');
|
ib.screenshot('deadbeef');
|
||||||
|
|
||||||
expect(exec).toHaveBeenCalledWith(
|
expect(promisifyChildProcess.exec).toHaveBeenCalledWith(
|
||||||
'xcrun simctl io deadbeef screenshot /temp/00000000-0000-0000-0000-000000000000.png',
|
'xcrun simctl io deadbeef screenshot /temp/00000000-0000-0000-0000-000000000000.png',
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -112,7 +108,7 @@ test.unix('uses idb to take screenshots when available', async () => {
|
|||||||
|
|
||||||
ib.screenshot('deadbeef');
|
ib.screenshot('deadbeef');
|
||||||
|
|
||||||
expect(exec).toHaveBeenCalledWith(
|
expect(promisifyChildProcess.exec).toHaveBeenCalledWith(
|
||||||
'idb screenshot --udid deadbeef /temp/00000000-0000-0000-0000-000000000000.png',
|
'idb screenshot --udid deadbeef /temp/00000000-0000-0000-0000-000000000000.png',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -122,7 +118,7 @@ test('uses xcrun to navigate with no idb when xcode is detected', async () => {
|
|||||||
|
|
||||||
ib.navigate('deadbeef', 'fb://dummy');
|
ib.navigate('deadbeef', 'fb://dummy');
|
||||||
|
|
||||||
expect(exec).toHaveBeenCalledWith(
|
expect(promisifyChildProcess.exec).toHaveBeenCalledWith(
|
||||||
'xcrun simctl io deadbeef launch url "fb://dummy"',
|
'xcrun simctl io deadbeef launch url "fb://dummy"',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -132,7 +128,9 @@ test('uses idb to navigate when available', async () => {
|
|||||||
|
|
||||||
ib.navigate('deadbeef', 'fb://dummy');
|
ib.navigate('deadbeef', 'fb://dummy');
|
||||||
|
|
||||||
expect(exec).toHaveBeenCalledWith('idb open --udid deadbeef "fb://dummy"');
|
expect(promisifyChildProcess.exec).toHaveBeenCalledWith(
|
||||||
|
'idb open --udid deadbeef "fb://dummy"',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('uses xcrun to record with no idb when xcode is detected', async () => {
|
test('uses xcrun to record with no idb when xcode is detected', async () => {
|
||||||
@@ -140,7 +138,7 @@ test('uses xcrun to record with no idb when xcode is detected', async () => {
|
|||||||
|
|
||||||
ib.recordVideo('deadbeef', '/tmp/video.mp4');
|
ib.recordVideo('deadbeef', '/tmp/video.mp4');
|
||||||
|
|
||||||
expect(exec).toHaveBeenCalledWith(
|
expect(promisifyChildProcess.exec).toHaveBeenCalledWith(
|
||||||
'xcrun simctl io deadbeef recordVideo --codec=h264 --force /tmp/video.mp4',
|
'xcrun simctl io deadbeef recordVideo --codec=h264 --force /tmp/video.mp4',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -150,7 +148,7 @@ test('uses idb to record when available', async () => {
|
|||||||
|
|
||||||
ib.recordVideo('deadbeef', '/tmo/video.mp4');
|
ib.recordVideo('deadbeef', '/tmo/video.mp4');
|
||||||
|
|
||||||
expect(exec).toHaveBeenCalledWith(
|
expect(promisifyChildProcess.exec).toHaveBeenCalledWith(
|
||||||
'idb record-video --udid deadbeef /tmo/video.mp4',
|
'idb record-video --udid deadbeef /tmo/video.mp4',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -8,16 +8,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {parseXcodeFromCoreSimPath} from '../iOSDeviceManager';
|
import {parseXcodeFromCoreSimPath} from '../iOSDeviceManager';
|
||||||
import configureStore from 'redux-mock-store';
|
|
||||||
import {State, createRootReducer} from '../../../../reducers/index';
|
|
||||||
import {getLogger} from 'flipper-common';
|
import {getLogger} from 'flipper-common';
|
||||||
import {IOSBridge} from '../IOSBridge';
|
import {IOSBridge} from '../IOSBridge';
|
||||||
import {FlipperServerImpl} from '../../../FlipperServerImpl';
|
import {FlipperServerImpl} from '../../../FlipperServerImpl';
|
||||||
|
|
||||||
const mockStore = configureStore<State, {}>([])(
|
|
||||||
createRootReducer()(undefined, {type: 'INIT'}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const standardCoresimulatorLog =
|
const standardCoresimulatorLog =
|
||||||
'username 1264 0.0 0.1 5989740 41648 ?? Ss 2:23PM 0:12.92 /Applications/Xcode_12.4.0_fb.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/libexec/mobileassetd';
|
'username 1264 0.0 0.1 5989740 41648 ?? Ss 2:23PM 0:12.92 /Applications/Xcode_12.4.0_fb.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/libexec/mobileassetd';
|
||||||
|
|
||||||
@@ -59,7 +53,7 @@ test('test parseXcodeFromCoreSimPath from standard locations', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('test getAllPromisesForQueryingDevices when xcode detected', () => {
|
test('test getAllPromisesForQueryingDevices when xcode detected', () => {
|
||||||
const flipperServer = new FlipperServerImpl({}, getLogger());
|
const flipperServer = new FlipperServerImpl(getLogger());
|
||||||
flipperServer.ios.iosBridge = {} as IOSBridge;
|
flipperServer.ios.iosBridge = {} as IOSBridge;
|
||||||
const promises = flipperServer.ios.getAllPromisesForQueryingDevices(
|
const promises = flipperServer.ios.getAllPromisesForQueryingDevices(
|
||||||
true,
|
true,
|
||||||
@@ -69,7 +63,7 @@ test('test getAllPromisesForQueryingDevices when xcode detected', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('test getAllPromisesForQueryingDevices when xcode is not detected', () => {
|
test('test getAllPromisesForQueryingDevices when xcode is not detected', () => {
|
||||||
const flipperServer = new FlipperServerImpl({}, getLogger());
|
const flipperServer = new FlipperServerImpl(getLogger());
|
||||||
flipperServer.ios.iosBridge = {} as IOSBridge;
|
flipperServer.ios.iosBridge = {} as IOSBridge;
|
||||||
const promises = flipperServer.ios.getAllPromisesForQueryingDevices(
|
const promises = flipperServer.ios.getAllPromisesForQueryingDevices(
|
||||||
false,
|
false,
|
||||||
@@ -79,7 +73,7 @@ test('test getAllPromisesForQueryingDevices when xcode is not detected', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('test getAllPromisesForQueryingDevices when xcode and idb are both unavailable', () => {
|
test('test getAllPromisesForQueryingDevices when xcode and idb are both unavailable', () => {
|
||||||
const flipperServer = new FlipperServerImpl({}, getLogger());
|
const flipperServer = new FlipperServerImpl(getLogger());
|
||||||
flipperServer.ios.iosBridge = {} as IOSBridge;
|
flipperServer.ios.iosBridge = {} as IOSBridge;
|
||||||
const promises = flipperServer.ios.getAllPromisesForQueryingDevices(
|
const promises = flipperServer.ios.getAllPromisesForQueryingDevices(
|
||||||
false,
|
false,
|
||||||
@@ -89,7 +83,7 @@ test('test getAllPromisesForQueryingDevices when xcode and idb are both unavaila
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('test getAllPromisesForQueryingDevices when both idb and xcode are available', () => {
|
test('test getAllPromisesForQueryingDevices when both idb and xcode are available', () => {
|
||||||
const flipperServer = new FlipperServerImpl({}, getLogger());
|
const flipperServer = new FlipperServerImpl(getLogger());
|
||||||
flipperServer.ios.iosBridge = {} as IOSBridge;
|
flipperServer.ios.iosBridge = {} as IOSBridge;
|
||||||
const promises = flipperServer.ios.getAllPromisesForQueryingDevices(
|
const promises = flipperServer.ios.getAllPromisesForQueryingDevices(
|
||||||
true,
|
true,
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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 {reportPlatformFailures} from 'flipper-common';
|
import {reportPlatformFailures} from 'flipper-common';
|
||||||
@@ -18,8 +17,6 @@ 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 {notification, Typography} from 'antd';
|
|
||||||
const exec = promisify(child_process.exec);
|
const exec = promisify(child_process.exec);
|
||||||
|
|
||||||
// Use debug to get helpful logs when idb fails
|
// Use debug to get helpful logs when idb fails
|
||||||
@@ -251,14 +248,9 @@ function handleMissingIdb(e: Error, idbPath: string): void {
|
|||||||
e.message.includes('sudo: no tty present and no askpass program specified')
|
e.message.includes('sudo: no tty present and no askpass program specified')
|
||||||
) {
|
) {
|
||||||
console.warn(e);
|
console.warn(e);
|
||||||
const message = `idb doesn't appear to be installed. Run "${idbPath} list-targets" to fix this.`;
|
throw new Error(
|
||||||
notification.error({
|
`idb doesn't appear to be installed. Run "${idbPath} list-targets" to fix this.`,
|
||||||
message: 'Cannot connect to idb',
|
);
|
||||||
duration: null,
|
|
||||||
description: message,
|
|
||||||
key: 'idb_connection_failed',
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
@@ -271,24 +263,11 @@ function handleMissingPermissions(e: Error): void {
|
|||||||
e.message.includes('sonar/app.csr')
|
e.message.includes('sonar/app.csr')
|
||||||
) {
|
) {
|
||||||
console.warn(e);
|
console.warn(e);
|
||||||
const message = fbConfig.isFBBuild ? (
|
throw new Error(
|
||||||
<>
|
'Cannot connect to iOS application. idb_certificate_pull_failed' +
|
||||||
Idb lacks permissions to exchange certificates. Did you install a source
|
'Idb lacks permissions to exchange certificates. Did you install a source build ([FB] or enable certificate exchange)? ' +
|
||||||
build or a debug build with certificate exchange enabled?{' '}
|
e,
|
||||||
<Typography.Link href="https://www.internalfb.com/intern/staticdocs/flipper/docs/getting-started/fb/connecting-to-flipper#app-on-physical-ios-device">
|
|
||||||
How To
|
|
||||||
</Typography.Link>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
'Idb lacks permissions to exchange certificates. Did you install a source build?'
|
|
||||||
);
|
);
|
||||||
notification.error({
|
|
||||||
message: 'Cannot connect to iOS application',
|
|
||||||
duration: null,
|
|
||||||
description: message,
|
|
||||||
key: 'idb_certificate_pull_failed',
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
@@ -8,13 +8,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {ChildProcess} from 'child_process';
|
import {ChildProcess} from 'child_process';
|
||||||
import type {DeviceType} from 'flipper-common';
|
import type {IOSDeviceParams} from 'flipper-common';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import childProcess from 'child_process';
|
import childProcess from 'child_process';
|
||||||
import {exec, execFile} from 'promisify-child-process';
|
import {exec, execFile} from 'promisify-child-process';
|
||||||
import iosUtil from './iOSContainerUtility';
|
import iosUtil from './iOSContainerUtility';
|
||||||
import IOSDevice from './IOSDevice';
|
import IOSDevice from './IOSDevice';
|
||||||
import {getStaticPath} from '../../../utils/pathUtils';
|
|
||||||
import {
|
import {
|
||||||
ERR_NO_IDB_OR_XCODE_AVAILABLE,
|
ERR_NO_IDB_OR_XCODE_AVAILABLE,
|
||||||
IOSBridge,
|
IOSBridge,
|
||||||
@@ -22,6 +21,7 @@ import {
|
|||||||
} from './IOSBridge';
|
} from './IOSBridge';
|
||||||
import {FlipperServerImpl} from '../../FlipperServerImpl';
|
import {FlipperServerImpl} from '../../FlipperServerImpl';
|
||||||
import {notNull} from '../../utils/typeUtils';
|
import {notNull} from '../../utils/typeUtils';
|
||||||
|
import {getFlipperServerConfig} from '../../FlipperServerConfig';
|
||||||
|
|
||||||
type iOSSimulatorDevice = {
|
type iOSSimulatorDevice = {
|
||||||
state: 'Booted' | 'Shutdown' | 'Shutting Down';
|
state: 'Booted' | 'Shutdown' | 'Shutting Down';
|
||||||
@@ -31,14 +31,6 @@ type iOSSimulatorDevice = {
|
|||||||
udid: string;
|
udid: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type IOSDeviceParams = {
|
|
||||||
udid: string;
|
|
||||||
type: DeviceType;
|
|
||||||
name: string;
|
|
||||||
deviceTypeIdentifier?: string;
|
|
||||||
state?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
function isAvailable(simulator: iOSSimulatorDevice): boolean {
|
function isAvailable(simulator: iOSSimulatorDevice): boolean {
|
||||||
// For some users "availability" is set, for others it's "isAvailable"
|
// For some users "availability" is set, for others it's "isAvailable"
|
||||||
// It's not clear which key is set, so we are checking both.
|
// It's not clear which key is set, so we are checking both.
|
||||||
@@ -53,13 +45,12 @@ function isAvailable(simulator: iOSSimulatorDevice): boolean {
|
|||||||
export class IOSDeviceManager {
|
export class IOSDeviceManager {
|
||||||
private portForwarders: Array<ChildProcess> = [];
|
private portForwarders: Array<ChildProcess> = [];
|
||||||
|
|
||||||
private portforwardingClient = getStaticPath(
|
private portforwardingClient = path.join(
|
||||||
path.join(
|
getFlipperServerConfig().staticPath,
|
||||||
'PortForwardingMacApp.app',
|
'PortForwardingMacApp.app',
|
||||||
'Contents',
|
'Contents',
|
||||||
'MacOS',
|
'MacOS',
|
||||||
'PortForwardingMacApp',
|
'PortForwardingMacApp',
|
||||||
),
|
|
||||||
);
|
);
|
||||||
iosBridge: IOSBridge | undefined;
|
iosBridge: IOSBridge | undefined;
|
||||||
private xcodeVersionMismatchFound = false;
|
private xcodeVersionMismatchFound = false;
|
||||||
@@ -114,7 +105,7 @@ export class IOSDeviceManager {
|
|||||||
isXcodeDetected: boolean,
|
isXcodeDetected: boolean,
|
||||||
isIdbAvailable: boolean,
|
isIdbAvailable: boolean,
|
||||||
): Array<Promise<any>> {
|
): Array<Promise<any>> {
|
||||||
const {config} = this.flipperServer;
|
const config = getFlipperServerConfig();
|
||||||
return [
|
return [
|
||||||
isIdbAvailable
|
isIdbAvailable
|
||||||
? getActiveDevices(config.idbPath, config.enablePhysicalIOS).then(
|
? getActiveDevices(config.idbPath, config.enablePhysicalIOS).then(
|
||||||
@@ -133,7 +124,7 @@ export class IOSDeviceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async queryDevices(): Promise<any> {
|
private async queryDevices(): Promise<any> {
|
||||||
const {config} = this.flipperServer;
|
const config = getFlipperServerConfig();
|
||||||
const isXcodeInstalled = await iosUtil.isXcodeDetected();
|
const isXcodeInstalled = await iosUtil.isXcodeDetected();
|
||||||
const isIdbAvailable = await iosUtil.isAvailable(config.idbPath);
|
const isIdbAvailable = await iosUtil.isAvailable(config.idbPath);
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
@@ -177,19 +168,19 @@ export class IOSDeviceManager {
|
|||||||
|
|
||||||
public async watchIOSDevices() {
|
public async watchIOSDevices() {
|
||||||
// TODO: pull this condition up
|
// TODO: pull this condition up
|
||||||
if (!this.flipperServer.config.enableIOS) {
|
if (!getFlipperServerConfig().enableIOS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const isDetected = await iosUtil.isXcodeDetected();
|
const isDetected = await iosUtil.isXcodeDetected();
|
||||||
this.xcodeCommandLineToolsDetected = isDetected;
|
this.xcodeCommandLineToolsDetected = isDetected;
|
||||||
if (this.flipperServer.config.enablePhysicalIOS) {
|
if (getFlipperServerConfig().enablePhysicalIOS) {
|
||||||
this.startDevicePortForwarders();
|
this.startDevicePortForwarders();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// Awaiting the promise here to trigger immediate error handling.
|
// Awaiting the promise here to trigger immediate error handling.
|
||||||
this.iosBridge = await makeIOSBridge(
|
this.iosBridge = await makeIOSBridge(
|
||||||
this.flipperServer.config.idbPath,
|
getFlipperServerConfig().idbPath,
|
||||||
isDetected,
|
isDetected,
|
||||||
);
|
);
|
||||||
this.queryDevicesForever();
|
this.queryDevicesForever();
|
||||||
@@ -7,101 +7,11 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {DeviceLogLevel} from 'flipper-common';
|
import {DeviceLogLevel, MetroReportableEvent} from 'flipper-common';
|
||||||
import util from 'util';
|
import util from 'util';
|
||||||
import {FlipperServerImpl} from '../../FlipperServerImpl';
|
import {FlipperServerImpl} from '../../FlipperServerImpl';
|
||||||
import {ServerDevice} from '../ServerDevice';
|
import {ServerDevice} from '../ServerDevice';
|
||||||
|
|
||||||
// From xplat/js/metro/packages/metro/src/lib/reporting.js
|
|
||||||
export type BundleDetails = {
|
|
||||||
entryFile: string;
|
|
||||||
platform?: string;
|
|
||||||
dev: boolean;
|
|
||||||
minify: boolean;
|
|
||||||
bundleType: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
// From xplat/js/metro/packages/metro/src/lib/reporting.js
|
|
||||||
export type GlobalCacheDisabledReason = 'too_many_errors' | 'too_many_misses';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A tagged union of all the actions that may happen and we may want to
|
|
||||||
* report to the tool user.
|
|
||||||
*
|
|
||||||
* Based on xplat/js/metro/packages/metro/src/lib/TerminalReporter.js
|
|
||||||
*/
|
|
||||||
export type MetroReportableEvent =
|
|
||||||
| {
|
|
||||||
port: number;
|
|
||||||
projectRoots: ReadonlyArray<string>;
|
|
||||||
type: 'initialize_started';
|
|
||||||
}
|
|
||||||
| {type: 'initialize_done'}
|
|
||||||
| {
|
|
||||||
type: 'initialize_failed';
|
|
||||||
port: number;
|
|
||||||
error: Error;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
buildID: string;
|
|
||||||
type: 'bundle_build_done';
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
buildID: string;
|
|
||||||
type: 'bundle_build_failed';
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
buildID: string;
|
|
||||||
bundleDetails: BundleDetails;
|
|
||||||
type: 'bundle_build_started';
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
error: Error;
|
|
||||||
type: 'bundling_error';
|
|
||||||
}
|
|
||||||
| {type: 'dep_graph_loading'}
|
|
||||||
| {type: 'dep_graph_loaded'}
|
|
||||||
| {
|
|
||||||
buildID: string;
|
|
||||||
type: 'bundle_transform_progressed';
|
|
||||||
transformedFileCount: number;
|
|
||||||
totalFileCount: number;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'global_cache_error';
|
|
||||||
error: Error;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'global_cache_disabled';
|
|
||||||
reason: GlobalCacheDisabledReason;
|
|
||||||
}
|
|
||||||
| {type: 'transform_cache_reset'}
|
|
||||||
| {
|
|
||||||
type: 'worker_stdout_chunk';
|
|
||||||
chunk: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'worker_stderr_chunk';
|
|
||||||
chunk: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'hmr_client_error';
|
|
||||||
error: Error;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'client_log';
|
|
||||||
level:
|
|
||||||
| 'trace'
|
|
||||||
| 'info'
|
|
||||||
| 'warn'
|
|
||||||
| 'log'
|
|
||||||
| 'group'
|
|
||||||
| 'groupCollapsed'
|
|
||||||
| 'groupEnd'
|
|
||||||
| 'debug';
|
|
||||||
data: Array<any>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const metroLogLevelMapping: {[key: string]: DeviceLogLevel} = {
|
const metroLogLevelMapping: {[key: string]: DeviceLogLevel} = {
|
||||||
trace: 'verbose',
|
trace: 'verbose',
|
||||||
info: 'info',
|
info: 'info',
|
||||||
@@ -7,6 +7,10 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function helloWorld() {
|
export {
|
||||||
return true;
|
FlipperServerConfig,
|
||||||
}
|
getFlipperServerConfig,
|
||||||
|
setFlipperServerConfig,
|
||||||
|
} from './FlipperServerConfig';
|
||||||
|
|
||||||
|
export {FlipperServerImpl} from './FlipperServerImpl';
|
||||||
|
|||||||
@@ -3865,7 +3865,7 @@ archiver-utils@^2.1.0:
|
|||||||
normalize-path "^3.0.0"
|
normalize-path "^3.0.0"
|
||||||
readable-stream "^2.0.0"
|
readable-stream "^2.0.0"
|
||||||
|
|
||||||
archiver@^5.0.2:
|
archiver@^5.0.2, archiver@^5.3.0:
|
||||||
version "5.3.0"
|
version "5.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.3.0.tgz#dd3e097624481741df626267564f7dd8640a45ba"
|
resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.3.0.tgz#dd3e097624481741df626267564f7dd8640a45ba"
|
||||||
integrity sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==
|
integrity sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==
|
||||||
@@ -5829,9 +5829,9 @@ electron-publish@22.11.1:
|
|||||||
mime "^2.5.0"
|
mime "^2.5.0"
|
||||||
|
|
||||||
electron-to-chromium@^1.3.857:
|
electron-to-chromium@^1.3.857:
|
||||||
version "1.3.862"
|
version "1.3.864"
|
||||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.862.tgz#c1c5d4382449e2c9b0e67fe1652f4fc451d6d8c0"
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.864.tgz#6a993bcc196a2b8b3df84d28d5d4dd912393885f"
|
||||||
integrity sha512-o+FMbCD+hAUJ9S8bfz/FaqA0gE8OpCCm58KhhGogOEqiA1BLFSoVYLi+tW+S/ZavnqBn++n0XZm7HQiBVPs8Jg==
|
integrity sha512-v4rbad8GO6/yVI92WOeU9Wgxc4NA0n4f6P1FvZTY+jyY7JHEhw3bduYu60v3Q1h81Cg6eo4ApZrFPuycwd5hGw==
|
||||||
|
|
||||||
electron@11.2.3:
|
electron@11.2.3:
|
||||||
version "11.2.3"
|
version "11.2.3"
|
||||||
@@ -10692,7 +10692,7 @@ promise@^7.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
asap "~2.0.3"
|
asap "~2.0.3"
|
||||||
|
|
||||||
promisify-child-process@^4.1.0:
|
promisify-child-process@^4.1.0, promisify-child-process@^4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/promisify-child-process/-/promisify-child-process-4.1.1.tgz#290659e079f9c7bd46708404d4488a1a6b802686"
|
resolved "https://registry.yarnpkg.com/promisify-child-process/-/promisify-child-process-4.1.1.tgz#290659e079f9c7bd46708404d4488a1a6b802686"
|
||||||
integrity sha512-/sRjHZwoXf1rJ+8s4oWjYjGRVKNK1DUnqfRC1Zek18pl0cN6k3yJ1cCbqd0tWNe4h0Gr+SY4vR42N33+T82WkA==
|
integrity sha512-/sRjHZwoXf1rJ+8s4oWjYjGRVKNK1DUnqfRC1Zek18pl0cN6k3yJ1cCbqd0tWNe4h0Gr+SY4vR42N33+T82WkA==
|
||||||
@@ -13661,7 +13661,7 @@ ws@1.1.5, ws@^1.1.5:
|
|||||||
options ">=0.0.5"
|
options ">=0.0.5"
|
||||||
ultron "1.0.x"
|
ultron "1.0.x"
|
||||||
|
|
||||||
ws@^7.4.5, ws@^7.4.6, ws@^8.2.1, ws@~7.4.2:
|
ws@^7.4.5, ws@^7.4.6, ws@^8.2.1, ws@^8.2.3, ws@~7.4.2:
|
||||||
version "7.5.5"
|
version "7.5.5"
|
||||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881"
|
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881"
|
||||||
integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==
|
integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==
|
||||||
|
|||||||
Reference in New Issue
Block a user