diff --git a/package.json b/package.json index b41f2bd94..ba0f90457 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/utils/pluginManager.tsx b/src/utils/pluginManager.tsx index fa96b6cbe..988d66db3 100644 --- a/src/utils/pluginManager.tsx +++ b/src/utils/pluginManager.tsx @@ -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)) { diff --git a/static/index.js b/static/index.js index 5853994f9..21db19cdb 100644 --- a/static/index.js +++ b/static/index.js @@ -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'), - path.join(__dirname, '..', 'src', 'plugins'), - path.join(__dirname, '..', 'src', 'fb', 'plugins'), - ) + ...(skipLoadingEmbeddedPlugins + ? [] + : [ + path.join(__dirname, '..', 'src', 'plugins'), + path.join(__dirname, '..', 'src', 'fb', 'plugins'), + ]), + ]) .map(expandTilde) .filter(fs.existsSync); diff --git a/types/decompress-unzip.d.tsx b/types/decompress-unzip.d.tsx new file mode 100644 index 000000000..43baefa23 --- /dev/null +++ b/types/decompress-unzip.d.tsx @@ -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; +}