diff --git a/desktop/app/src/dispatcher/plugins.tsx b/desktop/app/src/dispatcher/plugins.tsx index 100f62d4c..793677009 100644 --- a/desktop/app/src/dispatcher/plugins.tsx +++ b/desktop/app/src/dispatcher/plugins.tsx @@ -20,6 +20,8 @@ import { addFailedPlugins, registerLoadedPlugins, registerBundledPlugins, + registerMarketplacePlugins, + MarketplacePluginDetails, } from '../reducers/plugins'; import GK from '../fb-stubs/GK'; import {FlipperBasePlugin} from '../plugin'; @@ -49,6 +51,7 @@ import * as crc32 from 'crc32'; // eslint-disable-next-line import/no-unresolved import getDefaultPluginsIndex from '../utils/getDefaultPluginsIndex'; import {isDevicePluginDefinition} from '../utils/pluginUtils'; +import {isPluginCompatible} from '../utils/isPluginCompatible'; let defaultPluginsIndex: any = null; @@ -74,6 +77,13 @@ export default async (store: Store, logger: Logger) => { defaultPluginsIndex = getDefaultPluginsIndex(); + const marketplacePlugins = store.getState().plugins.marketplacePlugins; + store.dispatch( + registerMarketplacePlugins( + selectCompatibleMarketplaceVersions(marketplacePlugins), + ), + ); + const uninstalledPlugins = store.getState().plugins.uninstalledPlugins; const bundledPlugins = getBundledPlugins(); @@ -320,3 +330,27 @@ const requirePluginInternal = ( } return plugin; }; + +export function selectCompatibleMarketplaceVersions( + availablePlugins: MarketplacePluginDetails[], +): MarketplacePluginDetails[] { + const plugins: MarketplacePluginDetails[] = []; + for (const plugin of availablePlugins) { + if (!isPluginCompatible(plugin)) { + const compatibleVersion = + plugin.availableVersions?.find(isPluginCompatible) ?? + plugin.availableVersions?.slice(-1).pop(); + if (compatibleVersion) { + plugins.push({ + ...compatibleVersion, + availableVersions: plugin?.availableVersions, + }); + } else { + plugins.push(plugin); + } + } else { + plugins.push(plugin); + } + } + return plugins; +} diff --git a/desktop/app/src/utils/isPluginCompatible.tsx b/desktop/app/src/utils/isPluginCompatible.tsx new file mode 100644 index 000000000..dfa632f95 --- /dev/null +++ b/desktop/app/src/utils/isPluginCompatible.tsx @@ -0,0 +1,25 @@ +/** + * 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 {PluginDetails} from 'plugin-lib'; +import semver from 'semver'; +import GK from '../fb-stubs/GK'; +import {getAppVersion} from './info'; + +export function isPluginCompatible(plugin: PluginDetails) { + const flipperVersion = getAppVersion(); + return ( + GK.get('flipper_disable_plugin_compatibility_checks') || + flipperVersion === '0.0.0' || + !plugin.engines?.flipper || + semver.lte(plugin.engines?.flipper, flipperVersion) + ); +} + +export default isPluginCompatible; diff --git a/desktop/plugin-lib/src/__tests__/getPluginDetails.node.ts b/desktop/plugin-lib/src/__tests__/getPluginDetails.node.ts index ec306e7d0..c2f5b29a2 100644 --- a/desktop/plugin-lib/src/__tests__/getPluginDetails.node.ts +++ b/desktop/plugin-lib/src/__tests__/getPluginDetails.node.ts @@ -40,6 +40,7 @@ test('getPluginDetailsV1', async () => { "category": undefined, "description": "Description of Test Plugin", "dir": "/Users/mock/.flipper/thirdparty/flipper-plugin-test", + "engines": undefined, "entry": "/Users/mock/.flipper/plugins/flipper-plugin-test@2.0.0.js", "flipperSDKVersion": undefined, "gatekeeper": "GK_flipper_plugin_test", @@ -81,6 +82,7 @@ test('getPluginDetailsV2', async () => { "category": undefined, "description": "Description of Test Plugin", "dir": "/Users/mock/.flipper/thirdparty/flipper-plugin-test", + "engines": undefined, "entry": "/Users/mock/.flipper/thirdparty/flipper-plugin-test/dist/bundle.js", "flipperSDKVersion": undefined, "gatekeeper": "GK_flipper_plugin_test", @@ -122,6 +124,7 @@ test('id used as title if the latter omited', async () => { "category": undefined, "description": "Description of Test Plugin", "dir": "/Users/mock/.flipper/thirdparty/flipper-plugin-test", + "engines": undefined, "entry": "/Users/mock/.flipper/thirdparty/flipper-plugin-test/dist/bundle.js", "flipperSDKVersion": undefined, "gatekeeper": "GK_flipper_plugin_test", @@ -162,6 +165,7 @@ test('name without "flipper-plugin-" prefix is used as title if the latter omite "category": undefined, "description": "Description of Test Plugin", "dir": "/Users/mock/.flipper/thirdparty/flipper-plugin-test", + "engines": undefined, "entry": "/Users/mock/.flipper/thirdparty/flipper-plugin-test/dist/bundle.js", "flipperSDKVersion": undefined, "gatekeeper": "GK_flipper_plugin_test", @@ -205,6 +209,7 @@ test('flipper-plugin-version is parsed', async () => { "category": undefined, "description": "Description of Test Plugin", "dir": "/Users/mock/.flipper/thirdparty/flipper-plugin-test", + "engines": undefined, "entry": "/Users/mock/.flipper/thirdparty/flipper-plugin-test/dist/bundle.js", "flipperSDKVersion": "^0.45", "gatekeeper": "GK_flipper_plugin_test", @@ -252,6 +257,7 @@ test('plugin type and supported devices parsed', async () => { "category": undefined, "description": "Description of Test Plugin", "dir": "/Users/mock/.flipper/thirdparty/flipper-plugin-test", + "engines": undefined, "entry": "/Users/mock/.flipper/thirdparty/flipper-plugin-test/dist/bundle.js", "flipperSDKVersion": undefined, "gatekeeper": "GK_flipper_plugin_test", diff --git a/desktop/plugin-lib/src/getPluginDetails.ts b/desktop/plugin-lib/src/getPluginDetails.ts index 043238b09..ee1a2c053 100644 --- a/desktop/plugin-lib/src/getPluginDetails.ts +++ b/desktop/plugin-lib/src/getPluginDetails.ts @@ -89,6 +89,7 @@ function getPluginDetailsV1(packageJson: any): PluginDetails { flipperSDKVersion: packageJson?.peerDependencies?.['flipper-plugin'], pluginType: packageJson?.pluginType, supportedDevices: packageJson?.supportedDevices, + engines: packageJson.engines, }; } @@ -111,6 +112,7 @@ function getPluginDetailsV2(packageJson: any): PluginDetails { flipperSDKVersion: packageJson?.peerDependencies?.['flipper-plugin'], pluginType: packageJson?.pluginType, supportedDevices: packageJson?.supportedDevices, + engines: packageJson.engines, }; }