headless
Summary: _typescript_ Reviewed By: passy Differential Revision: D16962733 fbshipit-source-id: 6583c5a4471b12f91895f6449ed9c510265a63e2
This commit is contained in:
committed by
Facebook Github Bot
parent
7ed9e8e670
commit
853d80f182
@@ -8,46 +8,44 @@
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import {createStore} from 'redux';
|
import {createStore} from 'redux';
|
||||||
import {applyMiddleware} from 'redux';
|
import {applyMiddleware} from 'redux';
|
||||||
import yargs from 'yargs';
|
import yargs, {Argv} from 'yargs';
|
||||||
import dispatcher from '../src/dispatcher/index.tsx';
|
import dispatcher from '../src/dispatcher/index';
|
||||||
import reducers from '../src/reducers/index.tsx';
|
import reducers from '../src/reducers/index';
|
||||||
import {init as initLogger} from '../src/fb-stubs/Logger.tsx';
|
import {init as initLogger} from '../src/fb-stubs/Logger';
|
||||||
import {exportStore, pluginsClassMap} from '../src/utils/exportData.tsx';
|
import {exportStore, pluginsClassMap} from '../src/utils/exportData';
|
||||||
import {
|
import {
|
||||||
exportMetricsWithoutTrace,
|
exportMetricsWithoutTrace,
|
||||||
exportMetricsFromTrace,
|
exportMetricsFromTrace,
|
||||||
} from '../src/utils/exportMetrics.tsx';
|
} from '../src/utils/exportMetrics';
|
||||||
import {listDevices} from '../src/utils/listDevices.tsx';
|
import {listDevices} from '../src/utils/listDevices';
|
||||||
// $FlowFixMe this file exist, trust me, flow!
|
|
||||||
import setup from '../static/setup.js';
|
import setup from '../static/setup.js';
|
||||||
import type {Store} from '../src/reducers/index.tsx';
|
import {Store} from '../src/reducers/index';
|
||||||
import {getPersistentPlugins} from '../src/utils/pluginUtils.tsx';
|
import {getPersistentPlugins} from '../src/utils/pluginUtils';
|
||||||
import {serialize} from '../src/utils/serialization.tsx';
|
import {serialize} from '../src/utils/serialization';
|
||||||
import type BaseDevice from '../src/devices/BaseDevice.tsx';
|
import {getStringFromErrorLike} from '../src/utils/index';
|
||||||
|
import AndroidDevice from '../src/devices/AndroidDevice';
|
||||||
|
|
||||||
import {getStringFromErrorLike} from '../src/utils/index.tsx';
|
type Action = {exit: boolean; result?: string};
|
||||||
|
|
||||||
type Action = {|exit: true, result: string|} | {|exit: false|};
|
type UserArguments = {
|
||||||
|
securePort: string;
|
||||||
type UserArguments = {|
|
insecurePort: string;
|
||||||
securePort: string,
|
dev: boolean;
|
||||||
insecurePort: string,
|
exit: 'sigint' | 'disconnect';
|
||||||
dev: boolean,
|
verbose: boolean;
|
||||||
exit: 'sigint' | 'disconnect',
|
metrics: string;
|
||||||
verbose: boolean,
|
listDevices: boolean;
|
||||||
metrics: string,
|
device: string;
|
||||||
listDevices: boolean,
|
listPlugins: boolean;
|
||||||
device: string,
|
selectPlugins: Array<string>;
|
||||||
listPlugins: boolean,
|
};
|
||||||
selectPlugins: Array<string>,
|
|
||||||
|};
|
|
||||||
|
|
||||||
yargs
|
yargs
|
||||||
.usage('$0 [args]')
|
.usage('$0 [args]')
|
||||||
.command(
|
.command<UserArguments>(
|
||||||
'*',
|
'*',
|
||||||
'Start a headless Flipper instance',
|
'Start a headless Flipper instance',
|
||||||
yargs => {
|
(yargs: Argv<UserArguments>) => {
|
||||||
yargs.option('secure-port', {
|
yargs.option('secure-port', {
|
||||||
default: '8088',
|
default: '8088',
|
||||||
describe: 'Secure port the Flipper server should run on.',
|
describe: 'Secure port the Flipper server should run on.',
|
||||||
@@ -102,6 +100,7 @@ yargs
|
|||||||
'The identifier passed will be matched against the udid of the available devices and the matched device would be selected',
|
'The identifier passed will be matched against the udid of the available devices and the matched device would be selected',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
});
|
});
|
||||||
|
return yargs;
|
||||||
},
|
},
|
||||||
startFlipper,
|
startFlipper,
|
||||||
)
|
)
|
||||||
@@ -131,7 +130,7 @@ function errorAndExit(error: any): void {
|
|||||||
async function earlyExitActions(
|
async function earlyExitActions(
|
||||||
exitClosures: Array<(userArguments: UserArguments) => Promise<Action>>,
|
exitClosures: Array<(userArguments: UserArguments) => Promise<Action>>,
|
||||||
userArguments: UserArguments,
|
userArguments: UserArguments,
|
||||||
originalConsole: typeof global.console,
|
_originalConsole?: typeof global.console,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
for (const exitAction of exitClosures) {
|
for (const exitAction of exitClosures) {
|
||||||
try {
|
try {
|
||||||
@@ -147,7 +146,7 @@ async function earlyExitActions(
|
|||||||
|
|
||||||
async function exitActions(
|
async function exitActions(
|
||||||
exitClosures: Array<
|
exitClosures: Array<
|
||||||
(userArguments: UserArguments, store: Store) => Promise<Action>,
|
(userArguments: UserArguments, store: Store) => Promise<Action>
|
||||||
>,
|
>,
|
||||||
userArguments: UserArguments,
|
userArguments: UserArguments,
|
||||||
store: Store,
|
store: Store,
|
||||||
@@ -188,7 +187,7 @@ async function exitActions(
|
|||||||
|
|
||||||
async function storeModifyingActions(
|
async function storeModifyingActions(
|
||||||
storeModifyingClosures: Array<
|
storeModifyingClosures: Array<
|
||||||
(userArguments: UserArguments, store: Store) => Promise<Action>,
|
(userArguments: UserArguments, store: Store) => Promise<Action>
|
||||||
>,
|
>,
|
||||||
userArguments: UserArguments,
|
userArguments: UserArguments,
|
||||||
store: Store,
|
store: Store,
|
||||||
@@ -217,10 +216,10 @@ async function startFlipper(userArguments: UserArguments) {
|
|||||||
// redirect all logging to stderr
|
// redirect all logging to stderr
|
||||||
const originalConsole = global.console;
|
const originalConsole = global.console;
|
||||||
global.console = new Proxy(console, {
|
global.console = new Proxy(console, {
|
||||||
get: function(obj, prop) {
|
get: function(_obj, prop) {
|
||||||
return (...args) => {
|
return (...args) => {
|
||||||
if (prop === 'error' || verbose) {
|
if (prop === 'error' || verbose) {
|
||||||
originalConsole.error(`[${prop}] `, ...args);
|
originalConsole.error(`[${String(prop)}] `, ...args);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -275,11 +274,11 @@ async function startFlipper(userArguments: UserArguments) {
|
|||||||
const logger = initLogger(store, {isHeadless: true});
|
const logger = initLogger(store, {isHeadless: true});
|
||||||
|
|
||||||
const earlyExitClosures: Array<
|
const earlyExitClosures: Array<
|
||||||
(userArguments: UserArguments) => Promise<Action>,
|
(userArguments: UserArguments) => Promise<Action>
|
||||||
> = [
|
> = [
|
||||||
(userArguments: UserArguments) => {
|
async (userArguments: UserArguments) => {
|
||||||
if (userArguments.listDevices) {
|
if (userArguments.listDevices) {
|
||||||
return listDevices().then(async (devices: Array<BaseDevice>) => {
|
const devices = await listDevices();
|
||||||
const mapped = devices.map(device => {
|
const mapped = devices.map(device => {
|
||||||
return {
|
return {
|
||||||
os: device.os,
|
os: device.os,
|
||||||
@@ -289,7 +288,6 @@ async function startFlipper(userArguments: UserArguments) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
return {exit: true, result: await serialize(mapped)};
|
return {exit: true, result: await serialize(mapped)};
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return Promise.resolve({exit: false});
|
return Promise.resolve({exit: false});
|
||||||
},
|
},
|
||||||
@@ -300,17 +298,17 @@ async function startFlipper(userArguments: UserArguments) {
|
|||||||
const cleanupDispatchers = dispatcher(store, logger);
|
const cleanupDispatchers = dispatcher(store, logger);
|
||||||
|
|
||||||
const storeModifyingClosures: Array<
|
const storeModifyingClosures: Array<
|
||||||
(userArguments: UserArguments, store: Store) => Promise<Action>,
|
(userArguments: UserArguments, store: Store) => Promise<Action>
|
||||||
> = [
|
> = [
|
||||||
(userArguments: UserArguments, store: Store) => {
|
async (userArguments: UserArguments, store: Store) => {
|
||||||
const {device: selectedDeviceID} = userArguments;
|
const {device: selectedDeviceID} = userArguments;
|
||||||
if (selectedDeviceID) {
|
if (selectedDeviceID) {
|
||||||
return listDevices().then(devices => {
|
const devices = await listDevices();
|
||||||
const matchedDevice = devices.find(
|
const matchedDevice = devices.find(
|
||||||
device => device.serial === selectedDeviceID,
|
device => device.serial === selectedDeviceID,
|
||||||
);
|
);
|
||||||
if (matchedDevice) {
|
if (matchedDevice) {
|
||||||
if (matchedDevice.constructor.name === 'AndroidDevice') {
|
if (matchedDevice instanceof AndroidDevice) {
|
||||||
const ports = store.getState().application.serverPorts;
|
const ports = store.getState().application.serverPorts;
|
||||||
matchedDevice.reverse([ports.secure, ports.insecure]);
|
matchedDevice.reverse([ports.secure, ports.insecure]);
|
||||||
}
|
}
|
||||||
@@ -324,16 +322,13 @@ async function startFlipper(userArguments: UserArguments) {
|
|||||||
});
|
});
|
||||||
return {exit: false};
|
return {exit: false};
|
||||||
}
|
}
|
||||||
return Promise.reject(
|
throw new Error(`No device matching the serial ${selectedDeviceID}`);
|
||||||
new Error(`No device matching the serial ${selectedDeviceID}`),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return Promise.resolve({
|
return {
|
||||||
exit: false,
|
exit: false,
|
||||||
});
|
};
|
||||||
},
|
},
|
||||||
(userArguments: UserArguments, store: Store) => {
|
async (userArguments: UserArguments, store: Store) => {
|
||||||
const {selectPlugins} = userArguments;
|
const {selectPlugins} = userArguments;
|
||||||
const selectedPlugins = selectPlugins.filter(selectPlugin => {
|
const selectedPlugins = selectPlugins.filter(selectPlugin => {
|
||||||
return selectPlugin != undefined;
|
return selectPlugin != undefined;
|
||||||
@@ -344,14 +339,14 @@ async function startFlipper(userArguments: UserArguments) {
|
|||||||
payload: selectedPlugins,
|
payload: selectedPlugins,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return Promise.resolve({
|
return {
|
||||||
exit: false,
|
exit: false,
|
||||||
});
|
};
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const exitActionClosures: Array<
|
const exitActionClosures: Array<
|
||||||
(userArguments: UserArguments, store: Store) => Promise<Action>,
|
(userArguments: UserArguments, store: Store) => Promise<Action>
|
||||||
> = [
|
> = [
|
||||||
async (userArguments: UserArguments, store: Store) => {
|
async (userArguments: UserArguments, store: Store) => {
|
||||||
const {listPlugins} = userArguments;
|
const {listPlugins} = userArguments;
|
||||||
@@ -367,20 +362,19 @@ async function startFlipper(userArguments: UserArguments) {
|
|||||||
exit: false,
|
exit: false,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
(userArguments: UserArguments, store: Store) => {
|
async (userArguments: UserArguments, store: Store) => {
|
||||||
const {metrics} = userArguments;
|
const {metrics} = userArguments;
|
||||||
if (shouldExportMetric(metrics) && metrics && metrics.length > 0) {
|
if (shouldExportMetric(metrics) && metrics && metrics.length > 0) {
|
||||||
return exportMetricsFromTrace(
|
try {
|
||||||
|
const payload = await exportMetricsFromTrace(
|
||||||
metrics,
|
metrics,
|
||||||
pluginsClassMap(store.getState().plugins),
|
pluginsClassMap(store.getState().plugins),
|
||||||
store.getState().plugins.selectedPlugins,
|
store.getState().plugins.selectedPlugins,
|
||||||
)
|
);
|
||||||
.then(payload => {
|
|
||||||
return {exit: true, result: payload ? payload.toString() : ''};
|
return {exit: true, result: payload ? payload.toString() : ''};
|
||||||
})
|
} catch (error) {
|
||||||
.catch(error => {
|
|
||||||
return {exit: true, result: error};
|
return {exit: true, result: error};
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve({exit: false});
|
return Promise.resolve({exit: false});
|
||||||
},
|
},
|
||||||
@@ -93,7 +93,7 @@ async function createZip(buildDir, distDir, targets) {
|
|||||||
const distDir = path.join(__dirname, '..', 'dist');
|
const distDir = path.join(__dirname, '..', 'dist');
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log('Created build directory', buildDir);
|
console.log('Created build directory', buildDir);
|
||||||
await compile(buildDir, path.join(__dirname, '..', 'headless', 'index.js'));
|
await compile(buildDir, path.join(__dirname, '..', 'headless', 'index.tsx'));
|
||||||
const versionNumber = getVersionNumber();
|
const versionNumber = getVersionNumber();
|
||||||
const buildRevision = await genMercurialRevision();
|
const buildRevision = await genMercurialRevision();
|
||||||
await preludeBundle(buildDir, versionNumber, buildRevision);
|
await preludeBundle(buildDir, versionNumber, buildRevision);
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
"downlevelIteration": true,
|
"downlevelIteration": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"flipper": ["./src/index.js"]
|
"flipper": ["./src/index.tsx"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["src/**/*", "types/*"],
|
"include": ["src/**/*", "types/*", "headless/*"],
|
||||||
"exclude": ["node_modules", "**/*.spec.ts"]
|
"exclude": ["node_modules", "**/*.spec.ts"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,10 @@
|
|||||||
declare module NodeJS {
|
declare module NodeJS {
|
||||||
interface Global {
|
interface Global {
|
||||||
__REVISION__: string | undefined;
|
__REVISION__: string | undefined;
|
||||||
|
__VERSION__: string;
|
||||||
electronRequire: (name: string) => void;
|
electronRequire: (name: string) => void;
|
||||||
window: Window | undefined;
|
window: Window | undefined;
|
||||||
|
WebSocket: any;
|
||||||
|
fetch: any;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user