1 | const {identity, isPlainObject, omit, castArray, isNil, isString} = require('lodash');
|
2 | const AggregateError = require('aggregate-error');
|
3 | const getError = require('../get-error');
|
4 | const PLUGINS_DEFINITIONS = require('../definitions/plugins');
|
5 | const {validatePlugin, validateStep, loadPlugin, parseConfig} = require('./utils');
|
6 | const pipeline = require('./pipeline');
|
7 | const normalize = require('./normalize');
|
8 |
|
9 | module.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 |
|
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 | };
|