@netlify/config
Version:
Netlify config module
50 lines (49 loc) • 2.21 kB
JavaScript
import deepmerge from 'deepmerge';
import isPlainObj from 'is-plain-obj';
import { groupBy } from './utils/group.js';
import { removeUndefined } from './utils/remove_falsy.js';
// Merge an array of configuration objects.
// Last items have higher priority.
// Configuration objects are deeply merged.
// - By default, Arrays are overridden, not concatenated. This behavior can
// be changed by setting the `concatenateArrays` property to `true`.
export const mergeConfigs = function (configs, { concatenateArrays } = {}) {
const cleanedConfigs = configs.map(removeUndefinedProps);
return deepmerge.all(cleanedConfigs, { arrayMerge: concatenateArrays ? arrayConcatenate : arrayMerge });
};
const removeUndefinedProps = function ({ build = {}, ...config }) {
return removeUndefined({ ...config, build: removeUndefined(build) });
};
// By default, `deepmerge` concatenates arrays. We use the `arrayMerge` option
// to remove this behavior. Also, we merge some array properties differently,
// such as `plugins`.
const arrayMerge = function (arrayA, arrayB) {
if (isPluginsProperty(arrayA) && isPluginsProperty(arrayB)) {
return mergePlugins(arrayA, arrayB);
}
return arrayB;
};
// Concatenate two arrays such that elements from array A come after elements
// from array B.
const arrayConcatenate = function (arrayA, arrayB) {
return [...arrayB, ...arrayA];
};
// `deepmerge` does not allow retrieving the name of the array property being
// merged, so we need to do some heuristics.
const isPluginsProperty = function (array) {
return Array.isArray(array) && array.every(isPluginObject);
};
const isPluginObject = function (object) {
return isPlainObj(object) && typeof object.package === 'string';
};
// Merge two `config.plugins`. Merge plugins with the same `plugin.package`.
const mergePlugins = function (pluginsA, pluginsB) {
const plugins = [...pluginsA, ...pluginsB];
return groupBy(plugins, 'package').map(mergePluginConfigs);
};
const mergePluginConfigs = function (plugins) {
return plugins.reduce(mergePluginsPair, {});
};
const mergePluginsPair = function (pluginA, pluginB) {
return deepmerge(pluginA, pluginB, { arrayMerge });
};