/** * 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 {DeviceType, OS} from './server-types'; export interface PluginDetails { name: string; specVersion: number; version: string; source: string; main: string; serverAddOnSource?: string; serverAddOn?: string; id: string; gatekeeper?: string; title: string; icon?: string; description?: string; category?: string; engines?: { [name: string]: string; }; bugs?: { email?: string; url?: string; }; flipperSDKVersion?: string; pluginType?: PluginType; headless?: boolean; supportedDevices?: SupportedDevice[]; supportedApps?: SupportedApp[]; publishedDocs?: { overview?: boolean; setup?: boolean; }; /** * Provided by NPM. Allows developers to deprecated packages. Its value is the deprecation reason. * Alternatively, might be a part of the plugin's package JSON. In this case, the plugin is excluded from bundling. */ deprecated?: string; } export interface SupportedDevice { readonly os?: OS; readonly type?: DeviceType; readonly archived?: boolean; readonly specs?: DeviceSpec[]; } export interface SupportedApp { readonly appID?: string; readonly os?: OS; readonly type?: DeviceType; } export type PluginType = 'client' | 'device'; export type DeviceSpec = 'KaiOS'; export interface ConcretePluginDetails extends PluginDetails { // Determines whether the plugin is physically available for activation in Flipper. isActivatable: boolean; } // Describes plugin installed on the disk. export interface InstalledPluginDetails extends ConcretePluginDetails { isActivatable: true; dir: string; entry: string; serverAddOnEntry?: string; } // Describes plugin physically available for activation in Flipper. export type ActivatablePluginDetails = InstalledPluginDetails; // Describes plugin available for downloading. Until downloaded to the disk it is not available for activation in Flipper. export interface DownloadablePluginDetails extends ConcretePluginDetails { isActivatable: false; buildId: string; downloadUrl: string; lastUpdated: Date; // Indicates whether plugin should be enabled by default for new users isEnabledByDefault: boolean; } export interface MarketplacePluginDetails extends DownloadablePluginDetails { availableVersions?: DownloadablePluginDetails[]; } export type UpdateResult = | {kind: 'not-installed'; version: string} | {kind: 'up-to-date'} | {kind: 'error'; error: Error} | {kind: 'update-available'; version: string}; export type UpdatablePlugin = { updateStatus: UpdateResult; }; export type UpdatablePluginDetails = InstalledPluginDetails & UpdatablePlugin; export function getPluginDetails(packageJson: any): PluginDetails { const specVersion = packageJson.$schema && packageJson.$schema === 'https://fbflipper.com/schemas/plugin-package/v2.json' ? 2 : 1; switch (specVersion) { case 1: return getPluginDetailsV1(packageJson); case 2: return getPluginDetailsV2(packageJson); default: throw new Error(`Unknown plugin format version: ${specVersion}`); } } // Plugins packaged using V1 are distributed as sources and compiled in run-time. function getPluginDetailsV1(packageJson: any): PluginDetails { return { specVersion: 1, name: packageJson.name, version: packageJson.version, main: 'dist/bundle.js', source: packageJson.main, id: packageJson.name, gatekeeper: packageJson.gatekeeper, icon: packageJson.icon, title: packageJson.title || packageJson.name, description: packageJson.description, category: packageJson.category, bugs: packageJson.bugs, flipperSDKVersion: packageJson?.peerDependencies?.['flipper-plugin'], pluginType: packageJson?.pluginType, supportedDevices: packageJson?.supportedDevices, supportedApps: packageJson?.supportedApps, engines: packageJson.engines, deprecated: packageJson.deprecated, }; } // Plugins packaged using V2 are pre-bundled, so compilation in run-time is not required for them. function getPluginDetailsV2(packageJson: any): PluginDetails { return { specVersion: 2, name: packageJson.name, version: packageJson.version, main: packageJson.main, serverAddOn: packageJson.serverAddOn, source: packageJson.flipperBundlerEntry, serverAddOnSource: packageJson.flipperBundlerEntryServerAddOn, id: packageJson.id || packageJson.name, gatekeeper: packageJson.gatekeeper, icon: packageJson.icon, title: packageJson.title || packageJson.id || getTitleFromName(packageJson.name), description: packageJson.description, category: packageJson.category, bugs: packageJson.bugs, flipperSDKVersion: packageJson?.peerDependencies?.['flipper-plugin'], pluginType: packageJson?.pluginType, supportedDevices: packageJson?.supportedDevices, supportedApps: packageJson?.supportedApps, engines: packageJson.engines, publishedDocs: packageJson.publishedDocs, headless: packageJson.headless, deprecated: packageJson.deprecated, }; } function getTitleFromName(name: string): string { const prefix = 'flipper-plugin-'; if (name.startsWith(prefix)) { return name.substr(prefix.length); } return name; } export function isPluginJson(packageJson: any): boolean { return packageJson?.keywords?.includes('flipper-plugin'); }