Introduce types for Sandy plugins through code base
Summary:
So far there were 2 types of plugins: `FlipperPlugin` and `FlipperDevicePlugin`. This introduces a third kind: `SandyPluginDefinition`.
Unlike with the old plugins, the export of the module is not directly exposed as the plugin definition. Rather, we use class `SandyPluginDefinition` (instance) that holds a loaded definition and its meta data separately (`PluginDetails`). This means that we don't have to mix in and mutate loaded definitions, and that for unit tests we can avoid needing to provide a bunch of meta data. This also prevents a bunch of meta data existing on two places: on the loaded classes as static fields, and in the meta data field of the loaded class as well. Finally, we can now freely extends the `PluginDetails` interface in flipper, without needing to store it on the loaded classes and we are sure that no naming conflicts are caused by this in the future.
For compatibility with the existing code base, common fields are delegated from the `SandyPluginDefinition` class to the meta data.
Also cleaned up types around plugins a little bit and removed some unnecessary casts.
For all features that reason about plugins in general (such as exports), sandy plugins are ignored for now.
`SandyPluginInstance` is worked out in further diffs
The `instanceof` calls are replaced by a utility function in later diffs.
{F241363645}
Reviewed By: jknoxville
Differential Revision: D22091432
fbshipit-source-id: 3aa6b12fda5925268913779f3c3c9e84494438f8
This commit is contained in:
committed by
Facebook GitHub Bot
parent
845c9b67f5
commit
1029a6c97c
@@ -20,10 +20,12 @@ import Client, {ClientExport, ClientQuery} from '../Client';
|
||||
import {pluginKey} from '../reducers/pluginStates';
|
||||
import {
|
||||
FlipperDevicePlugin,
|
||||
FlipperPlugin,
|
||||
callClient,
|
||||
supportsMethod,
|
||||
FlipperBasePlugin,
|
||||
PluginDefinition,
|
||||
DevicePluginMap,
|
||||
ClientPluginMap,
|
||||
} from '../plugin';
|
||||
import {default as BaseDevice} from '../devices/BaseDevice';
|
||||
import {default as ArchivedDevice} from '../devices/ArchivedDevice';
|
||||
@@ -47,6 +49,7 @@ import {processMessageQueue} from './messageQueue';
|
||||
import {getPluginTitle} from './pluginUtils';
|
||||
import {capture} from './screenshot';
|
||||
import {uploadFlipperMedia} from '../fb-stubs/user';
|
||||
import {SandyPluginDefinition} from 'flipper-plugin';
|
||||
|
||||
export const IMPORT_FLIPPER_TRACE_EVENT = 'import-flipper-trace';
|
||||
export const EXPORT_FLIPPER_TRACE_EVENT = 'export-flipper-trace';
|
||||
@@ -93,7 +96,7 @@ type PluginsToProcess = {
|
||||
pluginKey: string;
|
||||
pluginId: string;
|
||||
pluginName: string;
|
||||
pluginClass: typeof FlipperPlugin | typeof FlipperDevicePlugin;
|
||||
pluginClass: PluginDefinition;
|
||||
client: Client;
|
||||
}[];
|
||||
|
||||
@@ -212,14 +215,17 @@ export function processNotificationStates(
|
||||
|
||||
const serializePluginStates = async (
|
||||
pluginStates: PluginStatesState,
|
||||
clientPlugins: Map<string, typeof FlipperPlugin>,
|
||||
devicePlugins: Map<string, typeof FlipperDevicePlugin>,
|
||||
clientPlugins: ClientPluginMap,
|
||||
devicePlugins: DevicePluginMap,
|
||||
statusUpdate?: (msg: string) => void,
|
||||
idler?: Idler,
|
||||
): Promise<PluginStatesExportState> => {
|
||||
const pluginsMap: Map<string, typeof FlipperBasePlugin> = new Map([]);
|
||||
clientPlugins.forEach((val, key) => {
|
||||
pluginsMap.set(key, val);
|
||||
// TODO: Support Sandy T68683449 and use ClientPluginsMap
|
||||
if (!(val instanceof SandyPluginDefinition)) {
|
||||
pluginsMap.set(key, val);
|
||||
}
|
||||
});
|
||||
devicePlugins.forEach((val, key) => {
|
||||
pluginsMap.set(key, val);
|
||||
@@ -248,12 +254,13 @@ const serializePluginStates = async (
|
||||
|
||||
const deserializePluginStates = (
|
||||
pluginStatesExportState: PluginStatesExportState,
|
||||
clientPlugins: Map<string, typeof FlipperPlugin>,
|
||||
devicePlugins: Map<string, typeof FlipperDevicePlugin>,
|
||||
clientPlugins: ClientPluginMap,
|
||||
devicePlugins: DevicePluginMap,
|
||||
): PluginStatesState => {
|
||||
const pluginsMap: Map<string, typeof FlipperBasePlugin> = new Map([]);
|
||||
clientPlugins.forEach((val, key) => {
|
||||
pluginsMap.set(key, val);
|
||||
// TODO: Support Sandy T68683449
|
||||
if (!(val instanceof SandyPluginDefinition)) pluginsMap.set(key, val);
|
||||
});
|
||||
devicePlugins.forEach((val, key) => {
|
||||
pluginsMap.set(key, val);
|
||||
@@ -358,8 +365,8 @@ type ProcessStoreOptions = {
|
||||
device: BaseDevice | null;
|
||||
pluginStates: PluginStatesState;
|
||||
clients: Array<ClientExport>;
|
||||
devicePlugins: Map<string, typeof FlipperDevicePlugin>;
|
||||
clientPlugins: Map<string, typeof FlipperPlugin>;
|
||||
devicePlugins: DevicePluginMap;
|
||||
clientPlugins: ClientPluginMap;
|
||||
salt: string;
|
||||
selectedPlugins: Array<string>;
|
||||
statusUpdate?: (msg: string) => void;
|
||||
@@ -514,7 +521,11 @@ async function processQueues(
|
||||
pluginKey,
|
||||
pluginClass,
|
||||
} of pluginsToProcess) {
|
||||
if (pluginClass.persistedStateReducer) {
|
||||
// TODO: Support Sandy T68683449
|
||||
if (
|
||||
!(pluginClass instanceof SandyPluginDefinition) &&
|
||||
pluginClass.persistedStateReducer
|
||||
) {
|
||||
const processQueueMarker = `${EXPORT_FLIPPER_TRACE_EVENT}:process-queue-per-plugin`;
|
||||
performance.mark(processQueueMarker);
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
import {FlipperPlugin, FlipperDevicePlugin} from 'flipper';
|
||||
import {serialize} from './serialization';
|
||||
import {State as PluginStatesState} from '../reducers/pluginStates';
|
||||
import {Store} from '../reducers';
|
||||
@@ -20,6 +19,8 @@ import {
|
||||
import {deserializeObject} from './serialization';
|
||||
import {deconstructPluginKey} from './clientUtils';
|
||||
import {pluginsClassMap} from './pluginUtils';
|
||||
import {PluginDefinition} from '../plugin';
|
||||
import {SandyPluginDefinition} from 'flipper-plugin';
|
||||
|
||||
export type MetricType = {[metricName: string]: number};
|
||||
type MetricPluginType = {[pluginID: string]: MetricType};
|
||||
@@ -27,7 +28,7 @@ export type ExportMetricType = {[clientID: string]: MetricPluginType};
|
||||
|
||||
async function exportMetrics(
|
||||
pluginStates: PluginStatesState,
|
||||
pluginsMap: Map<string, typeof FlipperDevicePlugin | typeof FlipperPlugin>,
|
||||
pluginsMap: Map<string, PluginDefinition>,
|
||||
selectedPlugins: Array<string>,
|
||||
): Promise<string> {
|
||||
const metrics: ExportMetricType = {};
|
||||
@@ -46,8 +47,10 @@ async function exportMetrics(
|
||||
const pluginClass = pluginsMap.get(pluginName);
|
||||
const metricsReducer:
|
||||
| (<U>(persistedState: U) => Promise<MetricType>)
|
||||
| null
|
||||
| undefined = pluginClass && pluginClass.metricsReducer;
|
||||
| undefined =
|
||||
pluginClass && !(pluginClass instanceof SandyPluginDefinition)
|
||||
? pluginClass.metricsReducer
|
||||
: undefined;
|
||||
if (pluginsMap.has(pluginName) && metricsReducer) {
|
||||
const metricsObject = await metricsReducer(pluginStateData);
|
||||
const pluginObject: MetricPluginType = {};
|
||||
@@ -67,10 +70,7 @@ export async function exportMetricsWithoutTrace(
|
||||
store: Store,
|
||||
pluginStates: PluginStatesState,
|
||||
): Promise<string | null> {
|
||||
const pluginsMap: Map<
|
||||
string,
|
||||
typeof FlipperDevicePlugin | typeof FlipperPlugin
|
||||
> = pluginsClassMap(store.getState().plugins);
|
||||
const pluginsMap = pluginsClassMap(store.getState().plugins);
|
||||
const {clients, selectedDevice} = store.getState().connections;
|
||||
const pluginsToProcess = determinePluginsToProcess(
|
||||
clients,
|
||||
@@ -107,7 +107,7 @@ function parseJSON(str: string): any {
|
||||
|
||||
export async function exportMetricsFromTrace(
|
||||
trace: string,
|
||||
pluginsMap: Map<string, typeof FlipperDevicePlugin | typeof FlipperPlugin>,
|
||||
pluginsMap: Map<string, PluginDefinition>,
|
||||
selectedPlugins: Array<string>,
|
||||
): Promise<string> {
|
||||
const data = fs.readFileSync(trace, 'utf8');
|
||||
@@ -136,5 +136,6 @@ export async function exportMetricsFromTrace(
|
||||
),
|
||||
);
|
||||
}
|
||||
// TODO: Support Sandy T68683449 and use ClientPluginsMap, or kill feature
|
||||
return await exportMetrics(pluginStates, pluginsMap, selectedPlugins);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import {pluginIsStarred, getSelectedPluginKey} from '../reducers/connections';
|
||||
import {deconstructPluginKey} from './clientUtils';
|
||||
import {onBytesReceived} from '../dispatcher/tracking';
|
||||
import {defaultEnabledBackgroundPlugins} from './pluginUtils';
|
||||
import {SandyPluginDefinition} from 'flipper-plugin';
|
||||
|
||||
const MAX_BACKGROUND_TASK_TIME = 25;
|
||||
|
||||
@@ -189,14 +190,22 @@ export function processMessagesImmediately(
|
||||
export function processMessagesLater(
|
||||
store: MiddlewareAPI,
|
||||
pluginKey: string,
|
||||
plugin: {
|
||||
defaultPersistedState: any;
|
||||
id: string;
|
||||
persistedStateReducer: PersistedStateReducer | null;
|
||||
maxQueueSize?: number;
|
||||
},
|
||||
plugin:
|
||||
| {
|
||||
defaultPersistedState: any;
|
||||
id: string;
|
||||
persistedStateReducer: PersistedStateReducer | null;
|
||||
maxQueueSize?: number;
|
||||
}
|
||||
| SandyPluginDefinition,
|
||||
messages: Message[],
|
||||
) {
|
||||
if (plugin instanceof SandyPluginDefinition) {
|
||||
// TODO:
|
||||
throw new Error(
|
||||
'Receiving messages is not yet supported for Sandy plugins',
|
||||
);
|
||||
}
|
||||
const isSelected =
|
||||
pluginKey === getSelectedPluginKey(store.getState().connections);
|
||||
switch (true) {
|
||||
|
||||
@@ -8,21 +8,21 @@
|
||||
*/
|
||||
|
||||
import {Store} from '../reducers/index';
|
||||
import {FlipperPlugin, FlipperDevicePlugin} from '../plugin';
|
||||
import {ClientPluginMap, DevicePluginMap, PluginDefinition} from '../plugin';
|
||||
import {setPluginState} from '../reducers/pluginStates';
|
||||
import BaseDevice from '../devices/BaseDevice';
|
||||
import {getPersistedState} from '../utils/pluginUtils';
|
||||
import {SandyPluginDefinition} from 'flipper-plugin';
|
||||
|
||||
export function registerDeviceCallbackOnPlugins(
|
||||
store: Store,
|
||||
devicePlugins: Map<string, typeof FlipperDevicePlugin>,
|
||||
clientPlugins: Map<string, typeof FlipperPlugin>,
|
||||
devicePlugins: DevicePluginMap,
|
||||
clientPlugins: ClientPluginMap,
|
||||
device: BaseDevice,
|
||||
) {
|
||||
const callRegisterDeviceHook = (
|
||||
plugin: typeof FlipperDevicePlugin | typeof FlipperPlugin,
|
||||
) => {
|
||||
if (plugin.onRegisterDevice) {
|
||||
const callRegisterDeviceHook = (plugin: PluginDefinition) => {
|
||||
// This hook is not registered for Sandy plugins, let's see in the future if it is needed
|
||||
if (!(plugin instanceof SandyPluginDefinition) && plugin.onRegisterDevice) {
|
||||
plugin.onRegisterDevice(
|
||||
store,
|
||||
device,
|
||||
|
||||
@@ -12,6 +12,7 @@ import fs from 'fs';
|
||||
import {Store, State} from '../reducers';
|
||||
import {getPluginKey} from './pluginUtils';
|
||||
import {serialize} from './serialization';
|
||||
import {SandyPluginDefinition} from 'flipper-plugin';
|
||||
|
||||
let pluginRecordingState: {
|
||||
recording: string;
|
||||
@@ -67,7 +68,10 @@ async function flipperStartPluginRecording(state: State) {
|
||||
// Note that we don't use the plugin's own serializeState, as that might interact with the
|
||||
// device state, and is used for creating Flipper Exports.
|
||||
pluginRecordingState.startState = await serialize(
|
||||
state.pluginStates[pluginKey] || plugin.defaultPersistedState,
|
||||
state.pluginStates[pluginKey] ||
|
||||
(plugin instanceof SandyPluginDefinition
|
||||
? {}
|
||||
: plugin.defaultPersistedState),
|
||||
);
|
||||
|
||||
console.log(
|
||||
|
||||
@@ -7,12 +7,18 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
import {FlipperDevicePlugin, FlipperPlugin, FlipperBasePlugin} from '../plugin';
|
||||
import {
|
||||
FlipperDevicePlugin,
|
||||
FlipperBasePlugin,
|
||||
PluginDefinition,
|
||||
DevicePluginDefinition,
|
||||
} from '../plugin';
|
||||
import {State as PluginStatesState} from '../reducers/pluginStates';
|
||||
import {State as PluginsState} from '../reducers/plugins';
|
||||
import {State as PluginMessageQueueState} from '../reducers/pluginMessageQueue';
|
||||
import {PluginDetails} from 'flipper-plugin-lib';
|
||||
import {deconstructPluginKey, deconstructClientId} from './clientUtils';
|
||||
import {SandyPluginDefinition} from 'flipper-plugin';
|
||||
|
||||
type Client = import('../Client').default;
|
||||
|
||||
@@ -20,11 +26,8 @@ export const defaultEnabledBackgroundPlugins = ['Navigation']; // The navigation
|
||||
|
||||
export function pluginsClassMap(
|
||||
plugins: PluginsState,
|
||||
): Map<string, typeof FlipperDevicePlugin | typeof FlipperPlugin> {
|
||||
const pluginsMap: Map<
|
||||
string,
|
||||
typeof FlipperDevicePlugin | typeof FlipperPlugin
|
||||
> = new Map([]);
|
||||
): Map<string, PluginDefinition> {
|
||||
const pluginsMap: Map<string, PluginDefinition> = new Map([]);
|
||||
plugins.clientPlugins.forEach((val, key) => {
|
||||
pluginsMap.set(key, val);
|
||||
});
|
||||
@@ -83,10 +86,7 @@ export function getEnabledOrExportPersistedStatePlugins(
|
||||
plugins: PluginsState,
|
||||
): Array<{id: string; label: string}> {
|
||||
const appName = deconstructClientId(client.id).app;
|
||||
const pluginsMap: Map<
|
||||
string,
|
||||
typeof FlipperDevicePlugin | typeof FlipperPlugin
|
||||
> = pluginsClassMap(plugins);
|
||||
const pluginsMap: Map<string, PluginDefinition> = pluginsClassMap(plugins);
|
||||
// Enabled Plugins with no exportPersistedState function defined
|
||||
const enabledPlugins = starredPlugin[appName]
|
||||
? starredPlugin[appName]
|
||||
@@ -141,10 +141,7 @@ export function getActivePersistentPlugins(
|
||||
plugins: PluginsState,
|
||||
selectedClient?: Client,
|
||||
): {id: string; label: string}[] {
|
||||
const pluginsMap: Map<
|
||||
string,
|
||||
typeof FlipperDevicePlugin | typeof FlipperPlugin
|
||||
> = pluginsClassMap(plugins);
|
||||
const pluginsMap: Map<string, PluginDefinition> = pluginsClassMap(plugins);
|
||||
return getPersistentPlugins(plugins)
|
||||
.map((pluginName) => pluginsMap.get(pluginName)!)
|
||||
.sort(sortPluginsByName)
|
||||
@@ -183,10 +180,7 @@ export function getActivePersistentPlugins(
|
||||
}
|
||||
|
||||
export function getPersistentPlugins(plugins: PluginsState): Array<string> {
|
||||
const pluginsMap: Map<
|
||||
string,
|
||||
typeof FlipperDevicePlugin | typeof FlipperPlugin
|
||||
> = pluginsClassMap(plugins);
|
||||
const pluginsMap: Map<string, PluginDefinition> = pluginsClassMap(plugins);
|
||||
|
||||
const arr: Array<PluginDetails> = plugins.disabledPlugins.concat(
|
||||
plugins.gatekeepedPlugins,
|
||||
@@ -210,32 +204,36 @@ export function getPersistentPlugins(plugins: PluginsState): Array<string> {
|
||||
return (
|
||||
plugin == 'DeviceLogs' ||
|
||||
(pluginClass &&
|
||||
// TODO: support Sandy plugin T68683449
|
||||
!(pluginClass instanceof SandyPluginDefinition) &&
|
||||
(pluginClass.defaultPersistedState != undefined ||
|
||||
pluginClass.exportPersistedState != undefined))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function getPluginTitle(pluginClass: typeof FlipperBasePlugin) {
|
||||
export function getPluginTitle(pluginClass: PluginDefinition) {
|
||||
return pluginClass.title || pluginClass.id;
|
||||
}
|
||||
|
||||
export function sortPluginsByName(
|
||||
a: typeof FlipperBasePlugin,
|
||||
b: typeof FlipperBasePlugin,
|
||||
a: PluginDefinition,
|
||||
b: PluginDefinition,
|
||||
): number {
|
||||
// make sure Device plugins are sorted before normal plugins
|
||||
if (
|
||||
a.prototype instanceof FlipperDevicePlugin &&
|
||||
!(b.prototype instanceof FlipperDevicePlugin)
|
||||
) {
|
||||
if (isDevicePluginDefinition(a) && !isDevicePluginDefinition(b)) {
|
||||
return -1;
|
||||
}
|
||||
if (
|
||||
b.prototype instanceof FlipperDevicePlugin &&
|
||||
!(a.prototype instanceof FlipperDevicePlugin)
|
||||
) {
|
||||
if (isDevicePluginDefinition(b) && !isDevicePluginDefinition(a)) {
|
||||
return 1;
|
||||
}
|
||||
return getPluginTitle(a) > getPluginTitle(b) ? 1 : -1;
|
||||
}
|
||||
|
||||
export function isDevicePluginDefinition(
|
||||
definition: PluginDefinition,
|
||||
): definition is DevicePluginDefinition {
|
||||
// TODO: support Sandy device plugins T68738317
|
||||
// @ts-ignore
|
||||
return definition.prototype instanceof FlipperDevicePlugin;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user