UNPKG

1.85 kBJavaScriptView Raw
1'use strict'
2
3const deepmerge = require('deepmerge')
4const isPlainObj = require('is-plain-obj')
5
6const { groupBy } = require('./utils/group')
7const { removeUndefined } = require('./utils/remove_falsy')
8
9// Merge an array of configuration objects.
10// Last items have higher priority.
11// Configuration objects are deeply merged.
12// - Arrays are overridden, not concatenated.
13const mergeConfigs = function (configs) {
14 const cleanedConfigs = configs.map(removeUndefinedProps)
15 return deepmerge.all(cleanedConfigs, { arrayMerge })
16}
17
18const removeUndefinedProps = function ({ build = {}, ...config }) {
19 return removeUndefined({ ...config, build: removeUndefined(build) })
20}
21
22// By default `deepmerge` concatenates arrays. We use the `arrayMerge` option
23// to remove this behavior. Also, we merge some array properties differently,
24// such as `plugins`.
25const arrayMerge = function (arrayA, arrayB) {
26 if (isPluginsProperty(arrayA) && isPluginsProperty(arrayB)) {
27 return mergePlugins(arrayA, arrayB)
28 }
29
30 return arrayB
31}
32
33// `deepmerge` does not allow retrieving the name of the array property being
34// merged, so we need to do some heuristics.
35const isPluginsProperty = function (array) {
36 return Array.isArray(array) && array.every(isPluginObject)
37}
38
39const isPluginObject = function (object) {
40 return isPlainObj(object) && typeof object.package === 'string'
41}
42
43// Merge two `config.plugins`. Merge plugins with the same `plugin.package`.
44const mergePlugins = function (pluginsA, pluginsB) {
45 const plugins = [...pluginsA, ...pluginsB]
46 return groupBy(plugins, 'package').map(mergePluginConfigs)
47}
48
49const mergePluginConfigs = function (plugins) {
50 return plugins.reduce(mergePluginsPair, {})
51}
52
53const mergePluginsPair = function (pluginA, pluginB) {
54 return deepmerge(pluginA, pluginB, { arrayMerge })
55}
56
57module.exports = { mergeConfigs }