refactor(plugins): switched from require to await import() when loading plugins (#2558)
This commit is contained in:
@@ -68,7 +68,7 @@ Your configuration for the \`${type}\` plugin is \`${stringify(pluginConf)}\`.`,
|
||||
message: 'The `plugins` configuration is invalid.',
|
||||
details: `The [plugins](${linkify(
|
||||
'docs/usage/configuration.md#plugins'
|
||||
)}) option must be an array of plugin definions. A plugin definition is an npm module name, optionally wrapped in an array with an object.
|
||||
)}) option must be an array of plugin definitions. A plugin definition is an npm module name, optionally wrapped in an array with an object.
|
||||
|
||||
The invalid configuration is \`${stringify(plugin)}\`.`,
|
||||
}),
|
||||
|
||||
+28
-18
@@ -6,15 +6,16 @@ const {validatePlugin, validateStep, loadPlugin, parseConfig} = require('./utils
|
||||
const pipeline = require('./pipeline');
|
||||
const normalize = require('./normalize');
|
||||
|
||||
module.exports = (context, pluginsPath) => {
|
||||
module.exports = async (context, pluginsPath) => {
|
||||
let {options, logger} = context;
|
||||
const errors = [];
|
||||
|
||||
const plugins = options.plugins
|
||||
? castArray(options.plugins).reduce((plugins, plugin) => {
|
||||
? await castArray(options.plugins).reduce(async (eventualPluginsList, plugin) => {
|
||||
const pluginsList = await eventualPluginsList;
|
||||
if (validatePlugin(plugin)) {
|
||||
const [name, config] = parseConfig(plugin);
|
||||
plugin = isString(name) ? loadPlugin(context, name, pluginsPath) : name;
|
||||
plugin = isString(name) ? await loadPlugin(context, name, pluginsPath) : name;
|
||||
|
||||
if (isPlainObject(plugin)) {
|
||||
Object.entries(plugin).forEach(([type, func]) => {
|
||||
@@ -24,7 +25,7 @@ module.exports = (context, pluginsPath) => {
|
||||
writable: false,
|
||||
enumerable: true,
|
||||
});
|
||||
plugins[type] = [...(plugins[type] || []), [func, config]];
|
||||
pluginsList[type] = [...(pluginsList[type] || []), [func, config]];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -34,7 +35,7 @@ module.exports = (context, pluginsPath) => {
|
||||
errors.push(getError('EPLUGINSCONF', {plugin}));
|
||||
}
|
||||
|
||||
return plugins;
|
||||
return pluginsList;
|
||||
}, {})
|
||||
: [];
|
||||
|
||||
@@ -44,9 +45,13 @@ module.exports = (context, pluginsPath) => {
|
||||
|
||||
options = {...plugins, ...options};
|
||||
|
||||
const pluginsConf = Object.entries(PLUGINS_DEFINITIONS).reduce(
|
||||
(pluginsConf, [type, {required, default: def, pipelineConfig, postprocess = identity, preprocess = identity}]) => {
|
||||
const pluginsConfig = await Object.entries(PLUGINS_DEFINITIONS).reduce(
|
||||
async (
|
||||
eventualPluginsConfigAccumulator,
|
||||
[type, {required, default: def, pipelineConfig, postprocess = identity, preprocess = identity}]
|
||||
) => {
|
||||
let pluginOptions;
|
||||
const pluginsConfigAccumulator = await eventualPluginsConfigAccumulator;
|
||||
|
||||
if (isNil(options[type]) && def) {
|
||||
pluginOptions = def;
|
||||
@@ -60,28 +65,33 @@ module.exports = (context, pluginsPath) => {
|
||||
|
||||
if (!validateStep({required}, options[type])) {
|
||||
errors.push(getError('EPLUGINCONF', {type, required, pluginConf: options[type]}));
|
||||
return pluginsConf;
|
||||
return pluginsConfigAccumulator;
|
||||
}
|
||||
|
||||
pluginOptions = options[type];
|
||||
}
|
||||
|
||||
const steps = castArray(pluginOptions).map((pluginOpt) =>
|
||||
normalize(
|
||||
{...context, options: omit(options, Object.keys(PLUGINS_DEFINITIONS), 'plugins')},
|
||||
type,
|
||||
pluginOpt,
|
||||
pluginsPath
|
||||
const steps = await Promise.all(
|
||||
castArray(pluginOptions).map(async (pluginOpt) =>
|
||||
normalize(
|
||||
{...context, options: omit(options, Object.keys(PLUGINS_DEFINITIONS), 'plugins')},
|
||||
type,
|
||||
pluginOpt,
|
||||
pluginsPath
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
pluginsConf[type] = async (input) =>
|
||||
pluginsConfigAccumulator[type] = async (input) =>
|
||||
postprocess(
|
||||
await pipeline(steps, pipelineConfig && pipelineConfig(pluginsConf, logger))(await preprocess(input)),
|
||||
await pipeline(
|
||||
steps,
|
||||
pipelineConfig && pipelineConfig(pluginsConfigAccumulator, logger)
|
||||
)(await preprocess(input)),
|
||||
input
|
||||
);
|
||||
|
||||
return pluginsConf;
|
||||
return pluginsConfigAccumulator;
|
||||
},
|
||||
plugins
|
||||
);
|
||||
@@ -89,5 +99,5 @@ module.exports = (context, pluginsPath) => {
|
||||
throw new AggregateError(errors);
|
||||
}
|
||||
|
||||
return pluginsConf;
|
||||
return pluginsConfig;
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@ const {extractErrors} = require('../utils');
|
||||
const PLUGINS_DEFINITIONS = require('../definitions/plugins');
|
||||
const {loadPlugin, parseConfig} = require('./utils');
|
||||
|
||||
module.exports = (context, type, pluginOpt, pluginsPath) => {
|
||||
module.exports = async (context, type, pluginOpt, pluginsPath) => {
|
||||
const {stdout, stderr, options, logger} = context;
|
||||
if (!pluginOpt) {
|
||||
return noop;
|
||||
@@ -13,7 +13,7 @@ module.exports = (context, type, pluginOpt, pluginsPath) => {
|
||||
|
||||
const [name, config] = parseConfig(pluginOpt);
|
||||
const pluginName = name.pluginName ? name.pluginName : isFunction(name) ? `[Function: ${name.name}]` : name;
|
||||
const plugin = loadPlugin(context, name, pluginsPath);
|
||||
const plugin = await loadPlugin(context, name, pluginsPath);
|
||||
|
||||
debug(`options for ${pluginName}/${type}: %O`, config);
|
||||
|
||||
|
||||
@@ -44,11 +44,14 @@ function validateStep({required}, conf) {
|
||||
return conf.length === 0 || validateSteps(conf);
|
||||
}
|
||||
|
||||
function loadPlugin({cwd}, name, pluginsPath) {
|
||||
async function loadPlugin({cwd}, name, pluginsPath) {
|
||||
const basePath = pluginsPath[name]
|
||||
? dirname(resolveFrom.silent(__dirname, pluginsPath[name]) || resolveFrom(cwd, pluginsPath[name]))
|
||||
: __dirname;
|
||||
return isFunction(name) ? name : require(resolveFrom.silent(basePath, name) || resolveFrom(cwd, name));
|
||||
|
||||
// See https://github.com/mysticatea/eslint-plugin-node/issues/250
|
||||
// eslint-disable-next-line node/no-unsupported-features/es-syntax
|
||||
return isFunction(name) ? name : (await import(resolveFrom.silent(basePath, name) || resolveFrom(cwd, name))).default;
|
||||
}
|
||||
|
||||
function parseConfig(plugin) {
|
||||
|
||||
Reference in New Issue
Block a user