'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;