// istanbul ignore next const isObject = (obj) => { if (typeof obj === "object" && obj !== null) { if (typeof Object.getPrototypeOf === "function") { const prototype = Object.getPrototypeOf(obj); return prototype === Object.prototype || prototype === null; } return Object.prototype.toString.call(obj) === "[object Object]"; } return false; }; export const merge = (...objects) => objects.reduce((result, current) => { if (current === undefined) { return result; } if (Array.isArray(current)) { throw new TypeError("Arguments provided to ts-deepmerge must be objects, not arrays."); } Object.keys(current).forEach((key) => { if (["__proto__", "constructor", "prototype"].includes(key)) { return; } if (Array.isArray(result[key]) && Array.isArray(current[key])) { result[key] = merge.options.mergeArrays ? merge.options.uniqueArrayItems ? Array.from(new Set(result[key].concat(current[key]))) : [...result[key], ...current[key]] : current[key]; } else if (isObject(result[key]) && isObject(current[key])) { result[key] = merge(result[key], current[key]); } else if (!isObject(result[key]) && isObject(current[key])) { result[key] = merge(current[key], undefined); } else { result[key] = current[key] === undefined ? merge.options.allowUndefinedOverrides ? current[key] : result[key] : current[key]; } }); return result; }, {}); const defaultOptions = { allowUndefinedOverrides: true, mergeArrays: true, uniqueArrayItems: true, }; merge.options = defaultOptions; merge.withOptions = (options, ...objects) => { merge.options = Object.assign(Object.assign({}, defaultOptions), options); const result = merge(...objects); merge.options = defaultOptions; return result; };