UNPKG

3.07 kBJavaScriptView Raw
1const {identity, isPlainObject, omit, castArray, isNil, isString} = require('lodash');
2const AggregateError = require('aggregate-error');
3const getError = require('../get-error');
4const PLUGINS_DEFINITIONS = require('../definitions/plugins');
5const {validatePlugin, validateStep, loadPlugin, parseConfig} = require('./utils');
6const pipeline = require('./pipeline');
7const normalize = require('./normalize');
8
9module.exports = (context, pluginsPath) => {
10 let {options, logger} = context;
11 const errors = [];
12
13 const plugins = options.plugins
14 ? castArray(options.plugins).reduce((plugins, plugin) => {
15 if (validatePlugin(plugin)) {
16 const [name, config] = parseConfig(plugin);
17 plugin = isString(name) ? loadPlugin(context, name, pluginsPath) : name;
18
19 if (isPlainObject(plugin)) {
20 Object.entries(plugin).forEach(([type, func]) => {
21 if (PLUGINS_DEFINITIONS[type]) {
22 Reflect.defineProperty(func, 'pluginName', {
23 value: isPlainObject(name) ? 'Inline plugin' : name,
24 writable: false,
25 enumerable: true,
26 });
27 plugins[type] = [...(plugins[type] || []), [func, config]];
28 }
29 });
30 } else {
31 errors.push(getError('EPLUGINSCONF', {plugin}));
32 }
33 } else {
34 errors.push(getError('EPLUGINSCONF', {plugin}));
35 }
36
37 return plugins;
38 }, {})
39 : [];
40
41 if (errors.length > 0) {
42 throw new AggregateError(errors);
43 }
44
45 options = {...plugins, ...options};
46
47 const pluginsConf = Object.entries(PLUGINS_DEFINITIONS).reduce(
48 (pluginsConf, [type, {required, default: def, pipelineConfig, postprocess = identity, preprocess = identity}]) => {
49 let pluginOptions;
50
51 if (isNil(options[type]) && def) {
52 pluginOptions = def;
53 } else {
54 // If an object is passed and the path is missing, merge it with step options
55 if (isPlainObject(options[type]) && !options[type].path) {
56 options[type] = castArray(plugins[type]).map((plugin) =>
57 plugin ? [plugin[0], Object.assign(plugin[1], options[type])] : plugin
58 );
59 }
60
61 if (!validateStep({required}, options[type])) {
62 errors.push(getError('EPLUGINCONF', {type, required, pluginConf: options[type]}));
63 return pluginsConf;
64 }
65
66 pluginOptions = options[type];
67 }
68
69 const steps = castArray(pluginOptions).map((pluginOpt) =>
70 normalize(
71 {...context, options: omit(options, Object.keys(PLUGINS_DEFINITIONS), 'plugins')},
72 type,
73 pluginOpt,
74 pluginsPath
75 )
76 );
77
78 pluginsConf[type] = async (input) =>
79 postprocess(
80 await pipeline(steps, pipelineConfig && pipelineConfig(pluginsConf, logger))(await preprocess(input)),
81 input
82 );
83
84 return pluginsConf;
85 },
86 plugins
87 );
88 if (errors.length > 0) {
89 throw new AggregateError(errors);
90 }
91
92 return pluginsConf;
93};