client server

Summary: Migrating Server, Client and UninitializedClient to TypeScript

Reviewed By: passy

Differential Revision: D16687855

fbshipit-source-id: 402e4dbcd5d283d3e280d4d8b312662829457886
This commit is contained in:
Daniel Büchele
2019-08-08 10:55:17 -07:00
committed by Facebook Github Bot
parent 53c1eee641
commit 5f53087c7e
35 changed files with 476 additions and 371 deletions

View File

@@ -10,6 +10,15 @@ const fbjs = require('eslint-config-fbjs');
// enforces copyright header and @format directive to be present in every file // enforces copyright header and @format directive to be present in every file
const pattern = /^\*\n \* Copyright 20\d{2}-present Facebook\.\n \* This source code is licensed under the MIT license found in the\n \* LICENSE file in the root directory of this source tree\.\n \* @format\n./; const pattern = /^\*\n \* Copyright 20\d{2}-present Facebook\.\n \* This source code is licensed under the MIT license found in the\n \* LICENSE file in the root directory of this source tree\.\n \* @format\n./;
const prettierConfig = {
requirePragma: true,
singleQuote: true,
trailingComma: 'all',
bracketSpacing: false,
jsxBracketSameLine: true,
parser: 'flow',
};
module.exports = { module.exports = {
parser: 'babel-eslint', parser: 'babel-eslint',
extends: 'fbjs', extends: 'fbjs',
@@ -39,17 +48,17 @@ module.exports = {
// additional rules for this project // additional rules for this project
'header/header': [2, 'block', {pattern}], 'header/header': [2, 'block', {pattern}],
'prettier/prettier': [ 'prettier/prettier': [2, prettierConfig],
2,
{
requirePragma: true,
singleQuote: true,
trailingComma: 'all',
bracketSpacing: false,
jsxBracketSameLine: true,
parser: 'flow',
},
],
'flowtype/object-type-delimiter': [0], 'flowtype/object-type-delimiter': [0],
}, },
overrides: [
{
files: ['*.tsx'],
parser: '@typescript-eslint/parser',
rules: {
'prettier/prettier': [2, {...prettierConfig, parser: 'typescript'}],
'@typescript-eslint/no-unused-vars': [1, {argsIgnorePattern: '^_'}],
},
},
],
}; };

View File

