Yarn workspaces

Summary:
1) moved "sonar/desktop/src" to "sonar/desktop/app/src", so "app" is now a separate package containing the core Flipper app code
2) Configured yarn workspaces with the root in "sonar/desktop": app, static, pkg, doctor, headless-tests. Plugins are not included for now, I plan to do this later.

Reviewed By: jknoxville

Differential Revision: D20535782

fbshipit-source-id: 600b2301960f37c7d72166e0d04eba462bec9fc1
This commit is contained in:
Anton Nikolaev
2020-03-20 13:31:37 -07:00
committed by Facebook GitHub Bot
parent 676d7bbd24
commit 863f89351e
340 changed files with 1635 additions and 294 deletions

View File

@@ -0,0 +1,187 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {Store} from '../reducers/index';
import {Logger} from '../fb-interfaces/Logger';
import {FlipperPlugin, FlipperDevicePlugin} from '../plugin';
import {State} from '../reducers/plugins';
import React from 'react';
import ReactDOM from 'react-dom';
import adbkit from 'adbkit';
import * as Flipper from '../index';
import {
registerPlugins,
addGatekeepedPlugins,
addDisabledPlugins,
addFailedPlugins,
} from '../reducers/plugins';
import {ipcRenderer} from 'electron';
import GK from '../fb-stubs/GK';
import {FlipperBasePlugin} from '../plugin';
import {setupMenuBar} from '../MenuBar';
import path from 'path';
import {default as config} from '../utils/processConfig';
import isProduction from '../utils/isProduction';
import {notNull} from '../utils/typeUtils';
export type PluginDefinition = {
id?: string;
name: string;
out?: string;
gatekeeper?: string;
entry?: string;
};
export default (store: Store, _logger: Logger) => {
// expose Flipper and exact globally for dynamically loaded plugins
const globalObject: any = typeof window === 'undefined' ? global : window;
globalObject.React = React;
globalObject.ReactDOM = ReactDOM;
globalObject.Flipper = Flipper;
globalObject.adbkit = adbkit;
const gatekeepedPlugins: Array<PluginDefinition> = [];
const disabledPlugins: Array<PluginDefinition> = [];
const failedPlugins: Array<[PluginDefinition, string]> = [];
const initialPlugins: Array<
typeof FlipperPlugin | typeof FlipperDevicePlugin
> = [...getBundledPlugins(), ...getDynamicPlugins()]
.filter(checkDisabled(disabledPlugins))
.filter(checkGK(gatekeepedPlugins))
.map(requirePlugin(failedPlugins))
.filter(notNull);
store.dispatch(addGatekeepedPlugins(gatekeepedPlugins));
store.dispatch(addDisabledPlugins(disabledPlugins));
store.dispatch(addFailedPlugins(failedPlugins));
store.dispatch(registerPlugins(initialPlugins));
let state: State | null = null;
store.subscribe(() => {
const newState = store.getState().plugins;
if (state !== newState) {
setupMenuBar(
[
...newState.devicePlugins.values(),
...newState.clientPlugins.values(),
],
store,
);
}
state = newState;
});
};
function getBundledPlugins(): Array<PluginDefinition> {
if (!isProduction() || process.env.FLIPPER_NO_EMBEDDED_PLUGINS) {
// Plugins are only bundled in production builds
return [];
}
// DefaultPlugins that are included in the bundle.
// List of defaultPlugins is written at build time
const pluginPath =
process.env.BUNDLED_PLUGIN_PATH || path.join(__dirname, 'defaultPlugins');
let bundledPlugins: Array<PluginDefinition> = [];
try {
bundledPlugins = global.electronRequire(
path.join(pluginPath, 'index.json'),
);
} catch (e) {
console.error(e);
}
return bundledPlugins
.filter(plugin => notNull(plugin.out))
.map(plugin => ({
...plugin,
out: path.join(pluginPath, plugin.out!),
}));
}
export function getDynamicPlugins() {
let dynamicPlugins: Array<PluginDefinition> = [];
try {
dynamicPlugins = ipcRenderer.sendSync('get-dynamic-plugins');
} catch (e) {
console.error(e);
}
return dynamicPlugins;
}
export const checkGK = (gatekeepedPlugins: Array<PluginDefinition>) => (
plugin: PluginDefinition,
): boolean => {
if (!plugin.gatekeeper) {
return true;
}
const result = GK.get(plugin.gatekeeper);
if (!result) {
gatekeepedPlugins.push(plugin);
}
return result;
};
export const checkDisabled = (disabledPlugins: Array<PluginDefinition>) => (
plugin: PluginDefinition,
): boolean => {
let disabledList: Set<string> = new Set();
try {
disabledList = config().disabledPlugins;
} catch (e) {
console.error(e);
}
if (disabledList.has(plugin.name)) {
disabledPlugins.push(plugin);
}
return !disabledList.has(plugin.name);
};
export const requirePlugin = (
failedPlugins: Array<[PluginDefinition, string]>,
reqFn: Function = global.electronRequire,
) => {
return (
pluginDefinition: PluginDefinition,
): typeof FlipperPlugin | typeof FlipperDevicePlugin | null => {
try {
let plugin = reqFn(pluginDefinition.out);
if (plugin.default) {
plugin = plugin.default;
}
if (!(plugin.prototype instanceof FlipperBasePlugin)) {
throw new Error(`Plugin ${plugin.name} is not a FlipperBasePlugin`);
}
// set values from package.json as static variables on class
Object.keys(pluginDefinition).forEach(key => {
if (key === 'name') {
plugin.id = plugin.id || pluginDefinition.name;
} else if (key === 'id') {
throw new Error(
'Field "id" not allowed in package.json. The plugin\'s name will be used as ID"',
);
} else {
plugin[key] =
plugin[key] || pluginDefinition[key as keyof PluginDefinition];
}
});
return plugin;
} catch (e) {
failedPlugins.push([pluginDefinition, e.message]);
console.error(pluginDefinition, e);
return null;
}
};
};