Move plugin manager logic out of UI component

Summary: Moving some things around for the upcoming update support.

Reviewed By: jknoxville

Differential Revision: D18347572

fbshipit-source-id: b614fe3a87f8e7fdc0c11c0d3bfe4787c0914d17
This commit is contained in:
Pascal Hartig
2019-11-06 08:31:43 -08:00
committed by Facebook Github Bot
parent 4c0c212258
commit 05c007be16
3 changed files with 76 additions and 54 deletions

View File

@@ -30,7 +30,6 @@ import {List} from 'immutable';
import algoliasearch from 'algoliasearch'; import algoliasearch from 'algoliasearch';
import path from 'path'; import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import {PluginManager as PM} from 'live-plugin-manager';
import {reportPlatformFailures, reportUsage} from '../utils/metrics'; import {reportPlatformFailures, reportUsage} from '../utils/metrics';
import restartFlipper from '../utils/restartFlipper'; import restartFlipper from '../utils/restartFlipper';
import { import {
@@ -38,17 +37,17 @@ import {
PluginDefinition, PluginDefinition,
registerInstalledPlugins, registerInstalledPlugins,
} from '../reducers/pluginManager'; } from '../reducers/pluginManager';
import {PLUGIN_DIR, readInstalledPlugins} from '../dispatcher/pluginManager'; import {
import {State as AppState, Store} from '../reducers'; PLUGIN_DIR,
readInstalledPlugins,
providePluginManager,
provideSearchIndex,
} from '../utils/pluginManager';
import {State as AppState} from '../reducers';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import {Dispatch, Action} from 'redux'; import {Dispatch, Action} from 'redux';
const ALGOLIA_APPLICATION_ID = 'OFCNCOG2CU';
const ALGOLIA_API_KEY = 'f54e21fa3a2a0160595bb058179bfb1e';
const TAG = 'PluginInstaller'; const TAG = 'PluginInstaller';
const PluginManager = new PM({
ignoredDependencies: ['flipper', 'react', 'react-dom', '@types/*'],
});
const EllipsisText = styled(Text)({ const EllipsisText = styled(Text)({
overflow: 'hidden', overflow: 'hidden',
@@ -111,10 +110,7 @@ type OwnProps = {
type Props = OwnProps & PropsFromState & DispatchFromProps; type Props = OwnProps & PropsFromState & DispatchFromProps;
const defaultProps: OwnProps = { const defaultProps: OwnProps = {
searchIndexFactory: () => { searchIndexFactory: provideSearchIndex,
const client = algoliasearch(ALGOLIA_APPLICATION_ID, ALGOLIA_API_KEY);
return client.initIndex('npm-search');
},
autoHeight: false, autoHeight: false,
}; };
@@ -208,13 +204,14 @@ function InstallButton(props: {
// create empty watchman config (required by metro's file watcher) // create empty watchman config (required by metro's file watcher)
await fs.writeFile(path.join(PLUGIN_DIR, '.watchmanconfig'), '{}'); await fs.writeFile(path.join(PLUGIN_DIR, '.watchmanconfig'), '{}');
const pluginManager = providePluginManager();
// install the plugin and all it's dependencies into node_modules // install the plugin and all it's dependencies into node_modules
PluginManager.options.pluginsPath = path.join( pluginManager.options.pluginsPath = path.join(
PLUGIN_DIR, PLUGIN_DIR,
props.name, props.name,
'node_modules', 'node_modules',
); );
await PluginManager.install(props.name); await pluginManager.install(props.name);
// move the plugin itself out of the node_modules folder // move the plugin itself out of the node_modules folder
const pluginDir = path.join( const pluginDir = path.join(

View File

@@ -9,46 +9,8 @@
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import {Logger} from '../fb-interfaces/Logger'; import {Logger} from '../fb-interfaces/Logger';
import path from 'path'; import {registerInstalledPlugins} from '../reducers/pluginManager';
import fs from 'fs-extra'; import {readInstalledPlugins} from '../utils/pluginManager';
import {homedir} from 'os';
import {
registerInstalledPlugins,
PluginMap,
PluginDefinition,
} from '../reducers/pluginManager';
export const PLUGIN_DIR = path.join(homedir(), '.flipper', 'thirdparty');
export async function readInstalledPlugins(): Promise<PluginMap> {
const pluginDirExists = await fs.pathExists(PLUGIN_DIR);
if (!pluginDirExists) {
return new Map();
}
const dirs = await fs.readdir(PLUGIN_DIR);
const plugins = await Promise.all<[string, PluginDefinition]>(
dirs.map(
name =>
new Promise(async (resolve, reject) => {
if (!(await fs.lstat(path.join(PLUGIN_DIR, name))).isDirectory()) {
return resolve(undefined);
}
const packageJSON = await fs.readFile(
path.join(PLUGIN_DIR, name, 'package.json'),
);
try {
resolve([name, JSON.parse(packageJSON.toString())]);
} catch (e) {
reject(e);
}
}),
),
);
return new Map(plugins.filter(Boolean));
}
function refreshInstalledPlugins(store: Store) { function refreshInstalledPlugins(store: Store) {
readInstalledPlugins().then(plugins => readInstalledPlugins().then(plugins =>

View File

@@ -0,0 +1,63 @@
/**
* 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
*/
import path from 'path';
import fs from 'fs-extra';
import {homedir} from 'os';
import {PluginMap, PluginDefinition} from '../reducers/pluginManager';
import {PluginManager as PM} from 'live-plugin-manager';
import algoliasearch from 'algoliasearch';
const ALGOLIA_APPLICATION_ID = 'OFCNCOG2CU';
const ALGOLIA_API_KEY = 'f54e21fa3a2a0160595bb058179bfb1e';
// TODO(T57014856): The use should be constrained to just this module when the
// refactor is done.
export function providePluginManager(): PM {
return new PM({
ignoredDependencies: ['flipper', 'react', 'react-dom', '@types/*'],
});
}
// TODO(T57014856): This should be private, too.
export function provideSearchIndex(): algoliasearch.Index {
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);
if (!pluginDirExists) {
return new Map();
}
const dirs = await fs.readdir(PLUGIN_DIR);
const plugins = await Promise.all<[string, PluginDefinition]>(
dirs.map(
name =>
new Promise(async (resolve, reject) => {
if (!(await fs.lstat(path.join(PLUGIN_DIR, name))).isDirectory()) {
return resolve(undefined);
}
const packageJSON = await fs.readFile(
path.join(PLUGIN_DIR, name, 'package.json'),
);
try {
resolve([name, JSON.parse(packageJSON.toString())]);
} catch (e) {
reject(e);
}
}),
),
);
return new Map(plugins.filter(Boolean));
}