@@ -52,12 +52,15 @@
"devDependencies": { "devDependencies": {
"@jest-runner/electron": "^2.0.1", "@jest-runner/electron": "^2.0.1",
"@types/react-dom": "^16.8.5", "@types/react-dom": "^16.8.5",
"@types/invariant": "^2.2.30",
"@types/jest": "^24.0.16", "@types/jest": "^24.0.16",
"@types/react": "^16.8.24", "@types/react": "^16.8.24",
"@types/react-redux": "^7.1.1", "@types/react-redux": "^7.1.1",
"@types/redux-persist": "^4.3.1", "@types/redux-persist": "^4.3.1",
"@types/rsocket-core": "^0.0.2",
"@types/uuid": "^3.4.5", "@types/uuid": "^3.4.5",
"@typescript-eslint/eslint-plugin": "^1.11.0", "@typescript-eslint/eslint-plugin": "^1.11.0",
"@typescript-eslint/parser": "^1.13.0",
"babel-code-frame": "^6.26.0", "babel-code-frame": "^6.26.0",
"babel-eslint": "^10.0.1", "babel-eslint": "^10.0.1",
"electron": "^5.0.8", "electron": "^5.0.8",
@@ -81,6 +84,7 @@
"typescript": "^3.5.2" "typescript": "^3.5.2"
}, },
"dependencies": { "dependencies": {
"@types/rsocket-tcp-server": "^0.0.2",
"JSONStream": "^1.3.1", "JSONStream": "^1.3.1",
"adbkit-fb": "2.10.1", "adbkit-fb": "2.10.1",
"ansi-to-html": "^0.6.3", "ansi-to-html": "^0.6.3",
@@ -147,10 +151,10 @@
"build": "yarn rm-dist && cross-env NODE_ENV=production node scripts/build-release.js $@", "build": "yarn rm-dist && cross-env NODE_ENV=production node scripts/build-release.js $@",
"build-headless": "yarn rm-dist && mkdir dist && cross-env NODE_ENV=production node scripts/build-headless.js $@", "build-headless": "yarn rm-dist && mkdir dist && cross-env NODE_ENV=production node scripts/build-headless.js $@",
"fix": "eslint . --fix --ext .js,.tsx", "fix": "eslint . --fix --ext .js,.tsx",
"test": "jest --testPathPattern=node\\.js$ --no-cache", "test": "jest --testPathPattern=\"node\\.(js|tsx)$\" --no-cache",
"test:debug": "node --inspect node_modules/.bin/jest --runInBand", "test:debug": "node --inspect node_modules/.bin/jest --runInBand",
"test-electron": "jest --testPathPattern=electron\\.js$ --testEnvironment=@jest-runner/electron/environment --runner=@jest-runner/electron --no-cache", "test-electron": "jest --testPathPattern=\"electron\\.(js|tsx)$\" --testEnvironment=@jest-runner/electron/environment --runner=@jest-runner/electron --no-cache",
"test-with-device": "USE_ELECTRON_STUBS=1 jest --testPathPattern=device\\.js$ --detectOpenHandles --no-cache", "test-with-device": "USE_ELECTRON_STUBS=1 jest --testPathPattern=\"device\\.(js|tsx)$\" --detectOpenHandles --no-cache",
"lint": "eslint . --ext .js,.tsx && flow check && tsc --noemit" "lint": "eslint . --ext .js,.tsx && flow check && tsc --noemit"
}, },
"optionalDependencies": { "optionalDependencies": {

View File

@@ -5,45 +5,54 @@
* @format * @format
*/ */
import type {FlipperPlugin, FlipperBasePlugin} from './plugin.js'; import {
import type BaseDevice from './devices/BaseDevice.js'; FlipperPlugin,
import type {App} from './App.js'; FlipperBasePlugin,
import type {Logger} from './fb-interfaces/Logger.js'; FlipperDevicePlugin,
import type {Store} from './reducers/index.tsx'; } from './plugin.js';
import type {OS} from './devices/BaseDevice.js'; import BaseDevice, {OS} from './devices/BaseDevice.js';
import {FlipperDevicePlugin} from './plugin.js'; import {App} from './App.js';
import {setPluginState} from './reducers/pluginStates.tsx'; import {Logger} from './fb-interfaces/Logger.js';
import {ReactiveSocket, PartialResponder} from 'rsocket-core'; import {Store} from './reducers/index';
// $FlowFixMe perf_hooks is a new API in node import {setPluginState} from './reducers/pluginStates';
import {RSocketClientSocket} from 'rsocket-core/RSocketClient';
import {performance} from 'perf_hooks'; import {performance} from 'perf_hooks';
import {reportPlatformFailures} from './utils/metrics'; import {reportPlatformFailures, reportPluginFailures} from './utils/metrics';
import {reportPluginFailures} from './utils/metrics';
import {default as isProduction} from './utils/isProduction.js'; import {default as isProduction} from './utils/isProduction.js';
import {registerPlugins} from './reducers/plugins.tsx'; import {registerPlugins} from './reducers/plugins';
import createTableNativePlugin from './plugins/TableNativePlugin'; import createTableNativePlugin from './plugins/TableNativePlugin';
import EventEmitter from 'events';
const EventEmitter = require('events'); import invariant from 'invariant';
const invariant = require('invariant'); import {Responder} from 'rsocket-types/ReactiveSocketTypes';
type Plugins = Array<string>; type Plugins = Array<string>;
export type ClientQuery = {| export type ClientQuery = {
app: string, app: string;
os: OS, os: OS;
device: string, device: string;
device_id: string, device_id: string;
sdk_version?: number, sdk_version?: number;
|}; };
export type ClientExport = {| export type ClientExport = {
id: string, id: string;
query: ClientQuery, query: ClientQuery;
|}; };
type ErrorType = {message: string, stacktrace: string, name: string}; type ErrorType = {message: string; stacktrace: string; name: string};
type RequestMetadata = {method: string, id: number, params: ?Object}; type Params = {
api: string;
method: string;
params?: Object;
};
type RequestMetadata = {method: string; id: number; params: Params | undefined};
const handleError = (store: Store, deviceSerial: ?string, error: ErrorType) => { const handleError = (
store: Store,
deviceSerial: string | undefined,
error: ErrorType,
) => {
if (isProduction()) { if (isProduction()) {
return; return;
} }
@@ -88,13 +97,39 @@ const handleError = (store: Store, deviceSerial: ?string, error: ErrorType) => {
}; };
export default class Client extends EventEmitter { export default class Client extends EventEmitter {
app: App;
connected: boolean;
id: string;
query: ClientQuery;
sdkVersion: number;
messageIdCounter: number;
plugins: Plugins;
connection: RSocketClientSocket<any, any> | null | undefined;
responder: Partial<Responder<any, any>>;
store: Store;
activePlugins: Set<string>;
device: Promise<BaseDevice>;
logger: Logger;
lastSeenDeviceList: Array<BaseDevice>;
broadcastCallbacks: Map<string, Map<string, Set<Function>>>;
requestCallbacks: Map<
number,
{
resolve: (data: any) => void;
reject: (err: Error) => void;
metadata: RequestMetadata;
// eslint-disable-next-line prettier/prettier
}
>;
constructor( constructor(
id: string, id: string,
query: ClientQuery, query: ClientQuery,
conn: ?ReactiveSocket, conn: RSocketClientSocket<any, any> | null | undefined,
logger: Logger, logger: Logger,
store: Store, store: Store,
plugins: ?Plugins, plugins?: Plugins | null | undefined,
) { ) {
super(); super();
this.connected = true; this.connected = true;
@@ -114,11 +149,11 @@ export default class Client extends EventEmitter {
const client = this; const client = this;
// node.js doesn't support requestIdleCallback // node.js doesn't support requestIdleCallback
const rIC = const rIC =
typeof requestIdleCallback === 'undefined' typeof window === 'undefined'
? (cb, options) => { ? (cb, _) => {
cb(); cb();
} }
: requestIdleCallback; : window.requestIdleCallback;
this.responder = { this.responder = {
fireAndForget: (payload: {data: string}) => fireAndForget: (payload: {data: string}) =>
@@ -150,10 +185,10 @@ export default class Client extends EventEmitter {
} }
this.device = reportPlatformFailures( this.device = reportPlatformFailures(
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
const device: ?BaseDevice = this.store const device = this.store
.getState() .getState()
.connections.devices.find( .connections.devices.find(
(device: BaseDevice) => device.serial === this.query.device_id, device => device.serial === this.query.device_id,
); );
if (device) { if (device) {
resolve(device); resolve(device);
@@ -167,7 +202,7 @@ export default class Client extends EventEmitter {
} }
this.lastSeenDeviceList = this.store.getState().connections.devices; this.lastSeenDeviceList = this.store.getState().connections.devices;
const matchingDevice = newDeviceList.find( const matchingDevice = newDeviceList.find(
(device: BaseDevice) => device.serial === this.query.device_id, device => device.serial === this.query.device_id,
); );
if (matchingDevice) { if (matchingDevice) {
resolve(matchingDevice); resolve(matchingDevice);
@@ -185,32 +220,7 @@ export default class Client extends EventEmitter {
); );
} }
app: App; supportsPlugin(Plugin: typeof FlipperPlugin): boolean {
connected: boolean;
id: string;
query: ClientQuery;
sdkVersion: number;
messageIdCounter: number;
plugins: Plugins;
connection: ?ReactiveSocket;
responder: PartialResponder;
store: Store;
activePlugins: Set<string>;
device: Promise<BaseDevice>;
logger: Logger;
lastSeenDeviceList: Array<BaseDevice>;
broadcastCallbacks: Map<?string, Map<string, Set<Function>>>;
requestCallbacks: Map<
number,
{|
resolve: (data: any) => void,
reject: (err: Error) => void,
metadata: RequestMetadata,
|},
>;
supportsPlugin(Plugin: Class<FlipperPlugin<>>): boolean {
return this.plugins.includes(Plugin.id); return this.plugins.includes(Plugin.id);
} }
@@ -221,9 +231,10 @@ export default class Client extends EventEmitter {
// get the supported plugins // get the supported plugins
async getPlugins(): Promise<Plugins> { async getPlugins(): Promise<Plugins> {
const plugins = await this.rawCall('getPlugins', false).then( const plugins = await this.rawCall<{plugins: Plugins}>(
data => data.plugins, 'getPlugins',
); false,
).then(data => data.plugins);
this.plugins = plugins; this.plugins = plugins;
const nativeplugins = plugins const nativeplugins = plugins
.map(plugin => /_nativeplugin_([^_]+)_([^_]+)/.exec(plugin)) .map(plugin => /_nativeplugin_([^_]+)_([^_]+)/.exec(plugin))
@@ -249,15 +260,16 @@ export default class Client extends EventEmitter {
this.emit('plugins-change'); this.emit('plugins-change');
} }
deviceSerial(): Promise<string> { async deviceSerial(): Promise<string> {
return this.device try {
.then(device => device.serial) const device = await this.device;
.catch(e => { return device.serial;
console.error( } catch (e) {
'Using "" for deviceId because client has no matching device', console.error(
); 'Using "" for deviceId because client has no matching device',
return ''; );
}); return '';
}
} }
onMessage(msg: string) { onMessage(msg: string) {
@@ -273,13 +285,13 @@ export default class Client extends EventEmitter {
return; return;
} }
const data: {| const data: {
id?: number, id?: number;
method?: string, method?: string;
params?: Object, params?: Params;
success?: Object, success?: Object;
error?: Object, error?: ErrorType;
|} = rawData; } = rawData;
console.debug(data, 'message:receive'); console.debug(data, 'message:receive');
@@ -303,7 +315,7 @@ export default class Client extends EventEmitter {
const params = data.params; const params = data.params;
invariant(params, 'expected params'); invariant(params, 'expected params');
const persistingPlugin: ?Class<FlipperBasePlugin<>> = const persistingPlugin: typeof FlipperBasePlugin | null =
this.store.getState().plugins.clientPlugins.get(params.api) || this.store.getState().plugins.clientPlugins.get(params.api) ||
this.store.getState().plugins.devicePlugins.get(params.api); this.store.getState().plugins.devicePlugins.get(params.api);
if (persistingPlugin && persistingPlugin.persistedStateReducer) { if (persistingPlugin && persistingPlugin.persistedStateReducer) {
@@ -319,7 +331,6 @@ export default class Client extends EventEmitter {
...persistingPlugin.defaultPersistedState, ...persistingPlugin.defaultPersistedState,
...this.store.getState().pluginStates[pluginKey], ...this.store.getState().pluginStates[pluginKey],
}; };
// $FlowFixMe: We checked persistedStateReducer exists
const newPluginState = persistingPlugin.persistedStateReducer( const newPluginState = persistingPlugin.persistedStateReducer(
persistedState, persistedState,
params.method, params.method,
@@ -339,7 +350,7 @@ export default class Client extends EventEmitter {
return; return;
} }
const methodCallbacks: ?Set<Function> = apiCallbacks.get(params.method); const methodCallbacks = apiCallbacks.get(params.method);
if (methodCallbacks) { if (methodCallbacks) {
for (const callback of methodCallbacks) { for (const callback of methodCallbacks) {
callback(params.params); callback(params.params);
@@ -362,11 +373,11 @@ export default class Client extends EventEmitter {
onResponse( onResponse(
data: { data: {
success?: Object, success?: Object;
error?: Object, error?: ErrorType;
}, },
resolve: any => any, resolve: (a: Object) => any,
reject: any => any, reject: (error: ErrorType) => any,
) { ) {
if (data.success) { if (data.success) {
resolve(data.success); resolve(data.success);
@@ -388,7 +399,7 @@ export default class Client extends EventEmitter {
} }
subscribe( subscribe(
api: ?string = null, api: string | null = null,
method: string, method: string,
callback: (params: Object) => void, callback: (params: Object) => void,
) { ) {
@@ -406,7 +417,7 @@ export default class Client extends EventEmitter {
methodCallbacks.add(callback); methodCallbacks.add(callback);
} }
unsubscribe(api: ?string = null, method: string, callback: Function) { unsubscribe(api: string | null = null, method: string, callback: Function) {
const apiCallbacks = this.broadcastCallbacks.get(api); const apiCallbacks = this.broadcastCallbacks.get(api);
if (!apiCallbacks) { if (!apiCallbacks) {
return; return;
@@ -419,11 +430,7 @@ export default class Client extends EventEmitter {
methodCallbacks.delete(callback); methodCallbacks.delete(callback);
} }
rawCall( rawCall<T>(method: string, fromPlugin: boolean, params?: Params): Promise<T> {
method: string,
fromPlugin: boolean,
params?: Object,
): Promise<Object> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const id = this.messageIdCounter++; const id = this.messageIdCounter++;
const metadata: RequestMetadata = { const metadata: RequestMetadata = {
@@ -442,7 +449,7 @@ export default class Client extends EventEmitter {
params, params,
}; };
const plugin = params?.api; const plugin = params ? params.api : undefined;
console.debug(data, 'message:call'); console.debug(data, 'message:call');
@@ -465,10 +472,10 @@ export default class Client extends EventEmitter {
if (!fromPlugin || this.isAcceptingMessagesFromPlugin(plugin)) { if (!fromPlugin || this.isAcceptingMessagesFromPlugin(plugin)) {
const logEventName = this.getLogEventName(data); const logEventName = this.getLogEventName(data);
this.logger.trackTimeSince(mark, logEventName); this.logger.trackTimeSince(mark, logEventName);
const response: {| const response: {
success?: Object, success?: Object;
error?: Object, error?: ErrorType;
|} = JSON.parse(payload.data); } = JSON.parse(payload.data);
this.onResponse(response, resolve, reject); this.onResponse(response, resolve, reject);
} }
}, },
@@ -493,7 +500,7 @@ export default class Client extends EventEmitter {
this.logger.trackTimeSince(mark, logEventName); this.logger.trackTimeSince(mark, logEventName);
} }
isAcceptingMessagesFromPlugin(plugin: ?string) { isAcceptingMessagesFromPlugin(plugin: string | null | undefined) {
return this.connection && (!plugin || this.activePlugins.has(plugin)); return this.connection && (!plugin || this.activePlugins.has(plugin));
} }
@@ -553,12 +560,16 @@ export default class Client extends EventEmitter {
return this.rawSend('execute', {api, method, params}); return this.rawSend('execute', {api, method, params});
} }
supportsMethod(api: string, method: string): Promise<boolean> { async supportsMethod(api: string, method: string): Promise<boolean> {
if (this.sdkVersion < 2) { if (this.sdkVersion < 2) {
return Promise.resolve(false); return Promise.resolve(false);
} }
return this.rawCall('isMethodSupported', true, {api, method}).then( const response = await this.rawCall<{
response => response.isSupported, isSupported: boolean;
); }>('isMethodSupported', true, {
api,
method,
});
return response.isSupported;
} }
} }

View File

@@ -9,7 +9,7 @@ import type {Logger} from './fb-interfaces/Logger';
import BaseDevice from './devices/BaseDevice.js'; import BaseDevice from './devices/BaseDevice.js';
import type {Props as PluginProps} from './plugin'; import type {Props as PluginProps} from './plugin';
import {pluginKey as getPluginKey} from './reducers/pluginStates.tsx'; import {pluginKey as getPluginKey} from './reducers/pluginStates.tsx';
import Client from './Client.js'; import Client from './Client.tsx';
import { import {
ErrorBoundary, ErrorBoundary,
PureComponent, PureComponent,

View File

@@ -6,7 +6,7 @@
*/ */
export type UninitializedClient = { export type UninitializedClient = {
os: string, os: string;
deviceName: string, deviceName: string;
appName: string, appName: string;
}; };

View File

@@ -5,16 +5,16 @@
* @format * @format
*/ */
import Server from '../server.js'; import Server from '../server';
import {init as initLogger} from '../fb-stubs/Logger'; import {init as initLogger} from '../fb-stubs/Logger';
import reducers from '../reducers/index.tsx'; import reducers from '../reducers/index';
import {createStore} from 'redux'; import {createStore} from 'redux';
import path from 'path'; import path from 'path';
import os from 'os'; import os from 'os';
import fs from 'fs'; import fs from 'fs';
import androidDevice from '../dispatcher/androidDevice'; import androidDevice from '../dispatcher/androidDevice';
import iosDevice from '../dispatcher/iOSDevice'; import iosDevice from '../dispatcher/iOSDevice';
import type Client from '../Client'; import Client from '../Client';
let server; let server;
let androidCleanup; let androidCleanup;

View File

@@ -7,7 +7,7 @@
import {init as initLogger} from '../fb-stubs/Logger'; import {init as initLogger} from '../fb-stubs/Logger';
import Server from '../server'; import Server from '../server';
import reducers from '../reducers/index.tsx'; import reducers from '../reducers/index';
import configureStore from 'redux-mock-store'; import configureStore from 'redux-mock-store';
import path from 'path'; import path from 'path';
import os from 'os'; import os from 'os';

View File

@@ -21,12 +21,12 @@ type State = {
| 'checking-for-update' | 'checking-for-update'
| 'update-available' | 'update-available'
| 'update-not-available' | 'update-not-available'
| 'update-downloaded', | 'update-downloaded';
error?: string, error?: string;
}; };
type Props = { type Props = {
version: string, version: string;
}; };
export default class AutoUpdateVersion extends Component<Props, State> { export default class AutoUpdateVersion extends Component<Props, State> {
@@ -63,11 +63,11 @@ export default class AutoUpdateVersion extends Component<Props, State> {
this.setState({updater: 'checking-for-update'}); this.setState({updater: 'checking-for-update'});
}); });
remote.autoUpdater.on('update-available', error => { remote.autoUpdater.on('update-available', () => {
this.setState({updater: 'update-available'}); this.setState({updater: 'update-available'});
}); });
remote.autoUpdater.on('update-not-available', error => { remote.autoUpdater.on('update-not-available', () => {
this.setState({updater: 'update-not-available'}); this.setState({updater: 'update-not-available'});
}); });

View File

@@ -8,8 +8,8 @@
import {FlipperBasePlugin} from '../plugin.js'; import {FlipperBasePlugin} from '../plugin.js';
import config from '../fb-stubs/config'; import config from '../fb-stubs/config';
import type BaseDevice from '../devices/BaseDevice.js'; import type BaseDevice from '../devices/BaseDevice.js';
import type Client from '../Client.js'; import type Client from '../Client.tsx';
import type {UninitializedClient} from '../UninitializedClient.js'; import type {UninitializedClient} from '../UninitializedClient.tsx';
import type {PluginNotification} from '../reducers/notifications.tsx'; import type {PluginNotification} from '../reducers/notifications.tsx';
import type {ActiveSheet} from '../reducers/application.tsx'; import type {ActiveSheet} from '../reducers/application.tsx';

View File

@@ -7,7 +7,7 @@
import type {FlipperDevicePlugin, FlipperPlugin} from '../plugin'; import type {FlipperDevicePlugin, FlipperPlugin} from '../plugin';
import type {PluginDefinition} from '../dispatcher/plugins'; import type {PluginDefinition} from '../dispatcher/plugins';
import type Client from '../Client'; import type Client from '../Client.tsx';
import type {TableBodyRow} from '../ui/components/table/types'; import type {TableBodyRow} from '../ui/components/table/types';
import {Component, Fragment} from 'react'; import {Component, Fragment} from 'react';

View File

@@ -59,25 +59,25 @@ const AppTitleBar = styled(FlexRow)(({focused}) => ({
})); }));
type OwnProps = { type OwnProps = {
version: string, version: string;
}; };
type DispatchFromProps = { type DispatchFromProps = {
toggleLeftSidebarVisible: (visible?: boolean) => void, toggleLeftSidebarVisible: (visible?: boolean) => void;
toggleRightSidebarVisible: (visible?: boolean) => void, toggleRightSidebarVisible: (visible?: boolean) => void;
setActiveSheet: (sheet: ActiveSheet) => void, setActiveSheet: (sheet: ActiveSheet) => void;
setFlipperRating: (rating: number) => void, setFlipperRating: (rating: number) => void;
}; };
type StateFromProps = { type StateFromProps = {
windowIsFocused: boolean, windowIsFocused: boolean;
leftSidebarVisible: boolean, leftSidebarVisible: boolean;
rightSidebarVisible: boolean, rightSidebarVisible: boolean;
rightSidebarAvailable: boolean, rightSidebarAvailable: boolean;
downloadingImportData: boolean, downloadingImportData: boolean;
launcherMsg: LauncherMsg, launcherMsg: LauncherMsg;
flipperRating: number | null, flipperRating: number | null;
share: ShareType | null | undefined, share: ShareType | null | undefined;
}; };
const VersionText = styled(Text)({ const VersionText = styled(Text)({

View File

@@ -15,7 +15,7 @@ const Container = styled(FlexRow)({
}); });
type Props = { type Props = {
launcherMsg: LauncherMsg, launcherMsg: LauncherMsg;
}; };
function getSeverityColor(severity: 'warning' | 'error'): string { function getSeverityColor(severity: 'warning' | 'error'): string {

View File

@@ -44,12 +44,12 @@ const UserName = styled(Text)({
type OwnProps = {}; type OwnProps = {};
type DispatchFromProps = { type DispatchFromProps = {
logout: () => void, logout: () => void;
setActiveSheet: (activeSheet: ActiveSheet) => void, setActiveSheet: (activeSheet: ActiveSheet) => void;
}; };
type StateFromProps = { type StateFromProps = {
user: User, user: User;
}; };
type Props = OwnProps & DispatchFromProps & StateFromProps; type Props = OwnProps & DispatchFromProps & StateFromProps;

View File

@@ -90,7 +90,7 @@ const Logo = styled('img')({
type Props = {}; type Props = {};
type State = { type State = {
isMounted: boolean, isMounted: boolean;
}; };
export default class WelcomeScreen extends PureComponent<Props, State> { export default class WelcomeScreen extends PureComponent<Props, State> {

View File

@@ -5,12 +5,12 @@
* @format * @format
*/ */
import Server from '../server.js'; import Server from '../server.tsx';
import type {Store} from '../reducers/index.tsx'; import type {Store} from '../reducers/index.tsx';
import type {Logger} from '../fb-interfaces/Logger.js'; import type {Logger} from '../fb-interfaces/Logger.js';
import type Client from '../Client.js'; import type Client from '../Client.tsx';
import type {UninitializedClient} from '../UninitializedClient'; import type {UninitializedClient} from '../UninitializedClient.tsx';
export default (store: Store, logger: Logger) => { export default (store: Store, logger: Logger) => {
const server = new Server(logger, store); const server = new Server(logger, store);

View File

@@ -11,7 +11,7 @@ import {performance} from 'perf_hooks';
import type {Store} from '../reducers/index.tsx'; import type {Store} from '../reducers/index.tsx';
import type {Logger} from '../fb-interfaces/Logger.js'; import type {Logger} from '../fb-interfaces/Logger.js';
import type Client from '../Client'; import type Client from '../Client.tsx';
export default (store: Store, logger: Logger) => { export default (store: Store, logger: Logger) => {
let droppedFrames: number = 0; let droppedFrames: number = 0;

View File

@@ -19,7 +19,7 @@ export {
} from './plugin.js'; } from './plugin.js';
export type {PluginClient, Props} from './plugin.js'; export type {PluginClient, Props} from './plugin.js';
export type {MetricType} from './utils/exportMetrics.js'; export type {MetricType} from './utils/exportMetrics.js';
export {default as Client} from './Client.js'; export {default as Client} from './Client.tsx';
export {clipboard} from 'electron'; export {clipboard} from 'electron';
export * from './fb-stubs/constants.js'; export * from './fb-stubs/constants.js';
export * from './fb-stubs/createPaste.js'; export * from './fb-stubs/createPaste.js';

View File

@@ -8,7 +8,7 @@
import type {KeyboardActions} from './MenuBar.js'; import type {KeyboardActions} from './MenuBar.js';
import type {App} from './App.js'; import type {App} from './App.js';
import type {Logger} from './fb-interfaces/Logger.js'; import type {Logger} from './fb-interfaces/Logger.js';
import type Client from './Client.js'; import type Client from './Client.tsx';
import type {Store, MiddlewareAPI} from './reducers/index.tsx'; import type {Store, MiddlewareAPI} from './reducers/index.tsx';
import type {MetricType} from './utils/exportMetrics.js'; import type {MetricType} from './utils/exportMetrics.js';
import React from 'react'; import React from 'react';

View File

@@ -7,7 +7,7 @@
import type {Element} from 'flipper'; import type {Element} from 'flipper';
import type {PluginClient} from 'flipper'; import type {PluginClient} from 'flipper';
import type Client from '../../Client.js'; import type Client from '../../Client.tsx';
import type {Logger} from '../../fb-interfaces/Logger.js'; import type {Logger} from '../../fb-interfaces/Logger.js';
import { import {

View File

@@ -33,37 +33,37 @@ export type ActiveSheet =
| null; | null;
export type LauncherMsg = { export type LauncherMsg = {
message: string, message: string;
severity: 'warning' | 'error', severity: 'warning' | 'error';
}; };
export type ServerPorts = { export type ServerPorts = {
insecure: number, insecure: number;
secure: number, secure: number;
}; };
type SubShareType = type SubShareType =
| { | {
type: 'file', type: 'file';
file: string, file: string;
} }
| {type: 'link'}; | {type: 'link'};
export type ShareType = { export type ShareType = {
statusComponent?: React.ReactNode, statusComponent?: React.ReactNode;
} & SubShareType; } & SubShareType;
export type State = { export type State = {
leftSidebarVisible: boolean, leftSidebarVisible: boolean;
rightSidebarVisible: boolean, rightSidebarVisible: boolean;
rightSidebarAvailable: boolean, rightSidebarAvailable: boolean;
windowIsFocused: boolean, windowIsFocused: boolean;
activeSheet: ActiveSheet, activeSheet: ActiveSheet;
share: ShareType | null, share: ShareType | null;
sessionId: string | null, sessionId: string | null;
serverPorts: ServerPorts, serverPorts: ServerPorts;
downloadingImportData: boolean, downloadingImportData: boolean;
launcherMsg: LauncherMsg, launcherMsg: LauncherMsg;
flipperRating: number | null, flipperRating: number | null;
}; };
type BooleanActionType = type BooleanActionType =
@@ -75,47 +75,47 @@ type BooleanActionType =
export type Action = export type Action =
| { | {
type: BooleanActionType, type: BooleanActionType;
payload?: boolean, payload?: boolean;
} }
| { | {
type: 'SET_ACTIVE_SHEET', type: 'SET_ACTIVE_SHEET';
payload: ActiveSheet, payload: ActiveSheet;
} }
| { | {
type: typeof ACTIVE_SHEET_SHARE_DATA_IN_FILE, type: typeof ACTIVE_SHEET_SHARE_DATA_IN_FILE;
payload: {file: string}, payload: {file: string};
} }
| { | {
type: typeof ACTIVE_SHEET_SELECT_PLUGINS_TO_EXPORT, type: typeof ACTIVE_SHEET_SELECT_PLUGINS_TO_EXPORT;
payload: ShareType, payload: ShareType;
} }
| { | {
type: 'SET_SERVER_PORTS', type: 'SET_SERVER_PORTS';
payload: { payload: {
insecure: number, insecure: number;
secure: number, secure: number;
}, };
} }
| { | {
type: 'LAUNCHER_MSG', type: 'LAUNCHER_MSG';
payload: { payload: {
severity: 'warning' | 'error', severity: 'warning' | 'error';
message: string, message: string;
}, };
} }
| { | {
type: 'SET_FLIPPER_RATING', type: 'SET_FLIPPER_RATING';
payload: { payload: {
rating: number, rating: number;
}, };
} }
| { | {
type: 'UNSET_SHARE', type: 'UNSET_SHARE';
} }
| { | {
type: 'SET_EXPORT_STATUS_MESSAGE', type: 'SET_EXPORT_STATUS_MESSAGE';
payload: React.ReactNode, payload: React.ReactNode;
}; };
const initialState: () => State = () => ({ const initialState: () => State = () => ({

View File

@@ -14,84 +14,84 @@ import iosUtil from '../fb-stubs/iOSContainerUtility';
import {performance} from 'perf_hooks'; import {performance} from 'perf_hooks';
export type State = { export type State = {
devices: Array<BaseDevice>, devices: Array<BaseDevice>;
androidEmulators: Array<string>, androidEmulators: Array<string>;
selectedDevice: null | BaseDevice, selectedDevice: null | BaseDevice;
selectedPlugin: null | string, selectedPlugin: null | string;
selectedApp: null | string, selectedApp: null | string;
userPreferredDevice: null | string, userPreferredDevice: null | string;
userPreferredPlugin: null | string, userPreferredPlugin: null | string;
userPreferredApp: null | string, userPreferredApp: null | string;
error: null | string, error: null | string;
clients: Array<Client>, clients: Array<Client>;
uninitializedClients: Array<{ uninitializedClients: Array<{
client: UninitializedClient, client: UninitializedClient;
deviceId?: string, deviceId?: string;
errorMessage?: string, errorMessage?: string;
}>, }>;
deepLinkPayload: null | string, deepLinkPayload: null | string;
}; };
export type Action = export type Action =
| { | {
type: 'UNREGISTER_DEVICES', type: 'UNREGISTER_DEVICES';
payload: Set<string>, payload: Set<string>;
} }
| { | {
type: 'REGISTER_DEVICE', type: 'REGISTER_DEVICE';
payload: BaseDevice, payload: BaseDevice;
} }
| { | {
type: 'REGISTER_ANDROID_EMULATORS', type: 'REGISTER_ANDROID_EMULATORS';
payload: Array<string>, payload: Array<string>;
} }
| { | {
type: 'SELECT_DEVICE', type: 'SELECT_DEVICE';
payload: BaseDevice, payload: BaseDevice;
} }
| { | {
type: 'SELECT_PLUGIN', type: 'SELECT_PLUGIN';
payload: { payload: {
selectedPlugin: null | string, selectedPlugin: null | string;
selectedApp?: null | string, selectedApp?: null | string;
deepLinkPayload: null | string, deepLinkPayload: null | string;
}, };
} }
| { | {
type: 'SELECT_USER_PREFERRED_PLUGIN', type: 'SELECT_USER_PREFERRED_PLUGIN';
payload: string, payload: string;
} }
| { | {
type: 'SERVER_ERROR', type: 'SERVER_ERROR';
payload: null | string, payload: null | string;
} }
| { | {
type: 'NEW_CLIENT', type: 'NEW_CLIENT';
payload: Client, payload: Client;
} }
| { | {
type: 'NEW_CLIENT_SANITY_CHECK', type: 'NEW_CLIENT_SANITY_CHECK';
payload: Client, payload: Client;
} }
| { | {
type: 'CLIENT_REMOVED', type: 'CLIENT_REMOVED';
payload: string, payload: string;
} }
| { | {
type: 'PREFER_DEVICE', type: 'PREFER_DEVICE';
payload: string, payload: string;
} }
| { | {
type: 'START_CLIENT_SETUP', type: 'START_CLIENT_SETUP';
payload: UninitializedClient, payload: UninitializedClient;
} }
| { | {
type: 'FINISH_CLIENT_SETUP', type: 'FINISH_CLIENT_SETUP';
payload: {client: UninitializedClient, deviceId: string}, payload: {client: UninitializedClient; deviceId: string};
} }
| { | {
type: 'CLIENT_SETUP_ERROR', type: 'CLIENT_SETUP_ERROR';
payload: {client: UninitializedClient, error: Error}, payload: {client: UninitializedClient; error: Error};
}; };
const DEFAULT_PLUGIN = 'DeviceLogs'; const DEFAULT_PLUGIN = 'DeviceLogs';
@@ -374,9 +374,9 @@ export const preferDevice = (payload: string): Action => ({
}); });
export const selectPlugin = (payload: { export const selectPlugin = (payload: {
selectedPlugin: null | string, selectedPlugin: null | string;
selectedApp?: null | string, selectedApp?: null | string;
deepLinkPayload: null | string, deepLinkPayload: null | string;
}): Action => ({ }): Action => ({
type: 'SELECT_PLUGIN', type: 'SELECT_PLUGIN',
payload, payload,

View File

@@ -43,12 +43,12 @@ type Actions =
| {type: 'INIT'}; | {type: 'INIT'};
export type State = { export type State = {
application: ApplicationState, application: ApplicationState;
connections: DevicesState, connections: DevicesState;
pluginStates: PluginStatesState, pluginStates: PluginStatesState;
notifications: NotificationsState, notifications: NotificationsState;
plugins: PluginsState, plugins: PluginsState;
user: UserState, user: UserState;
}; };
export type Store = ReduxStore<State, Actions>; export type Store = ReduxStore<State, Actions>;

View File

@@ -7,47 +7,47 @@
import {Notification} from '../plugin'; import {Notification} from '../plugin';
export type PluginNotification = { export type PluginNotification = {
notification: Notification, notification: Notification;
pluginId: string, pluginId: string;
client: null | string, client: null | string;
}; };
export type State = { export type State = {
activeNotifications: Array<PluginNotification>, activeNotifications: Array<PluginNotification>;
invalidatedNotifications: Array<PluginNotification>, invalidatedNotifications: Array<PluginNotification>;
blacklistedPlugins: Array<string>, blacklistedPlugins: Array<string>;
blacklistedCategories: Array<string>, blacklistedCategories: Array<string>;
clearedNotifications: Set<string>, clearedNotifications: Set<string>;
}; };
type ActiveNotificationsAction = { type ActiveNotificationsAction = {
type: 'SET_ACTIVE_NOTIFICATIONS', type: 'SET_ACTIVE_NOTIFICATIONS';
payload: { payload: {
notifications: Array<Notification>, notifications: Array<Notification>;
client: null | string, client: null | string;
pluginId: string, pluginId: string;
}, };
}; };
export type Action = export type Action =
| { | {
type: 'CLEAR_ALL_NOTIFICATIONS', type: 'CLEAR_ALL_NOTIFICATIONS';
} }
| { | {
type: 'SET_ACTIVE_NOTIFICATIONS', type: 'SET_ACTIVE_NOTIFICATIONS';
payload: { payload: {
notifications: Array<Notification>, notifications: Array<Notification>;
client: null | string, client: null | string;
pluginId: string, pluginId: string;
}, };
} }
| { | {
type: 'UPDATE_PLUGIN_BLACKLIST', type: 'UPDATE_PLUGIN_BLACKLIST';
payload: Array<string>, payload: Array<string>;
} }
| { | {
type: 'UPDATE_CATEGORY_BLACKLIST', type: 'UPDATE_CATEGORY_BLACKLIST';
payload: Array<string>, payload: Array<string>;
}; };
const INITIAL_STATE: State = { const INITIAL_STATE: State = {
@@ -138,9 +138,9 @@ function activeNotificationsReducer(
} }
export function setActiveNotifications(payload: { export function setActiveNotifications(payload: {
notifications: Array<Notification>, notifications: Array<Notification>;
client: null | string, client: null | string;
pluginId: string, pluginId: string;
}): Action { }): Action {
return { return {
type: 'SET_ACTIVE_NOTIFICATIONS', type: 'SET_ACTIVE_NOTIFICATIONS',

View File

@@ -6,7 +6,7 @@
*/ */
export type State = { export type State = {
[pluginKey: string]: Object, [pluginKey: string]: Object;
}; };
export const pluginKey = (serial: string, pluginName: string): string => { export const pluginKey = (serial: string, pluginName: string): string => {
@@ -15,15 +15,15 @@ export const pluginKey = (serial: string, pluginName: string): string => {
export type Action = export type Action =
| { | {
type: 'SET_PLUGIN_STATE', type: 'SET_PLUGIN_STATE';
payload: { payload: {
pluginKey: string, pluginKey: string;
state: Object, state: Object;
}, };
} }
| { | {
type: 'CLEAR_PLUGIN_STATE', type: 'CLEAR_PLUGIN_STATE';
payload: {clientId: string, devicePlugins: Set<string>}, payload: {clientId: string; devicePlugins: Set<string>};
}; };
const INITIAL_STATE: State = {}; const INITIAL_STATE: State = {};
@@ -65,8 +65,8 @@ export default function reducer(
} }
export const setPluginState = (payload: { export const setPluginState = (payload: {
pluginKey: string, pluginKey: string;
state: Object, state: Object;
}): Action => ({ }): Action => ({
type: 'SET_PLUGIN_STATE', type: 'SET_PLUGIN_STATE',
payload, payload,

View File

@@ -9,36 +9,36 @@ import {FlipperPlugin, FlipperDevicePlugin} from '../plugin.js';
import {PluginDefinition} from '../dispatcher/plugins'; import {PluginDefinition} from '../dispatcher/plugins';
export type State = { export type State = {
devicePlugins: Map<string, typeof FlipperDevicePlugin>, devicePlugins: Map<string, typeof FlipperDevicePlugin>;
clientPlugins: Map<string, typeof FlipperPlugin>, clientPlugins: Map<string, typeof FlipperPlugin>;
gatekeepedPlugins: Array<PluginDefinition>, gatekeepedPlugins: Array<PluginDefinition>;
disabledPlugins: Array<PluginDefinition>, disabledPlugins: Array<PluginDefinition>;
failedPlugins: Array<[PluginDefinition, string]>, failedPlugins: Array<[PluginDefinition, string]>;
selectedPlugins: Array<string>, selectedPlugins: Array<string>;
}; };
type P = typeof FlipperPlugin | typeof FlipperDevicePlugin; type P = typeof FlipperPlugin | typeof FlipperDevicePlugin;
export type Action = export type Action =
| { | {
type: 'REGISTER_PLUGINS', type: 'REGISTER_PLUGINS';
payload: Array<P>, payload: Array<P>;
} }
| { | {
type: 'GATEKEEPED_PLUGINS', type: 'GATEKEEPED_PLUGINS';
payload: Array<PluginDefinition>, payload: Array<PluginDefinition>;
} }
| { | {
type: 'DISABLED_PLUGINS', type: 'DISABLED_PLUGINS';
payload: Array<PluginDefinition>, payload: Array<PluginDefinition>;
} }
| { | {
type: 'FAILED_PLUGINS', type: 'FAILED_PLUGINS';
payload: Array<[PluginDefinition, string]>, payload: Array<[PluginDefinition, string]>;
} }
| { | {
type: 'SELECTED_PLUGINS', type: 'SELECTED_PLUGINS';
payload: Array<string>, payload: Array<string>;
}; };
const INITIAL_STATE: State = { const INITIAL_STATE: State = {

View File

@@ -6,21 +6,21 @@
*/ */
export type User = { export type User = {
name?: string, name?: string;
profile_picture?: { profile_picture?: {
uri: string, uri: string;
}, };
}; };
export type State = User; export type State = User;
export type Action = export type Action =
| { | {
type: 'LOGIN', type: 'LOGIN';
payload: User, payload: User;
} }
| { | {
type: 'LOGOUT', type: 'LOGOUT';
}; };
const INITIAL_STATE: State = {}; const INITIAL_STATE: State = {};

View File

@@ -5,39 +5,38 @@
* @format * @format
*/ */
import type {SecureServerConfig} from './utils/CertificateProvider'; import {SecureServerConfig} from './utils/CertificateProvider';
import type {Logger} from './fb-interfaces/Logger'; import {Logger} from './fb-interfaces/Logger';
import type {ClientQuery} from './Client.js'; import {ClientQuery} from './Client';
import type {Store} from './reducers/index.tsx'; import {Store} from './reducers/index';
import CertificateProvider from './utils/CertificateProvider'; import CertificateProvider from './utils/CertificateProvider';
import {RSocketServer, ReactiveSocket} from 'rsocket-core'; import {RSocketServer} from 'rsocket-core';
import RSocketTCPServer from 'rsocket-tcp-server'; import RSocketTCPServer from 'rsocket-tcp-server';
import {Single} from 'rsocket-flowable'; import {Single} from 'rsocket-flowable';
import Client from './Client.js'; import Client from './Client';
import type {UninitializedClient} from './UninitializedClient'; import {UninitializedClient} from './UninitializedClient';
import {reportPlatformFailures} from './utils/metrics'; import {reportPlatformFailures} from './utils/metrics';
import EventEmitter from 'events';
import invariant from 'invariant';
import tls from 'tls';
import net from 'net';
import {RSocketClientSocket} from 'rsocket-core/RSocketClient';
const EventEmitter = (require('events'): any); type ClientInfo = {
const invariant = require('invariant'); connection: RSocketClientSocket<any, any> | null | undefined;
const tls = require('tls'); client: Client;
const net = require('net'); };
type RSocket = {| declare interface Server {
fireAndForget(payload: {data: string}): void, on(event: 'new-client', callback: (client: Client) => void): this;
connectionStatus(): any, on(event: 'error', callback: (err: Error) => void): this;
close(): void, on(event: 'clients-change', callback: () => void): this;
|}; }
type ClientInfo = {| class Server extends EventEmitter {
connection: ?ReactiveSocket,
client: Client,
|};
export default class Server extends EventEmitter {
connections: Map<string, ClientInfo>; connections: Map<string, ClientInfo>;
secureServer: Promise<RSocketServer>; secureServer: Promise<RSocketServer<any, any>>;
insecureServer: Promise<RSocketServer>; insecureServer: Promise<RSocketServer<any, any>>;
certificateProvider: CertificateProvider; certificateProvider: CertificateProvider;
connectionTracker: ConnectionTracker; connectionTracker: ConnectionTracker;
logger: Logger; logger: Logger;
@@ -53,10 +52,6 @@ export default class Server extends EventEmitter {
this.store = store; this.store = store;
} }
on: ((event: 'new-client', callback: (client: Client) => void) => void) &
((event: 'error', callback: (err: Error) => void) => void) &
((event: 'clients-change', callback: () => void) => void);
init() { init() {
const {insecure, secure} = this.store.getState().application.serverPorts; const {insecure, secure} = this.store.getState().application.serverPorts;
this.initialisePromise = this.certificateProvider this.initialisePromise = this.certificateProvider
@@ -73,10 +68,10 @@ export default class Server extends EventEmitter {
startServer( startServer(
port: number, port: number,
sslConfig?: SecureServerConfig, sslConfig?: SecureServerConfig,
): Promise<RSocketServer> { ): Promise<RSocketServer<any, any>> {
const server = this; const server = this;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let rsServer; // eslint-disable-line prefer-const let rsServer: RSocketServer<any, any> | undefined; // eslint-disable-line prefer-const
const serverFactory = onConnect => { const serverFactory = onConnect => {
const transportServer = sslConfig const transportServer = sslConfig
? tls.createServer(sslConfig, socket => { ? tls.createServer(sslConfig, socket => {
@@ -115,7 +110,10 @@ export default class Server extends EventEmitter {
}); });
} }
_trustedRequestHandler = (conn: RSocket, connectRequest: {data: string}) => { _trustedRequestHandler = (
conn: RSocketClientSocket<any, any>,
connectRequest: {data: string},
) => {
const server = this; const server = this;
const clientData: ClientQuery = JSON.parse(connectRequest.data); const clientData: ClientQuery = JSON.parse(connectRequest.data);
@@ -139,10 +137,10 @@ export default class Server extends EventEmitter {
}; };
_untrustedRequestHandler = ( _untrustedRequestHandler = (
conn: RSocket, _conn: RSocketClientSocket<any, any>,
connectRequest: {data: string}, connectRequest: {data: string},
) => { ) => {
const clientData = JSON.parse(connectRequest.data); const clientData: ClientQuery = JSON.parse(connectRequest.data);
this.connectionTracker.logConnectionAttempt(clientData); this.connectionTracker.logConnectionAttempt(clientData);
const client: UninitializedClient = { const client: UninitializedClient = {
@@ -170,17 +168,17 @@ export default class Server extends EventEmitter {
return; return;
} }
const json: {| const json: {
method: 'signCertificate', method: 'signCertificate';
csr: string, csr: string;
destination: string, destination: string;
|} = rawData; } = rawData;
if (json.method === 'signCertificate') { if (json.method === 'signCertificate') {
console.debug('CSR received from device', 'server'); console.debug('CSR received from device', 'server');
const {csr, destination} = json; const {csr, destination} = json;
return new Single(subscriber => { return new Single(subscriber => {
subscriber.onSubscribe(); subscriber.onSubscribe(undefined);
reportPlatformFailures( reportPlatformFailures(
this.certificateProvider.processCertificateSigningRequest( this.certificateProvider.processCertificateSigningRequest(
csr, csr,
@@ -217,19 +215,20 @@ export default class Server extends EventEmitter {
return; return;
} }
let rawData; let json:
| {
method: 'signCertificate';
csr: string;
destination: string;
}
| undefined;
try { try {
rawData = JSON.parse(payload.data); json = JSON.parse(payload.data);
} catch (err) { } catch (err) {
console.error(`Invalid JSON: ${payload.data}`, 'server'); console.error(`Invalid JSON: ${payload.data}`, 'server');
return; return;
} }
const json: {|
method: 'signCertificate',
csr: string,
destination: string,
|} = rawData;
if (json.method === 'signCertificate') { if (json.method === 'signCertificate') {
console.debug('CSR received from device', 'server'); console.debug('CSR received from device', 'server');
const {csr, destination} = json; const {csr, destination} = json;
@@ -259,7 +258,10 @@ export default class Server extends EventEmitter {
return null; return null;
} }
addConnection(conn: ReactiveSocket, query: ClientQuery): Client { addConnection(
conn: RSocketClientSocket<any, any>,
query: ClientQuery,
): Client {
invariant(query, 'expected query'); invariant(query, 'expected query');
const id = `${query.app}#${query.os}#${query.device}#${query.device_id}`; const id = `${query.app}#${query.os}#${query.device}#${query.device_id}`;
@@ -349,3 +351,5 @@ class ConnectionTracker {
} }
} }
} }
export default Server;

View File

@@ -7,7 +7,7 @@
import type {Element} from './ElementsInspector.js'; import type {Element} from './ElementsInspector.js';
import type {PluginClient} from '../../../plugin'; import type {PluginClient} from '../../../plugin';
import type Client from '../../../Client.js'; import type Client from '../../../Client.tsx';
import type {Logger} from '../../../fb-interfaces/Logger.js'; import type {Logger} from '../../../fb-interfaces/Logger.js';
import Panel from '../Panel.js'; import Panel from '../Panel.js';
import ManagedDataInspector from '../data-inspector/ManagedDataInspector.js'; import ManagedDataInspector from '../data-inspector/ManagedDataInspector.js';

View File

@@ -6,7 +6,7 @@
*/ */
import type {Logger} from '../fb-interfaces/Logger'; import type {Logger} from '../fb-interfaces/Logger';
import Server from '../server'; import Server from '../server.tsx';
import {promisify} from 'util'; import {promisify} from 'util';
import fs from 'fs'; import fs from 'fs';
import { import {

View File

@@ -10,7 +10,7 @@ import {default as ArchivedDevice} from '../../devices/ArchivedDevice';
import {processStore} from '../exportData'; import {processStore} from '../exportData';
import {FlipperDevicePlugin} from '../../plugin.js'; import {FlipperDevicePlugin} from '../../plugin.js';
import type {Notification} from '../../plugin.js'; import type {Notification} from '../../plugin.js';
import type {ClientExport} from '../../Client.js'; import type {ClientExport} from '../../Client.tsx';
class TestDevicePlugin extends FlipperDevicePlugin { class TestDevicePlugin extends FlipperDevicePlugin {
static id = 'TestDevicePlugin'; static id = 'TestDevicePlugin';

View File

@@ -9,13 +9,13 @@ import type {Store, MiddlewareAPI} from '../reducers.tsx';
import type {DeviceExport} from '../devices/BaseDevice'; import type {DeviceExport} from '../devices/BaseDevice';
import type {State as PluginStates} from '../reducers/pluginStates.tsx'; import type {State as PluginStates} from '../reducers/pluginStates.tsx';
import type {PluginNotification} from '../reducers/notifications.tsx'; import type {PluginNotification} from '../reducers/notifications.tsx';
import type {ClientExport} from '../Client.js'; import type {ClientExport} from '../Client.tsx';
import type {State as PluginStatesState} from '../reducers/pluginStates.tsx'; import type {State as PluginStatesState} from '../reducers/pluginStates.tsx';
import {pluginKey} from '../reducers/pluginStates.tsx'; import {pluginKey} from '../reducers/pluginStates.tsx';
import {FlipperDevicePlugin, FlipperPlugin, callClient} from '../plugin.js'; import {FlipperDevicePlugin, FlipperPlugin, callClient} from '../plugin.js';
import {default as BaseDevice} from '../devices/BaseDevice'; import {default as BaseDevice} from '../devices/BaseDevice';
import {default as ArchivedDevice} from '../devices/ArchivedDevice'; import {default as ArchivedDevice} from '../devices/ArchivedDevice';
import {default as Client} from '../Client'; import {default as Client} from '../Client.tsx';
import fs from 'fs'; import fs from 'fs';
import uuid from 'uuid'; import uuid from 'uuid';
import {remote} from 'electron'; import {remote} from 'electron';

View File

@@ -46,8 +46,8 @@ function transform({filename, options, src}) {
} else { } else {
plugins.push( plugins.push(
require('../node_modules/@babel/plugin-transform-typescript'), require('../node_modules/@babel/plugin-transform-typescript'),
require('../node_modules/@babel/plugin-transform-modules-commonjs'),
require('../node_modules/@babel/plugin-proposal-class-properties'), require('../node_modules/@babel/plugin-proposal-class-properties'),
require('../node_modules/@babel/plugin-transform-modules-commonjs'),
); );
} }
@@ -73,13 +73,11 @@ function transform({filename, options, src}) {
// electron imports are working out of the box. // electron imports are working out of the box.
plugins.push(require('./electron-requires.js')); plugins.push(require('./electron-requires.js'));
} }
if (isPlugin) { if (isPlugin) {
plugins.push(require('./flipper-requires.js')); plugins.push(require('./flipper-requires.js'));
} else { } else {
plugins.push(require('./import-react.js')); plugins.push(require('./import-react.js'));
} }
ast = babel.transformFromAst(ast, src, { ast = babel.transformFromAst(ast, src, {
ast: true, ast: true,
babelrc: !filename.includes('node_modules'), babelrc: !filename.includes('node_modules'),

View File

@@ -14,6 +14,6 @@
"flipper": ["./src/index.js"] "flipper": ["./src/index.js"]
} }
}, },
"include": ["src/**/*"], "include": ["src/**/*", "types/globals.tsx"],
"exclude": ["node_modules", "**/*.spec.ts"] "exclude": ["node_modules", "**/*.spec.ts"]
} }

25
types/globals.tsx Normal file
View File

@@ -0,0 +1,25 @@
/**
* Copyright 2018-present Facebook.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* @format
*/
export {};
type RequestIdleHandle = number;
declare global {
interface Window {
// rIC not supportedin TS: https://github.com/Microsoft/TypeScript/issues/21309
requestIdleCallback: (
callback: (deadline: {
didTimeout: boolean;
timeRemaining: () => number;
}) => void,
opts?: {
timeout: number;
},
) => RequestIdleHandle;
cancelIdleCallback: (handle: RequestIdleHandle) => void;
}
}

View File

@@ -1062,6 +1062,11 @@
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.4.tgz#56eec47706f0fd0b7c694eae2f3172e6b0b769da" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.4.tgz#56eec47706f0fd0b7c694eae2f3172e6b0b769da"
integrity sha512-D9MyoQFI7iP5VdpEyPZyjjqIJ8Y8EDNQFIFVLOmeg1rI1xiHOChyUPMPRUVfqFCerxfE+yS3vMyj37F6IdtOoQ== integrity sha512-D9MyoQFI7iP5VdpEyPZyjjqIJ8Y8EDNQFIFVLOmeg1rI1xiHOChyUPMPRUVfqFCerxfE+yS3vMyj37F6IdtOoQ==
"@types/eslint-visitor-keys@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==
"@types/events@*": "@types/events@*":
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
@@ -1084,6 +1089,11 @@
"@types/react" "*" "@types/react" "*"
hoist-non-react-statics "^3.3.0" hoist-non-react-statics "^3.3.0"
"@types/invariant@^2.2.30":
version "2.2.30"
resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.30.tgz#20efa342807606ada5483731a8137cb1561e5fe9"
integrity sha512-98fB+yo7imSD2F7PF7GIpELNgtLNgo5wjivu0W5V4jx+KVVJxo6p/qN4zdzSTBWy4/sN3pPyXwnhRSD28QX+ag==
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
@@ -1173,6 +1183,40 @@
dependencies: dependencies:
redux-persist "*" redux-persist "*"
"@types/rsocket-core@*", "@types/rsocket-core@^0.0.2":
version "0.0.2"
resolved "https://registry.yarnpkg.com/@types/rsocket-core/-/rsocket-core-0.0.2.tgz#9f5d5b1acc2269a53ed2dd8185432b5b7fcdda86"
integrity sha512-dUpBxZ6f+dCw+Q9GM/OOqz5iPrU3VghfOzf/qnvE0ok7PwO//opHbOYAwXHGwCHxdDbntH4yy3NUYe0KchCZRQ==
dependencies:
"@types/node" "*"
"@types/rsocket-flowable" "*"
"@types/rsocket-types" "*"
"@types/rsocket-flowable@*":
version "0.0.2"
resolved "https://registry.yarnpkg.com/@types/rsocket-flowable/-/rsocket-flowable-0.0.2.tgz#2a795798e3bcde5905772a4acc692290e32e85aa"
integrity sha512-yBbwAjta5kWuR+DINmxEJJ1Nfy8/JUCEVFnrzlqVGk0u85Apki5GUY5mjEeDIwWVWdTUt/jXoPemdv74wBdBHg==
dependencies:
"@types/rsocket-types" "*"
"@types/rsocket-tcp-server@^0.0.2":
version "0.0.2"
resolved "https://registry.yarnpkg.com/@types/rsocket-tcp-server/-/rsocket-tcp-server-0.0.2.tgz#3eb1cf6dcde76b151c8ba8b3247c729053a8c201"
integrity sha512-BHNM/IHkaLiwW3bYBOoYJIlo93f4/mKCX4oldEYdHN8xV9yGhC/YSIrECYC3OrK1kcsnXcHzkJkqKnKSxwQ2yg==
dependencies:
"@types/node" "*"
"@types/rsocket-core" "*"
"@types/rsocket-flowable" "*"
"@types/rsocket-types" "*"
"@types/rsocket-types@*":
version "0.0.1"
resolved "https://registry.yarnpkg.com/@types/rsocket-types/-/rsocket-types-0.0.1.tgz#680b1dc908fed9c83d1ff440177aa568ca5af807"
integrity sha512-pJnPxlLMCFmBCi9ofm/OCnGEXWuaHAMY7dL/NTTltk6MnAPkpCorOG96RRCq/JPmLUb/3OOrfLoh+MXxpltcVg==
dependencies:
"@types/node" "*"
"@types/rsocket-flowable" "*"
"@types/stack-utils@^1.0.1": "@types/stack-utils@^1.0.1":
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
@@ -1210,6 +1254,16 @@
"@typescript-eslint/typescript-estree" "1.13.0" "@typescript-eslint/typescript-estree" "1.13.0"
eslint-scope "^4.0.0" eslint-scope "^4.0.0"
"@typescript-eslint/parser@^1.13.0":
version "1.13.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-1.13.0.tgz#61ac7811ea52791c47dc9fd4dd4a184fae9ac355"
integrity sha512-ITMBs52PCPgLb2nGPoeT4iU3HdQZHcPaZVw+7CsFagRJHUhyeTgorEwHXhFf3e7Evzi8oujKNpHc8TONth8AdQ==
dependencies:
"@types/eslint-visitor-keys" "^1.0.0"
"@typescript-eslint/experimental-utils" "1.13.0"
"@typescript-eslint/typescript-estree" "1.13.0"
eslint-visitor-keys "^1.0.0"
"@typescript-eslint/typescript-estree@1.13.0": "@typescript-eslint/typescript-estree@1.13.0":
version "1.13.0" version "1.13.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz#8140f17d0f60c03619798f1d628b8434913dc32e" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz#8140f17d0f60c03619798f1d628b8434913dc32e"