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
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 = {
parser: 'babel-eslint',
extends: 'fbjs',
@@ -39,17 +48,17 @@ module.exports = {
// additional rules for this project
'header/header': [2, 'block', {pattern}],
'prettier/prettier': [
2,
{
requirePragma: true,
singleQuote: true,
trailingComma: 'all',
bracketSpacing: false,
jsxBracketSameLine: true,
parser: 'flow',
},
],
'prettier/prettier': [2, prettierConfig],
'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": {
"@jest-runner/electron": "^2.0.1",
"@types/react-dom": "^16.8.5",
"@types/invariant": "^2.2.30",
"@types/jest": "^24.0.16",
"@types/react": "^16.8.24",
"@types/react-redux": "^7.1.1",
"@types/redux-persist": "^4.3.1",
"@types/rsocket-core": "^0.0.2",
"@types/uuid": "^3.4.5",
"@typescript-eslint/eslint-plugin": "^1.11.0",
"@typescript-eslint/parser": "^1.13.0",
"babel-code-frame": "^6.26.0",
"babel-eslint": "^10.0.1",
"electron": "^5.0.8",
@@ -81,6 +84,7 @@
"typescript": "^3.5.2"
},
"dependencies": {
"@types/rsocket-tcp-server": "^0.0.2",
"JSONStream": "^1.3.1",
"adbkit-fb": "2.10.1",
"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-headless": "yarn rm-dist && mkdir dist && cross-env NODE_ENV=production node scripts/build-headless.js $@",
"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-electron": "jest --testPathPattern=electron\\.js$ --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-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|tsx)$\" --detectOpenHandles --no-cache",
"lint": "eslint . --ext .js,.tsx && flow check && tsc --noemit"
},
"optionalDependencies": {

View File

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

View File

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

View File

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

View File

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

View File

@@ -21,12 +21,12 @@ type State = {
| 'checking-for-update'
| 'update-available'
| 'update-not-available'
| 'update-downloaded',
error?: string,
| 'update-downloaded';
error?: string;
};
type Props = {
version: string,
version: string;
};
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'});
});
remote.autoUpdater.on('update-available', error => {
remote.autoUpdater.on('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'});
});

View File

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

View File

@@ -7,7 +7,7 @@
import type {FlipperDevicePlugin, FlipperPlugin} from '../plugin';
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 {Component, Fragment} from 'react';

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,12 +5,12 @@
* @format
*/
import Server from '../server.js';
import Server from '../server.tsx';
import type {Store} from '../reducers/index.tsx';
import type {Logger} from '../fb-interfaces/Logger.js';
import type Client from '../Client.js';
import type {UninitializedClient} from '../UninitializedClient';
import type Client from '../Client.tsx';
import type {UninitializedClient} from '../UninitializedClient.tsx';
export default (store: Store, logger: Logger) => {
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 {Logger} from '../fb-interfaces/Logger.js';
import type Client from '../Client';
import type Client from '../Client.tsx';
export default (store: Store, logger: Logger) => {
let droppedFrames: number = 0;

View File

@@ -19,7 +19,7 @@ export {
} from './plugin.js';
export type {PluginClient, Props} from './plugin.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 * from './fb-stubs/constants.js';
export * from './fb-stubs/createPaste.js';

View File

@@ -8,7 +8,7 @@
import type {KeyboardActions} from './MenuBar.js';
import type {App} from './App.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 {MetricType} from './utils/exportMetrics.js';
import React from 'react';

View File

@@ -7,7 +7,7 @@
import type {Element} 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 {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -10,7 +10,7 @@ import {default as ArchivedDevice} from '../../devices/ArchivedDevice';
import {processStore} from '../exportData';
import {FlipperDevicePlugin} 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 {
static id = 'TestDevicePlugin';

View File

@@ -9,13 +9,13 @@ import type {Store, MiddlewareAPI} from '../reducers.tsx';
import type {DeviceExport} from '../devices/BaseDevice';
import type {State as PluginStates} from '../reducers/pluginStates.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 {pluginKey} from '../reducers/pluginStates.tsx';
import {FlipperDevicePlugin, FlipperPlugin, callClient} from '../plugin.js';
import {default as BaseDevice} from '../devices/BaseDevice';
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 uuid from 'uuid';
import {remote} from 'electron';

View File

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

View File

@@ -14,6 +14,6 @@
"flipper": ["./src/index.js"]
}
},
"include": ["src/**/*"],
"include": ["src/**/*", "types/globals.tsx"],
"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"
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@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
@@ -1084,6 +1089,11 @@
"@types/react" "*"
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":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
@@ -1173,6 +1183,40 @@
dependencies:
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":
version "1.0.1"
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"
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":
version "1.13.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz#8140f17d0f60c03619798f1d628b8434913dc32e"