Support installation of plugins packaged as vsix

Summary: This is experimental feature to prove that vsix format can be used to publish plugins. Turns out there are almost no differences of vsix in comparison with npm packages.

Reviewed By: jknoxville

Differential Revision: D19770476

fbshipit-source-id: b3c62e7f2a4e8000113b9f1651e8657eb3e0d6fa
This commit is contained in:
Anton Nikolaev
2020-02-06 11:12:28 -08:00
committed by Facebook Github Bot
parent 47b63f9543
commit e42e44c324
4 changed files with 46 additions and 10 deletions

View File

@@ -136,6 +136,7 @@
"dashify": "^2.0.0",
"decompress": "^4.2.0",
"decompress-targz": "^4.1.1",
"decompress-unzip": "^4.0.1",
"deep-equal": "^2.0.1",
"detect-port": "^1.1.1",
"electron-devtools-installer": "^2.2.0",
@@ -207,6 +208,7 @@
"rm-temp": "rimraf $TMPDIR/jest* $TMPDIR/react-native-packager*",
"reset": "yarn rm-dist && yarn rm-temp && yarn cache clean && yarn rm-modules",
"start": "cross-env NODE_ENV=development node scripts/start-dev-server.js",
"start:no-embedded-plugins": "cross-env NODE_ENV=development cross-env FLIPPER_NO_EMBEDDED_PLUGINS=true node scripts/start-dev-server.js",
"build": "yarn rm-dist && cross-env NODE_ENV=production node scripts/build-release.js $@",
"build-headless": "yarn rm-dist && mkdir dist && cross-env NODE_ENV=production node scripts/build-headless.js $@",
"fix": "eslint . --fix --ext .js,.tsx",

View File

@@ -17,6 +17,7 @@ import NpmApi, {Package} from 'npm-api';
import semver from 'semver';
import decompress from 'decompress';
import decompressTargz from 'decompress-targz';
import decompressUnzip from 'decompress-unzip';
import tmp from 'tmp';
const ALGOLIA_APPLICATION_ID = 'OFCNCOG2CU';
@@ -68,27 +69,42 @@ export async function installPluginFromFile(packagePath: string) {
const tmpDir = tmp.dirSync().name;
try {
const files = await decompress(packagePath, tmpDir, {
plugins: [decompressTargz()],
plugins: [decompressTargz(), decompressUnzip()],
});
if (!files.length) {
throw new Error('The package is not in tar.gz format or is empty');
}
// npm packages are tar.gz archives containing folder 'package' inside
const packageDir = path.join(tmpDir, 'package');
if (!(await fs.pathExists(packageDir))) {
const isNpmPackage = await fs.pathExists(packageDir);
// vsix packages are zip archives containing folder 'extension' inside
const extensionDir = path.join(tmpDir, 'extension');
const isVsix = await fs.pathExists(extensionDir);
if (!isNpmPackage && !isVsix) {
throw new Error(
'Package format is invalid: directory "package" not found',
'Package format is invalid: directory "package" or "extensions" not found in the archive root',
);
}
const packageJsonPath = path.join(packageDir, 'package.json');
const packageRoot = isNpmPackage ? packageDir : extensionDir;
// otherwise both npm and vsix are quite similar, so we can use the same logic for installing them
const packageJsonPath = path.join(packageRoot, 'package.json');
if (!(await fs.pathExists(packageJsonPath))) {
throw new Error(
'Package format is invalid: file "package/package.json" not found',
`Package format is invalid: file "${path.relative(
tmpDir,
packageJsonPath,
)}" not found`,
);
}
const packageJson = await fs.readJSON(packageJsonPath);
const name = packageJson.name as string;
await installPlugin(name, pluginManager =>
pluginManager.installFromPath(packageDir).then(() => {}),
pluginManager.installFromPath(packageRoot).then(() => {}),
);
} finally {
if (fs.existsSync(tmpDir)) {

View File

@@ -74,12 +74,18 @@ const argv = yargs
const {config, configPath, flipperDir} = setup(argv);
const skipLoadingEmbeddedPlugins = process.env.FLIPPER_NO_EMBEDDED_PLUGINS;
const pluginPaths = config.pluginPaths
.concat(
.concat([
path.join(configPath, '..', 'thirdparty'),
...(skipLoadingEmbeddedPlugins
? []
: [
path.join(__dirname, '..', 'src', 'plugins'),
path.join(__dirname, '..', 'src', 'fb', 'plugins'),
)
]),
])
.map(expandTilde)
.filter(fs.existsSync);

View File

@@ -0,0 +1,12 @@
/**
* 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
*/
declare module 'decompress-unzip' {
export default function(): any;
}