Move most of plugin tests to flipper-frontend-core
Summary: See D37139129 Reviewed By: passy Differential Revision: D37241829 fbshipit-source-id: d6bef24416e2b999d529fb6e275c64384c775c21
This commit is contained in:
committed by
Facebook GitHub Bot
parent
f4fc07ffd2
commit
3e72831699
188
desktop/flipper-frontend-core/src/__tests__/plugins.node.tsx
Normal file
188
desktop/flipper-frontend-core/src/__tests__/plugins.node.tsx
Normal file
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and 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 {
|
||||
getDynamicPlugins,
|
||||
checkDisabled,
|
||||
checkGK,
|
||||
createRequirePluginFunction,
|
||||
getLatestCompatibleVersionOfEachPlugin,
|
||||
} from '../plugins';
|
||||
import {BundledPluginDetails, InstalledPluginDetails} from 'flipper-common';
|
||||
import {_SandyPluginDefinition} from 'flipper-plugin';
|
||||
import {getRenderHostInstance} from '../RenderHost';
|
||||
|
||||
let loadDynamicPluginsMock: jest.Mock;
|
||||
|
||||
const sampleInstalledPluginDetails: InstalledPluginDetails = {
|
||||
name: 'other Name',
|
||||
version: '1.0.0',
|
||||
specVersion: 2,
|
||||
pluginType: 'client',
|
||||
main: 'dist/bundle.js',
|
||||
source: 'src/index.js',
|
||||
id: 'Sample',
|
||||
title: 'Sample',
|
||||
dir: '/Users/mock/.flipper/thirdparty/flipper-plugin-sample',
|
||||
entry: 'this/path/does not/exist',
|
||||
isBundled: false,
|
||||
isActivatable: true,
|
||||
};
|
||||
|
||||
const sampleBundledPluginDetails: BundledPluginDetails = {
|
||||
...sampleInstalledPluginDetails,
|
||||
id: 'SampleBundled',
|
||||
isBundled: true,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
loadDynamicPluginsMock = getRenderHostInstance().flipperServer.exec =
|
||||
jest.fn();
|
||||
loadDynamicPluginsMock.mockResolvedValue([]);
|
||||
});
|
||||
|
||||
test('getDynamicPlugins returns empty array on errors', async () => {
|
||||
loadDynamicPluginsMock.mockRejectedValue(new Error('ooops'));
|
||||
const res = await getDynamicPlugins();
|
||||
expect(res).toEqual([]);
|
||||
});
|
||||
|
||||
test('checkDisabled', () => {
|
||||
const disabledPlugin = 'pluginName';
|
||||
const hostConfig = getRenderHostInstance().serverConfig;
|
||||
const orig = hostConfig.processConfig;
|
||||
try {
|
||||
hostConfig.processConfig = {
|
||||
...orig,
|
||||
disabledPlugins: [disabledPlugin],
|
||||
};
|
||||
const disabled = checkDisabled([]);
|
||||
|
||||
expect(
|
||||
disabled({
|
||||
...sampleBundledPluginDetails,
|
||||
name: 'other Name',
|
||||
version: '1.0.0',
|
||||
}),
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
disabled({
|
||||
...sampleBundledPluginDetails,
|
||||
name: disabledPlugin,
|
||||
version: '1.0.0',
|
||||
}),
|
||||
).toBeFalsy();
|
||||
} finally {
|
||||
hostConfig.processConfig = orig;
|
||||
}
|
||||
});
|
||||
|
||||
test('checkGK for plugin without GK', () => {
|
||||
expect(
|
||||
checkGK([])({
|
||||
...sampleBundledPluginDetails,
|
||||
name: 'pluginID',
|
||||
version: '1.0.0',
|
||||
}),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
test('checkGK for passing plugin', () => {
|
||||
expect(
|
||||
checkGK([])({
|
||||
...sampleBundledPluginDetails,
|
||||
name: 'pluginID',
|
||||
gatekeeper: 'TEST_PASSING_GK',
|
||||
version: '1.0.0',
|
||||
}),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
test('checkGK for failing plugin', () => {
|
||||
const gatekeepedPlugins: InstalledPluginDetails[] = [];
|
||||
const name = 'pluginID';
|
||||
const plugins = checkGK(gatekeepedPlugins)({
|
||||
...sampleBundledPluginDetails,
|
||||
name,
|
||||
gatekeeper: 'TEST_FAILING_GK',
|
||||
version: '1.0.0',
|
||||
});
|
||||
|
||||
expect(plugins).toBeFalsy();
|
||||
expect(gatekeepedPlugins[0].name).toEqual(name);
|
||||
});
|
||||
|
||||
test('requirePlugin returns null for invalid requires', async () => {
|
||||
const requireFn = createRequirePluginFunction(() => {
|
||||
throw new Error();
|
||||
});
|
||||
const plugin = await requireFn([])({
|
||||
...sampleInstalledPluginDetails,
|
||||
name: 'pluginID',
|
||||
dir: '/Users/mock/.flipper/thirdparty/flipper-plugin-sample',
|
||||
entry: 'this/path/does not/exist',
|
||||
version: '1.0.0',
|
||||
});
|
||||
|
||||
expect(plugin).toBeNull();
|
||||
});
|
||||
|
||||
test('newest version of each plugin is used', () => {
|
||||
const bundledPlugins: BundledPluginDetails[] = [
|
||||
{
|
||||
...sampleBundledPluginDetails,
|
||||
id: 'TestPlugin1',
|
||||
name: 'flipper-plugin-test1',
|
||||
version: '0.1.0',
|
||||
},
|
||||
{
|
||||
...sampleBundledPluginDetails,
|
||||
id: 'TestPlugin2',
|
||||
name: 'flipper-plugin-test2',
|
||||
version: '0.1.0-alpha.201',
|
||||
},
|
||||
];
|
||||
const installedPlugins: InstalledPluginDetails[] = [
|
||||
{
|
||||
...sampleInstalledPluginDetails,
|
||||
id: 'TestPlugin2',
|
||||
name: 'flipper-plugin-test2',
|
||||
version: '0.1.0-alpha.21',
|
||||
dir: '/Users/mock/.flipper/thirdparty/flipper-plugin-test2',
|
||||
entry: './test/index.js',
|
||||
},
|
||||
{
|
||||
...sampleInstalledPluginDetails,
|
||||
id: 'TestPlugin1',
|
||||
name: 'flipper-plugin-test1',
|
||||
version: '0.10.0',
|
||||
dir: '/Users/mock/.flipper/thirdparty/flipper-plugin-test1',
|
||||
entry: './test/index.js',
|
||||
},
|
||||
];
|
||||
const filteredPlugins = getLatestCompatibleVersionOfEachPlugin(
|
||||
[...bundledPlugins, ...installedPlugins],
|
||||
'0.1.0',
|
||||
);
|
||||
expect(filteredPlugins).toHaveLength(2);
|
||||
expect(filteredPlugins).toContainEqual({
|
||||
...sampleInstalledPluginDetails,
|
||||
id: 'TestPlugin1',
|
||||
name: 'flipper-plugin-test1',
|
||||
version: '0.10.0',
|
||||
dir: '/Users/mock/.flipper/thirdparty/flipper-plugin-test1',
|
||||
entry: './test/index.js',
|
||||
});
|
||||
expect(filteredPlugins).toContainEqual({
|
||||
...sampleBundledPluginDetails,
|
||||
id: 'TestPlugin2',
|
||||
name: 'flipper-plugin-test2',
|
||||
version: '0.1.0-alpha.201',
|
||||
});
|
||||
});
|
||||
@@ -43,6 +43,10 @@ export abstract class AbstractPluginInitializer {
|
||||
return this._initialPlugins;
|
||||
}
|
||||
|
||||
get requirePlugin() {
|
||||
return createRequirePluginFunction(this.requirePluginImpl.bind(this));
|
||||
}
|
||||
|
||||
protected async _init(): Promise<_SandyPluginDefinition[]> {
|
||||
this.loadDefaultPluginIndex();
|
||||
this.loadMarketplacePlugins();
|
||||
@@ -100,9 +104,7 @@ export abstract class AbstractPluginInitializer {
|
||||
}
|
||||
|
||||
protected async loadPlugins(pluginsToLoad: ActivatablePluginDetails[]) {
|
||||
const loader = createRequirePluginFunction(
|
||||
this.requirePluginImpl.bind(this),
|
||||
)(this.failedPlugins);
|
||||
const loader = this.requirePlugin(this.failedPlugins);
|
||||
const initialPlugins: _SandyPluginDefinition[] = (
|
||||
await pMap(pluginsToLoad, loader)
|
||||
).filter(notNull);
|
||||
@@ -267,7 +269,7 @@ export const createRequirePluginFunction =
|
||||
};
|
||||
};
|
||||
|
||||
const wrapRequirePlugin =
|
||||
export const wrapRequirePlugin =
|
||||
(
|
||||
requirePluginImpl: (
|
||||
pluginDetails: ActivatablePluginDetails,
|
||||
|
||||
@@ -7,21 +7,17 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
jest.mock('../../../../app/src/defaultPlugins');
|
||||
import dispatcher, {
|
||||
getDynamicPlugins,
|
||||
checkDisabled,
|
||||
checkGK,
|
||||
createRequirePluginFunction,
|
||||
getLatestCompatibleVersionOfEachPlugin,
|
||||
} from '../plugins';
|
||||
import {BundledPluginDetails, InstalledPluginDetails} from 'flipper-common';
|
||||
import dispatcher, {requirePluginInternal} from '../plugins';
|
||||
import {InstalledPluginDetails} from 'flipper-common';
|
||||
import {createRootReducer, State} from '../../reducers/index';
|
||||
import {getLogger} from 'flipper-common';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import TestPlugin from './TestPlugin';
|
||||
import {_SandyPluginDefinition} from 'flipper-plugin';
|
||||
import {getRenderHostInstance} from 'flipper-frontend-core';
|
||||
import {
|
||||
getRenderHostInstance,
|
||||
createRequirePluginFunction,
|
||||
} from 'flipper-frontend-core';
|
||||
import path from 'path';
|
||||
|
||||
let loadDynamicPluginsMock: jest.Mock;
|
||||
@@ -46,11 +42,8 @@ const sampleInstalledPluginDetails: InstalledPluginDetails = {
|
||||
isActivatable: true,
|
||||
};
|
||||
|
||||
const sampleBundledPluginDetails: BundledPluginDetails = {
|
||||
...sampleInstalledPluginDetails,
|
||||
id: 'SampleBundled',
|
||||
isBundled: true,
|
||||
};
|
||||
// bind to empty default plugin index so we try fetching from flipper-server every time
|
||||
const requirePlugin = requirePluginInternal.bind({}, {});
|
||||
|
||||
beforeEach(() => {
|
||||
loadDynamicPluginsMock = getRenderHostInstance().flipperServer.exec =
|
||||
@@ -64,79 +57,8 @@ test('dispatcher dispatches REGISTER_PLUGINS', async () => {
|
||||
expect(actions.map((a) => a.type)).toContain('REGISTER_PLUGINS');
|
||||
});
|
||||
|
||||
test('getDynamicPlugins returns empty array on errors', async () => {
|
||||
loadDynamicPluginsMock.mockRejectedValue(new Error('ooops'));
|
||||
const res = await getDynamicPlugins();
|
||||
expect(res).toEqual([]);
|
||||
});
|
||||
|
||||
test('checkDisabled', () => {
|
||||
const disabledPlugin = 'pluginName';
|
||||
const hostConfig = getRenderHostInstance().serverConfig;
|
||||
const orig = hostConfig.processConfig;
|
||||
try {
|
||||
hostConfig.processConfig = {
|
||||
...orig,
|
||||
disabledPlugins: [disabledPlugin],
|
||||
};
|
||||
const disabled = checkDisabled([]);
|
||||
|
||||
expect(
|
||||
disabled({
|
||||
...sampleBundledPluginDetails,
|
||||
name: 'other Name',
|
||||
version: '1.0.0',
|
||||
}),
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
disabled({
|
||||
...sampleBundledPluginDetails,
|
||||
name: disabledPlugin,
|
||||
version: '1.0.0',
|
||||
}),
|
||||
).toBeFalsy();
|
||||
} finally {
|
||||
hostConfig.processConfig = orig;
|
||||
}
|
||||
});
|
||||
|
||||
test('checkGK for plugin without GK', () => {
|
||||
expect(
|
||||
checkGK([])({
|
||||
...sampleBundledPluginDetails,
|
||||
name: 'pluginID',
|
||||
version: '1.0.0',
|
||||
}),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
test('checkGK for passing plugin', () => {
|
||||
expect(
|
||||
checkGK([])({
|
||||
...sampleBundledPluginDetails,
|
||||
name: 'pluginID',
|
||||
gatekeeper: 'TEST_PASSING_GK',
|
||||
version: '1.0.0',
|
||||
}),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
test('checkGK for failing plugin', () => {
|
||||
const gatekeepedPlugins: InstalledPluginDetails[] = [];
|
||||
const name = 'pluginID';
|
||||
const plugins = checkGK(gatekeepedPlugins)({
|
||||
...sampleBundledPluginDetails,
|
||||
name,
|
||||
gatekeeper: 'TEST_FAILING_GK',
|
||||
version: '1.0.0',
|
||||
});
|
||||
|
||||
expect(plugins).toBeFalsy();
|
||||
expect(gatekeepedPlugins[0].name).toEqual(name);
|
||||
});
|
||||
|
||||
test('requirePlugin returns null for invalid requires', async () => {
|
||||
const requireFn = createRequirePluginFunction([]);
|
||||
test('requirePluginInternal returns null for invalid requires', async () => {
|
||||
const requireFn = createRequirePluginFunction(requirePlugin)([]);
|
||||
const plugin = await requireFn({
|
||||
...sampleInstalledPluginDetails,
|
||||
name: 'pluginID',
|
||||
@@ -148,9 +70,9 @@ test('requirePlugin returns null for invalid requires', async () => {
|
||||
expect(plugin).toBeNull();
|
||||
});
|
||||
|
||||
test('requirePlugin loads plugin', async () => {
|
||||
test('requirePluginInternal loads plugin', async () => {
|
||||
const name = 'pluginID';
|
||||
const requireFn = createRequirePluginFunction([]);
|
||||
const requireFn = createRequirePluginFunction(requirePlugin)([]);
|
||||
const plugin = await requireFn({
|
||||
...sampleInstalledPluginDetails,
|
||||
name,
|
||||
@@ -170,63 +92,9 @@ test('requirePlugin loads plugin', async () => {
|
||||
expect(plugin!.id).toBe(TestPlugin.id);
|
||||
});
|
||||
|
||||
test('newest version of each plugin is used', () => {
|
||||
const bundledPlugins: BundledPluginDetails[] = [
|
||||
{
|
||||
...sampleBundledPluginDetails,
|
||||
id: 'TestPlugin1',
|
||||
name: 'flipper-plugin-test1',
|
||||
version: '0.1.0',
|
||||
},
|
||||
{
|
||||
...sampleBundledPluginDetails,
|
||||
id: 'TestPlugin2',
|
||||
name: 'flipper-plugin-test2',
|
||||
version: '0.1.0-alpha.201',
|
||||
},
|
||||
];
|
||||
const installedPlugins: InstalledPluginDetails[] = [
|
||||
{
|
||||
...sampleInstalledPluginDetails,
|
||||
id: 'TestPlugin2',
|
||||
name: 'flipper-plugin-test2',
|
||||
version: '0.1.0-alpha.21',
|
||||
dir: '/Users/mock/.flipper/thirdparty/flipper-plugin-test2',
|
||||
entry: './test/index.js',
|
||||
},
|
||||
{
|
||||
...sampleInstalledPluginDetails,
|
||||
id: 'TestPlugin1',
|
||||
name: 'flipper-plugin-test1',
|
||||
version: '0.10.0',
|
||||
dir: '/Users/mock/.flipper/thirdparty/flipper-plugin-test1',
|
||||
entry: './test/index.js',
|
||||
},
|
||||
];
|
||||
const filteredPlugins = getLatestCompatibleVersionOfEachPlugin([
|
||||
...bundledPlugins,
|
||||
...installedPlugins,
|
||||
]);
|
||||
expect(filteredPlugins).toHaveLength(2);
|
||||
expect(filteredPlugins).toContainEqual({
|
||||
...sampleInstalledPluginDetails,
|
||||
id: 'TestPlugin1',
|
||||
name: 'flipper-plugin-test1',
|
||||
version: '0.10.0',
|
||||
dir: '/Users/mock/.flipper/thirdparty/flipper-plugin-test1',
|
||||
entry: './test/index.js',
|
||||
});
|
||||
expect(filteredPlugins).toContainEqual({
|
||||
...sampleBundledPluginDetails,
|
||||
id: 'TestPlugin2',
|
||||
name: 'flipper-plugin-test2',
|
||||
version: '0.1.0-alpha.201',
|
||||
});
|
||||
});
|
||||
|
||||
test('requirePlugin loads valid Sandy plugin', async () => {
|
||||
test('requirePluginInternal loads valid Sandy plugin', async () => {
|
||||
const name = 'pluginID';
|
||||
const requireFn = createRequirePluginFunction([]);
|
||||
const requireFn = createRequirePluginFunction(requirePlugin)([]);
|
||||
const plugin = (await requireFn({
|
||||
...sampleInstalledPluginDetails,
|
||||
name,
|
||||
@@ -261,10 +129,10 @@ test('requirePlugin loads valid Sandy plugin', async () => {
|
||||
expect(typeof plugin.asPluginModule().plugin).toBe('function');
|
||||
});
|
||||
|
||||
test('requirePlugin errors on invalid Sandy plugin', async () => {
|
||||
test('requirePluginInternal errors on invalid Sandy plugin', async () => {
|
||||
const name = 'pluginID';
|
||||
const failedPlugins: any[] = [];
|
||||
const requireFn = createRequirePluginFunction(failedPlugins);
|
||||
const requireFn = createRequirePluginFunction(requirePlugin)(failedPlugins);
|
||||
await requireFn({
|
||||
...sampleInstalledPluginDetails,
|
||||
name,
|
||||
@@ -279,9 +147,9 @@ test('requirePlugin errors on invalid Sandy plugin', async () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('requirePlugin loads valid Sandy Device plugin', async () => {
|
||||
test('requirePluginInternal loads valid Sandy Device plugin', async () => {
|
||||
const name = 'pluginID';
|
||||
const requireFn = createRequirePluginFunction([]);
|
||||
const requireFn = createRequirePluginFunction(requirePlugin)([]);
|
||||
const plugin = (await requireFn({
|
||||
...sampleInstalledPluginDetails,
|
||||
pluginType: 'device',
|
||||
|
||||
@@ -8,11 +8,7 @@
|
||||
*/
|
||||
|
||||
import type {Store} from '../reducers/index';
|
||||
import {
|
||||
InstalledPluginDetails,
|
||||
Logger,
|
||||
tryCatchReportPluginFailuresAsync,
|
||||
} from 'flipper-common';
|
||||
import {Logger} from 'flipper-common';
|
||||
import {PluginDefinition} from '../plugin';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
@@ -30,23 +26,21 @@ import {
|
||||
pluginsInitialized,
|
||||
} from '../reducers/plugins';
|
||||
import {FlipperBasePlugin} from '../plugin';
|
||||
import {ActivatablePluginDetails, ConcretePluginDetails} from 'flipper-common';
|
||||
import {reportUsage} from 'flipper-common';
|
||||
import {ActivatablePluginDetails} from 'flipper-common';
|
||||
import * as FlipperPluginSDK from 'flipper-plugin';
|
||||
import {_SandyPluginDefinition} from 'flipper-plugin';
|
||||
import * as Immer from 'immer';
|
||||
import * as antd from 'antd';
|
||||
import * as emotion_styled from '@emotion/styled';
|
||||
import * as antdesign_icons from '@ant-design/icons';
|
||||
|
||||
import {isDevicePluginDefinition} from '../utils/pluginUtils';
|
||||
import isPluginCompatible from '../utils/isPluginCompatible';
|
||||
import isPluginVersionMoreRecent from '../utils/isPluginVersionMoreRecent';
|
||||
import {createSandyPluginWrapper} from '../utils/createSandyPluginWrapper';
|
||||
import {
|
||||
AbstractPluginInitializer,
|
||||
getRenderHostInstance,
|
||||
setGlobalObject,
|
||||
isSandyPlugin,
|
||||
wrapRequirePlugin,
|
||||
} from 'flipper-frontend-core';
|
||||
import * as deprecatedExports from '../deprecated-exports';
|
||||
import {getAppVersion} from '../utils/info';
|
||||
@@ -124,142 +118,10 @@ export default async (store: Store, _logger: Logger) => {
|
||||
await uiPluginInitializer.init();
|
||||
};
|
||||
|
||||
export function getLatestCompatibleVersionOfEachPlugin<
|
||||
T extends ConcretePluginDetails,
|
||||
>(plugins: T[]): T[] {
|
||||
const latestCompatibleVersions: Map<string, T> = new Map();
|
||||
for (const plugin of plugins) {
|
||||
if (isPluginCompatible(plugin)) {
|
||||
const loadedVersion = latestCompatibleVersions.get(plugin.id);
|
||||
if (!loadedVersion || isPluginVersionMoreRecent(plugin, loadedVersion)) {
|
||||
latestCompatibleVersions.set(plugin.id, plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Array.from(latestCompatibleVersions.values());
|
||||
}
|
||||
export const requirePlugin = (pluginDetails: ActivatablePluginDetails) =>
|
||||
wrapRequirePlugin(uiPluginInitializer!.requirePluginImpl)(pluginDetails);
|
||||
|
||||
export async function getDynamicPlugins(): Promise<InstalledPluginDetails[]> {
|
||||
try {
|
||||
return await getRenderHostInstance().flipperServer!.exec(
|
||||
'plugins-load-dynamic-plugins',
|
||||
);
|
||||
} catch (e) {
|
||||
console.error('Failed to load dynamic plugins', e);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export const checkGK =
|
||||
(gatekeepedPlugins: Array<ActivatablePluginDetails>) =>
|
||||
(plugin: ActivatablePluginDetails): boolean => {
|
||||
try {
|
||||
if (!plugin.gatekeeper) {
|
||||
return true;
|
||||
}
|
||||
const result = getRenderHostInstance().GK(plugin.gatekeeper);
|
||||
if (!result) {
|
||||
gatekeepedPlugins.push(plugin);
|
||||
}
|
||||
return result;
|
||||
} catch (err) {
|
||||
console.error(`Failed to check GK for plugin ${plugin.id}`, err);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const checkDisabled = (
|
||||
disabledPlugins: Array<ActivatablePluginDetails>,
|
||||
) => {
|
||||
const config = getRenderHostInstance().serverConfig;
|
||||
let enabledList: Set<string> | null = null;
|
||||
let disabledList: Set<string> = new Set();
|
||||
try {
|
||||
if (config.env.FLIPPER_ENABLED_PLUGINS) {
|
||||
enabledList = new Set<string>(
|
||||
config.env.FLIPPER_ENABLED_PLUGINS.split(','),
|
||||
);
|
||||
}
|
||||
disabledList = new Set(config.processConfig.disabledPlugins);
|
||||
} catch (e) {
|
||||
console.error('Failed to compute enabled/disabled plugins', e);
|
||||
}
|
||||
return (plugin: ActivatablePluginDetails): boolean => {
|
||||
try {
|
||||
if (disabledList.has(plugin.name)) {
|
||||
disabledPlugins.push(plugin);
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
enabledList &&
|
||||
!(
|
||||
enabledList.has(plugin.name) ||
|
||||
enabledList.has(plugin.id) ||
|
||||
enabledList.has(plugin.name.replace('flipper-plugin-', ''))
|
||||
)
|
||||
) {
|
||||
disabledPlugins.push(plugin);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error(
|
||||
`Failed to check whether plugin ${plugin.id} is disabled`,
|
||||
e,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export const createRequirePluginFunction = (
|
||||
failedPlugins: Array<[ActivatablePluginDetails, string]>,
|
||||
) => {
|
||||
return async (
|
||||
pluginDetails: ActivatablePluginDetails,
|
||||
): Promise<PluginDefinition | null> => {
|
||||
try {
|
||||
const pluginDefinition = await requirePlugin(pluginDetails);
|
||||
if (
|
||||
pluginDefinition &&
|
||||
isDevicePluginDefinition(pluginDefinition) &&
|
||||
pluginDefinition.details.pluginType !== 'device'
|
||||
) {
|
||||
console.warn(
|
||||
`Package ${pluginDefinition.details.name} contains the device plugin "${pluginDefinition.title}" defined in a wrong format. Specify "pluginType" and "supportedDevices" properties and remove exported function "supportsDevice". See details at https://fbflipper.com/docs/extending/desktop-plugin-structure#creating-a-device-plugin.`,
|
||||
);
|
||||
}
|
||||
return pluginDefinition;
|
||||
} catch (e) {
|
||||
failedPlugins.push([pluginDetails, e.message]);
|
||||
console.error(`Plugin ${pluginDetails.id} failed to load`, e);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export const requirePlugin = (
|
||||
pluginDetails: ActivatablePluginDetails,
|
||||
): Promise<PluginDefinition> => {
|
||||
reportUsage(
|
||||
'plugin:load',
|
||||
{
|
||||
version: pluginDetails.version,
|
||||
},
|
||||
pluginDetails.id,
|
||||
);
|
||||
return tryCatchReportPluginFailuresAsync(
|
||||
() => uiPluginInitializer.requirePluginImpl(pluginDetails),
|
||||
'plugin:load',
|
||||
pluginDetails.id,
|
||||
);
|
||||
};
|
||||
|
||||
const isSandyPlugin = (pluginDetails: ActivatablePluginDetails) => {
|
||||
return !!pluginDetails.flipperSDKVersion;
|
||||
};
|
||||
|
||||
const requirePluginInternal = async (
|
||||
export const requirePluginInternal = async (
|
||||
defaultPluginsIndex: any,
|
||||
pluginDetails: ActivatablePluginDetails,
|
||||
): Promise<PluginDefinition> => {
|
||||
|
||||
@@ -10,7 +10,10 @@
|
||||
import type {PluginDefinition} from '../plugin';
|
||||
import type {State, Store} from '../reducers';
|
||||
import type {State as PluginsState} from '../reducers/plugins';
|
||||
import type {BaseDevice} from 'flipper-frontend-core';
|
||||
import {
|
||||
BaseDevice,
|
||||
getLatestCompatibleVersionOfEachPlugin,
|
||||
} from 'flipper-frontend-core';
|
||||
import type Client from '../Client';
|
||||
import type {
|
||||
ActivatablePluginDetails,
|
||||
@@ -18,8 +21,8 @@ import type {
|
||||
DownloadablePluginDetails,
|
||||
PluginDetails,
|
||||
} from 'flipper-common';
|
||||
import {getLatestCompatibleVersionOfEachPlugin} from '../dispatcher/plugins';
|
||||
import {getPluginKey} from './pluginKey';
|
||||
import {getAppVersion} from './info';
|
||||
|
||||
export type PluginLists = {
|
||||
devicePlugins: PluginDefinition[];
|
||||
@@ -181,10 +184,10 @@ export function computePluginLists(
|
||||
} {
|
||||
const enabledDevicePluginsState = connections.enabledDevicePlugins;
|
||||
const enabledPluginsState = connections.enabledPlugins;
|
||||
const uninstalledMarketplacePlugins = getLatestCompatibleVersionOfEachPlugin([
|
||||
...plugins.bundledPlugins.values(),
|
||||
...plugins.marketplacePlugins,
|
||||
]).filter((p) => !plugins.loadedPlugins.has(p.id));
|
||||
const uninstalledMarketplacePlugins = getLatestCompatibleVersionOfEachPlugin(
|
||||
[...plugins.bundledPlugins.values(), ...plugins.marketplacePlugins],
|
||||
getAppVersion(),
|
||||
).filter((p) => !plugins.loadedPlugins.has(p.id));
|
||||
const devicePlugins: PluginDefinition[] = [...plugins.devicePlugins.values()]
|
||||
.filter((p) => device?.supportsPlugin(p))
|
||||
.filter((p) => enabledDevicePluginsState.has(p.id));
|
||||
|
||||
Reference in New Issue
Block a user