move plugin management from ui-core to server-core

Summary:
Follow up of D32665064, this diff moves all plugin management logic from flipper-ui to flipper-server. Things like downloading, installing, querying new plugins.

Loading plugins is handled separately in the next diff.

Reviewed By: nikoant

Differential Revision: D32666537

fbshipit-source-id: 9786b82987f00180bb26200e38735b334dc4d5c3
This commit is contained in:
Michel Weststrate
2021-12-08 04:25:28 -08:00
committed by Facebook GitHub Bot
parent f9b72ac69e
commit 64747dc417
25 changed files with 441 additions and 276 deletions

View File

@@ -10,9 +10,9 @@
import fs from 'fs-extra';
import path from 'path';
import {
DownloadablePluginDetails,
getPluginDetails,
InstalledPluginDetails,
PluginDetails,
isPluginJson,
} from 'flipper-common';
import {pluginCacheDir} from './pluginPaths';
@@ -26,10 +26,6 @@ export async function readPluginPackageJson(dir: string): Promise<any> {
}
}
export function isPluginJson(packageJson: any): boolean {
return packageJson?.keywords?.includes('flipper-plugin');
}
export async function isPluginDir(dir: string): Promise<boolean> {
const packageJsonPath = path.join(dir, 'package.json');
const json = (await fs.pathExists(packageJsonPath))
@@ -40,23 +36,6 @@ export async function isPluginDir(dir: string): Promise<boolean> {
return isPluginJson(json);
}
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}`);
}
}
export async function getInstalledPluginDetails(
dir: string,
packageJson?: any,
@@ -92,74 +71,3 @@ export async function getInstalledPluginDetails(
entry,
};
}
export function getDownloadablePluginDetails(
packageJson: any,
downloadUrl: string,
lastUpdated: Date,
): DownloadablePluginDetails {
const details = getPluginDetails(packageJson);
return {
...details,
isBundled: false,
isActivatable: false,
downloadUrl,
lastUpdated,
};
}
// 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,
};
}
// 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,
source: packageJson.flipperBundlerEntry,
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,
};
}
function getTitleFromName(name: string): string {
const prefix = 'flipper-plugin-';
if (name.startsWith(prefix)) {
return name.substr(prefix.length);
}
return name;
}

View File

@@ -7,29 +7,21 @@
* @format
*/
import {InstalledPluginDetails} from 'flipper-common';
import {
UpdatablePluginDetails,
UpdateResult,
getPluginDetails,
} from 'flipper-common';
import {getInstalledPlugins} from './pluginInstaller';
import semver from 'semver';
import {getNpmHostedPlugins, NpmPackageDescriptor} from './getNpmHostedPlugins';
import NpmApi from 'npm-api';
import {getInstalledPluginDetails, getPluginDetails} from './getPluginDetails';
import {getInstalledPluginDetails} from './getPluginDetails';
import {getPluginVersionInstallationDir} from './pluginPaths';
import pmap from 'p-map';
import {notNull} from './typeUtils';
const npmApi = new NpmApi();
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 async function getUpdatablePlugins(
query?: string,
): Promise<UpdatablePluginDetails[]> {

View File

@@ -109,7 +109,7 @@ export async function installPluginFromNpm(name: string) {
tmpDir,
getPluginDirNameFromPackageName(name),
);
await installPluginFromTempDir(pluginTempDir);
return await installPluginFromTempDir(pluginTempDir);
} finally {
await fs.remove(tmpDir);
}
@@ -137,9 +137,7 @@ export async function removePlugin(name: string): Promise<void> {
await fs.remove(getPluginInstallationDir(name));
}
export async function removePlugins(
names: IterableIterator<string>,
): Promise<void> {
export async function removePlugins(names: Array<string>): Promise<void> {
await pmap(names, (name) => removePlugin(name));
}