Install plugin from package file
Summary: Adding a way to install plugins directly from package files. This is required for testing after packaging format changes. Stage 3: Implemented installation of plugins directly from package file. Reviewed By: jknoxville Differential Revision: D19765619 fbshipit-source-id: 57f36c87d3cf5d4e1c9a1f8f9f9f32b14a18bc8b
This commit is contained in:
committed by
Facebook Github Bot
parent
984cdbfb67
commit
b9e7f5d6d1
@@ -15,10 +15,15 @@ import {PluginManager as PM} from 'live-plugin-manager';
|
||||
import {default as algoliasearch, SearchIndex} from 'algoliasearch';
|
||||
import NpmApi, {Package} from 'npm-api';
|
||||
import semver from 'semver';
|
||||
import decompress from 'decompress';
|
||||
import decompressTargz from 'decompress-targz';
|
||||
import tmp from 'tmp';
|
||||
|
||||
const ALGOLIA_APPLICATION_ID = 'OFCNCOG2CU';
|
||||
const ALGOLIA_API_KEY = 'f54e21fa3a2a0160595bb058179bfb1e';
|
||||
|
||||
export const PLUGIN_DIR = path.join(homedir(), '.flipper', 'thirdparty');
|
||||
|
||||
// TODO(T57014856): The use should be constrained to just this module when the
|
||||
// refactor is done.
|
||||
export function providePluginManager(): PM {
|
||||
@@ -27,13 +32,77 @@ export function providePluginManager(): PM {
|
||||
});
|
||||
}
|
||||
|
||||
async function installPlugin(
|
||||
name: string,
|
||||
installFn: (pluginManager: PM) => Promise<void>,
|
||||
) {
|
||||
await fs.ensureDir(PLUGIN_DIR);
|
||||
// create empty watchman config (required by metro's file watcher)
|
||||
await fs.writeFile(path.join(PLUGIN_DIR, '.watchmanconfig'), '{}');
|
||||
const destinationDir = path.join(PLUGIN_DIR, name);
|
||||
// Clean up existing destination files.
|
||||
await fs.remove(destinationDir);
|
||||
|
||||
const pluginManager = providePluginManager();
|
||||
// install the plugin and all it's dependencies into node_modules
|
||||
pluginManager.options.pluginsPath = path.join(destinationDir, 'node_modules');
|
||||
await installFn(pluginManager);
|
||||
|
||||
// move the plugin itself out of the node_modules folder
|
||||
const pluginDir = path.join(PLUGIN_DIR, name, 'node_modules', name);
|
||||
const pluginFiles = await fs.readdir(pluginDir);
|
||||
await Promise.all(
|
||||
pluginFiles.map(f =>
|
||||
fs.move(path.join(pluginDir, f), path.join(pluginDir, '..', '..', f)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
export async function installPluginFromNpm(name: string) {
|
||||
await installPlugin(name, pluginManager =>
|
||||
pluginManager.install(name).then(() => {}),
|
||||
);
|
||||
}
|
||||
|
||||
export async function installPluginFromFile(packagePath: string) {
|
||||
const tmpDir = tmp.dirSync().name;
|
||||
try {
|
||||
const files = await decompress(packagePath, tmpDir, {
|
||||
plugins: [decompressTargz()],
|
||||
});
|
||||
if (!files.length) {
|
||||
throw new Error('The package is not in tar.gz format or is empty');
|
||||
}
|
||||
const packageDir = path.join(tmpDir, 'package');
|
||||
if (!(await fs.pathExists(packageDir))) {
|
||||
throw new Error(
|
||||
'Package format is invalid: directory "package" not found',
|
||||
);
|
||||
}
|
||||
const packageJsonPath = path.join(packageDir, 'package.json');
|
||||
if (!(await fs.pathExists(packageJsonPath))) {
|
||||
throw new Error(
|
||||
'Package format is invalid: file "package/package.json" not found',
|
||||
);
|
||||
}
|
||||
const packageJson = await fs.readJSON(packageJsonPath);
|
||||
const name = packageJson.name as string;
|
||||
await installPlugin(name, pluginManager =>
|
||||
pluginManager.installFromPath(packageDir).then(() => {}),
|
||||
);
|
||||
} finally {
|
||||
if (fs.existsSync(tmpDir)) {
|
||||
fs.removeSync(tmpDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(T57014856): This should be private, too.
|
||||
export function provideSearchIndex(): SearchIndex {
|
||||
const client = algoliasearch(ALGOLIA_APPLICATION_ID, ALGOLIA_API_KEY);
|
||||
return client.initIndex('npm-search');
|
||||
}
|
||||
|
||||
export const PLUGIN_DIR = path.join(homedir(), '.flipper', 'thirdparty');
|
||||
export async function readInstalledPlugins(): Promise<PluginMap> {
|
||||
const pluginDirExists = await fs.pathExists(PLUGIN_DIR);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user