|
'use strict';
|
|
const {URL} = require('url');
|
|
const is = require('@sindresorhus/is');
|
|
const knownHookEvents = require('./known-hook-events');
|
|
|
|
const merge = (target, ...sources) => {
|
|
for (const source of sources) {
|
|
for (const [key, sourceValue] of Object.entries(source)) {
|
|
if (is.undefined(sourceValue)) {
|
|
continue;
|
|
}
|
|
|
|
const targetValue = target[key];
|
|
if (is.urlInstance(targetValue) && (is.urlInstance(sourceValue) || is.string(sourceValue))) {
|
|
target[key] = new URL(sourceValue, targetValue);
|
|
} else if (is.plainObject(sourceValue)) {
|
|
if (is.plainObject(targetValue)) {
|
|
target[key] = merge({}, targetValue, sourceValue);
|
|
} else {
|
|
target[key] = merge({}, sourceValue);
|
|
}
|
|
} else if (is.array(sourceValue)) {
|
|
target[key] = merge([], sourceValue);
|
|
} else {
|
|
target[key] = sourceValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
return target;
|
|
};
|
|
|
|
const mergeOptions = (...sources) => {
|
|
sources = sources.map(source => source || {});
|
|
const merged = merge({}, ...sources);
|
|
|
|
const hooks = {};
|
|
for (const hook of knownHookEvents) {
|
|
hooks[hook] = [];
|
|
}
|
|
|
|
for (const source of sources) {
|
|
if (source.hooks) {
|
|
for (const hook of knownHookEvents) {
|
|
hooks[hook] = hooks[hook].concat(source.hooks[hook]);
|
|
}
|
|
}
|
|
}
|
|
|
|
merged.hooks = hooks;
|
|
|
|
return merged;
|
|
};
|
|
|
|
const mergeInstances = (instances, methods) => {
|
|
const handlers = instances.map(instance => instance.defaults.handler);
|
|
const size = instances.length - 1;
|
|
|
|
return {
|
|
methods,
|
|
options: mergeOptions(...instances.map(instance => instance.defaults.options)),
|
|
handler: (options, next) => {
|
|
let iteration = -1;
|
|
const iterate = options => handlers[++iteration](options, iteration === size ? next : iterate);
|
|
|
|
return iterate(options);
|
|
}
|
|
};
|
|
};
|
|
|
|
module.exports = merge;
|
|
module.exports.options = mergeOptions;
|
|
module.exports.instances = mergeInstances;
|