feat: add new plugins option
This commit is contained in:
+55
-18
@@ -1,52 +1,89 @@
|
||||
const {identity, isPlainObject, omit, castArray, isUndefined} = require('lodash');
|
||||
const {identity, isPlainObject, omit, castArray, isNil, isString} = require('lodash');
|
||||
const AggregateError = require('aggregate-error');
|
||||
const getError = require('../get-error');
|
||||
const PLUGINS_DEFINITIONS = require('../definitions/plugins');
|
||||
const {validateConfig} = require('./utils');
|
||||
const {validatePlugin, validateStep, loadPlugin, parseConfig} = require('./utils');
|
||||
const pipeline = require('./pipeline');
|
||||
const normalize = require('./normalize');
|
||||
|
||||
module.exports = (context, pluginsPath) => {
|
||||
const {options, logger} = context;
|
||||
let {options, logger} = context;
|
||||
const errors = [];
|
||||
const plugins = Object.entries(PLUGINS_DEFINITIONS).reduce(
|
||||
|
||||
const plugins = options.plugins
|
||||
? castArray(options.plugins).reduce((plugins, plugin) => {
|
||||
if (validatePlugin(plugin)) {
|
||||
const [name, config] = parseConfig(plugin);
|
||||
plugin = isString(name) ? loadPlugin(context, name, pluginsPath) : name;
|
||||
|
||||
if (isPlainObject(plugin)) {
|
||||
Object.entries(plugin).forEach(([type, func]) => {
|
||||
if (PLUGINS_DEFINITIONS[type]) {
|
||||
plugins[type] = [...(plugins[type] || []), [func, config]];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
errors.push(getError('EPLUGINSCONF', {plugin}));
|
||||
}
|
||||
} else {
|
||||
errors.push(getError('EPLUGINSCONF', {plugin}));
|
||||
}
|
||||
|
||||
return plugins;
|
||||
}, {})
|
||||
: [];
|
||||
|
||||
if (errors.length > 0) {
|
||||
throw new AggregateError(errors);
|
||||
}
|
||||
|
||||
options = {...plugins, ...options};
|
||||
|
||||
const pluginsConf = Object.entries(PLUGINS_DEFINITIONS).reduce(
|
||||
(
|
||||
plugins,
|
||||
pluginsConf,
|
||||
[type, {multiple, required, default: def, pipelineConfig, postprocess = identity, preprocess = identity}]
|
||||
) => {
|
||||
let pluginOpts;
|
||||
|
||||
if (isUndefined(options[type])) {
|
||||
if (isNil(options[type]) && def) {
|
||||
pluginOpts = def;
|
||||
} else {
|
||||
const defaultPaths = castArray(def);
|
||||
// If an object is passed and the path is missing, set the default one for single plugins
|
||||
if (isPlainObject(options[type]) && !options[type].path && defaultPaths.length === 1) {
|
||||
[options[type].path] = defaultPaths;
|
||||
// If an object is passed and the path is missing, merge it with step options
|
||||
if (isPlainObject(options[type]) && !options[type].path) {
|
||||
options[type] = castArray(plugins[type]).map(
|
||||
plugin => (plugin ? [plugin[0], Object.assign(plugin[1], options[type])] : plugin)
|
||||
);
|
||||
}
|
||||
if (!validateConfig({multiple, required}, options[type])) {
|
||||
if (!validateStep({multiple, required}, options[type])) {
|
||||
errors.push(getError('EPLUGINCONF', {type, multiple, required, pluginConf: options[type]}));
|
||||
return plugins;
|
||||
return pluginsConf;
|
||||
}
|
||||
pluginOpts = options[type];
|
||||
}
|
||||
|
||||
const steps = castArray(pluginOpts).map(pluginOpt =>
|
||||
normalize({...context, options: omit(options, Object.keys(PLUGINS_DEFINITIONS))}, type, pluginOpt, pluginsPath)
|
||||
normalize(
|
||||
{...context, options: omit(options, Object.keys(PLUGINS_DEFINITIONS), 'plugins')},
|
||||
type,
|
||||
pluginOpt,
|
||||
pluginsPath
|
||||
)
|
||||
);
|
||||
|
||||
plugins[type] = async input =>
|
||||
pluginsConf[type] = async input =>
|
||||
postprocess(
|
||||
await pipeline(steps, pipelineConfig && pipelineConfig(plugins, logger))(await preprocess(input)),
|
||||
await pipeline(steps, pipelineConfig && pipelineConfig(pluginsConf, logger))(await preprocess(input)),
|
||||
input
|
||||
);
|
||||
|
||||
return plugins;
|
||||
return pluginsConf;
|
||||
},
|
||||
{}
|
||||
plugins
|
||||
);
|
||||
if (errors.length > 0) {
|
||||
throw new AggregateError(errors);
|
||||
}
|
||||
return plugins;
|
||||
|
||||
return pluginsConf;
|
||||
};
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
const {dirname} = require('path');
|
||||
const {isString, isPlainObject, isFunction, noop, cloneDeep, omit} = require('lodash');
|
||||
const resolveFrom = require('resolve-from');
|
||||
const {isPlainObject, isFunction, noop, cloneDeep, omit} = require('lodash');
|
||||
const getError = require('../get-error');
|
||||
const {extractErrors} = require('../utils');
|
||||
const PLUGINS_DEFINITIONS = require('../definitions/plugins');
|
||||
const {loadPlugin, parseConfig} = require('./utils');
|
||||
|
||||
module.exports = ({cwd, stdout, stderr, options, logger}, type, pluginOpt, pluginsPath) => {
|
||||
module.exports = (context, type, pluginOpt, pluginsPath) => {
|
||||
const {stdout, stderr, options, logger} = context;
|
||||
if (!pluginOpt) {
|
||||
return noop;
|
||||
}
|
||||
|
||||
const {path, ...config} = isString(pluginOpt) || isFunction(pluginOpt) ? {path: pluginOpt} : pluginOpt;
|
||||
const [path, config] = parseConfig(pluginOpt);
|
||||
const pluginName = isFunction(path) ? `[Function: ${path.name}]` : path;
|
||||
|
||||
const basePath = pluginsPath[path]
|
||||
? dirname(resolveFrom.silent(__dirname, pluginsPath[path]) || resolveFrom(cwd, pluginsPath[path]))
|
||||
: __dirname;
|
||||
const plugin = isFunction(path) ? path : require(resolveFrom.silent(basePath, path) || resolveFrom(cwd, path));
|
||||
const plugin = loadPlugin(context, path, pluginsPath);
|
||||
|
||||
let func;
|
||||
if (isFunction(plugin)) {
|
||||
|
||||
+59
-9
@@ -1,18 +1,68 @@
|
||||
const {isString, isFunction, castArray} = require('lodash');
|
||||
const {dirname} = require('path');
|
||||
const {isString, isFunction, castArray, isArray, isPlainObject, isNil} = require('lodash');
|
||||
const resolveFrom = require('resolve-from');
|
||||
|
||||
const validateSingleConfig = conf => {
|
||||
const validateStepArrayDefinition = conf =>
|
||||
isArray(conf) &&
|
||||
(conf.length === 1 || conf.length === 2) &&
|
||||
(isString(conf[0]) || isFunction(conf[0])) &&
|
||||
(isNil(conf[1]) || isPlainObject(conf[1]));
|
||||
|
||||
const validateSingleStep = conf => {
|
||||
if (validateStepArrayDefinition(conf)) {
|
||||
return true;
|
||||
}
|
||||
conf = castArray(conf);
|
||||
return conf.length === 1 && (isString(conf[0]) || isString(conf[0].path) || isFunction(conf[0]));
|
||||
|
||||
if (conf.length !== 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const [path, config] = parseConfig(conf[0]);
|
||||
return (isString(path) || isFunction(path)) && isPlainObject(config);
|
||||
};
|
||||
|
||||
const validateMultipleConfig = conf => castArray(conf).every(conf => validateSingleConfig(conf));
|
||||
const validateMultipleStep = conf => {
|
||||
return conf.every(conf => validateSingleStep(conf));
|
||||
};
|
||||
|
||||
const validateConfig = ({multiple, required}, conf) => {
|
||||
function validatePlugin(conf) {
|
||||
return (
|
||||
isString(conf) ||
|
||||
(isArray(conf) &&
|
||||
(conf.length === 1 || conf.length === 2) &&
|
||||
(isString(conf[0]) || isPlainObject(conf[0])) &&
|
||||
(isNil(conf[1]) || isPlainObject(conf[1]))) ||
|
||||
(isPlainObject(conf) && (isNil(conf.path) || isString(conf.path) || isPlainObject(conf.path)))
|
||||
);
|
||||
}
|
||||
|
||||
function validateStep({multiple, required}, conf) {
|
||||
conf = castArray(conf).filter(Boolean);
|
||||
if (required) {
|
||||
return Boolean(conf) && conf.length >= 1 && (multiple ? validateMultipleConfig : validateSingleConfig)(conf);
|
||||
return conf.length >= 1 && (multiple ? validateMultipleStep : validateSingleStep)(conf);
|
||||
}
|
||||
return conf.length === 0 || (multiple ? validateMultipleConfig : validateSingleConfig)(conf);
|
||||
};
|
||||
return conf.length === 0 || (multiple ? validateMultipleStep : validateSingleStep)(conf);
|
||||
}
|
||||
|
||||
module.exports = {validateConfig};
|
||||
function loadPlugin({cwd}, path, pluginsPath) {
|
||||
const basePath = pluginsPath[path]
|
||||
? dirname(resolveFrom.silent(__dirname, pluginsPath[path]) || resolveFrom(cwd, pluginsPath[path]))
|
||||
: __dirname;
|
||||
return isFunction(path) ? path : require(resolveFrom.silent(basePath, path) || resolveFrom(cwd, path));
|
||||
}
|
||||
|
||||
function parseConfig(plugin) {
|
||||
let path;
|
||||
let config;
|
||||
if (isArray(plugin)) {
|
||||
[path, config] = plugin;
|
||||
} else if (isPlainObject(plugin) && !isNil(plugin.path)) {
|
||||
({path, ...config} = plugin);
|
||||
} else {
|
||||
path = plugin;
|
||||
}
|
||||
return [path, config || {}];
|
||||
}
|
||||
|
||||
module.exports = {validatePlugin, validateStep, loadPlugin, parseConfig};
|
||||
|
||||
Reference in New Issue
Block a user