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,240 @@
/**
* 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 {FlipperDevicePlugin, FlipperPlugin, FlipperBasePlugin} from '../plugin';
import BaseDevice from '../devices/BaseDevice';
import {State as PluginStatesState} from '../reducers/pluginStates';
import {State as PluginsState} from '../reducers/plugins';
import {State as PluginMessageQueueState} from '../reducers/pluginMessageQueue';
import {PluginDefinition} from '../dispatcher/plugins';
import {deconstructPluginKey, deconstructClientId} from './clientUtils';
type Client = import('../Client').default;
export function pluginsClassMap(
plugins: PluginsState,
): Map<string, typeof FlipperDevicePlugin | typeof FlipperPlugin> {
const pluginsMap: Map<
string,
typeof FlipperDevicePlugin | typeof FlipperPlugin
> = new Map([]);
plugins.clientPlugins.forEach((val, key) => {
pluginsMap.set(key, val);
});
plugins.devicePlugins.forEach((val, key) => {
pluginsMap.set(key, val);
});
return pluginsMap;
}
export function getPluginKey(
selectedAppId: string | null,
baseDevice: BaseDevice | null,
pluginID: string,
): string {
if (selectedAppId) {
return `${selectedAppId}#${pluginID}`;
}
if (baseDevice) {
// If selected App is not defined, then the plugin is a device plugin
return `${baseDevice.serial}#${pluginID}`;
}
return `unknown#${pluginID}`;
}
export function getPersistedState<PersistedState>(
pluginKey: string,
persistingPlugin: typeof FlipperBasePlugin | null,
pluginStates: PluginStatesState,
): PersistedState | null {
if (!persistingPlugin) {
return null;
}
const persistedState: PersistedState = {
...persistingPlugin.defaultPersistedState,
...pluginStates[pluginKey],
};
return persistedState;
}
/**
*
* @param starredPlugin starredPlugin is the dictionary of client and its enabled plugin
* @param client Optional paramater indicating the selected client.
* @param plugins Plugins from the state which has the mapping to Plugin's Class.
* Returns plugins which are enabled or which has exportPersistedState function defined for the passed client.
* Note all device plugins are enabled.
*/
export function getEnabledOrExportPersistedStatePlugins(
starredPlugin: {
[client: string]: string[];
},
client: Client,
plugins: PluginsState,
): Array<{id: string; label: string}> {
const appName = deconstructClientId(client.id).app;
const pluginsMap: Map<
string,
typeof FlipperDevicePlugin | typeof FlipperPlugin
> = pluginsClassMap(plugins);
// Enabled Plugins with no exportPersistedState function defined
const enabledPlugins = starredPlugin[appName]
? starredPlugin[appName]
.map(pluginName => pluginsMap.get(pluginName)!)
.filter(plugin => {
return !plugin.exportPersistedState;
})
.sort(sortPluginsByName)
.map(plugin => {
return {id: plugin.id, label: getPluginTitle(plugin)};
})
: [];
// Device Plugins
const devicePlugins = Array.from(plugins.devicePlugins.keys())
.filter(plugin => {
return client.plugins.includes(plugin);
})
.map(plugin => {
return {
id: plugin,
label: getPluginTitle(plugins.devicePlugins.get(plugin)!),
};
});
// Plugins which have defined exportPersistedState.
const exportPersistedStatePlugins = client.plugins
.filter(name => {
return pluginsMap.get(name)?.exportPersistedState != null;
})
.map(name => {
const plugin = pluginsMap.get(name)!;
return {id: plugin.id, label: getPluginTitle(plugin)};
});
return [
...devicePlugins,
...enabledPlugins,
...exportPersistedStatePlugins,
{id: 'DeviceLogs', label: 'Logs'},
];
}
/**
*
* @param pluginsState PluginsState of the Redux Store.
* @param plugins Plugins from the state which has the mapping to Plugin's Class.
* @param selectedClient Optional paramater indicating the selected client.
* Returns active persistent plugin, which means plugins which has the data in redux store or has the `exportPersistedState` function defined which can return the plugin's data when called.
* If the selectedClient is defined then the active persistent plugins only for the selectedClient will be returned, otherwise it will return all active persistent plugins.
*/
export function getActivePersistentPlugins(
pluginsState: PluginStatesState,
pluginsMessageQueue: PluginMessageQueueState,
plugins: PluginsState,
selectedClient?: Client,
): {id: string; label: string}[] {
const pluginsMap: Map<
string,
typeof FlipperDevicePlugin | typeof FlipperPlugin
> = pluginsClassMap(plugins);
return getPersistentPlugins(plugins)
.map(pluginName => pluginsMap.get(pluginName)!)
.sort(sortPluginsByName)
.map(plugin => {
const keys = [
...new Set([
...Object.keys(pluginsState),
...Object.keys(pluginsMessageQueue),
]),
]
.filter(k => !selectedClient || k.includes(selectedClient.id))
.map(key => deconstructPluginKey(key).pluginName);
let result = plugin.id == 'DeviceLogs';
const pluginsWithExportPersistedState =
plugin && plugin.exportPersistedState != undefined;
const pluginsWithReduxData = keys.includes(plugin.id);
if (!result && selectedClient) {
// If there is a selected client, active persistent plugin is the plugin which is active for selectedClient and also persistent.
result =
selectedClient.plugins.includes(plugin.id) &&
(pluginsWithExportPersistedState || pluginsWithReduxData);
} else if (!result && !selectedClient) {
// If there is no selected client, active persistent plugin is the plugin which is just persistent.
result =
(plugin && plugin.exportPersistedState != undefined) ||
keys.includes(plugin.id);
}
return (result
? {
id: plugin.id,
label: getPluginTitle(plugin),
}
: undefined)!;
})
.filter(Boolean);
}
export function getPersistentPlugins(plugins: PluginsState): Array<string> {
const pluginsMap: Map<
string,
typeof FlipperDevicePlugin | typeof FlipperPlugin
> = pluginsClassMap(plugins);
const arr: Array<PluginDefinition> = plugins.disabledPlugins.concat(
plugins.gatekeepedPlugins,
);
arr.forEach((plugin: PluginDefinition) => {
if (pluginsMap.has(plugin.name)) {
pluginsMap.delete(plugin.name);
}
});
plugins.failedPlugins.forEach((plugin: [PluginDefinition, string]) => {
if (plugin[0] && plugin[0].name && pluginsMap.has(plugin[0].name)) {
pluginsMap.delete(plugin[0].name);
}
});
const activePlugins = [...pluginsMap.keys()];
return activePlugins.filter(plugin => {
const pluginClass = pluginsMap.get(plugin);
return (
plugin == 'DeviceLogs' ||
(pluginClass &&
(pluginClass.defaultPersistedState != undefined ||
pluginClass.exportPersistedState != undefined))
);
});
}
export function getPluginTitle(pluginClass: typeof FlipperBasePlugin) {
return pluginClass.title || pluginClass.id;
}
export function sortPluginsByName(
a: typeof FlipperBasePlugin,
b: typeof FlipperBasePlugin,
): number {
// make sure Device plugins are sorted before normal plugins
if (
a.prototype instanceof FlipperDevicePlugin &&
!(b.prototype instanceof FlipperDevicePlugin)
) {
return -1;
}
if (
b.prototype instanceof FlipperDevicePlugin &&
!(a.prototype instanceof FlipperDevicePlugin)
) {
return 1;
}
return getPluginTitle(a) > getPluginTitle(b) ? 1 : -1;
}