import { __assign, __spreadArray } from "tslib"; import { isNonNullObject } from "./objects.js"; var hasOwnProperty = Object.prototype.hasOwnProperty; export function mergeDeep() { var sources = []; for (var _i = 0; _i < arguments.length; _i++) { sources[_i] = arguments[_i]; } return mergeDeepArray(sources); } // In almost any situation where you could succeed in getting the // TypeScript compiler to infer a tuple type for the sources array, you // could just use mergeDeep instead of mergeDeepArray, so instead of // trying to convert T[] to an intersection type we just infer the array // element type, which works perfectly when the sources array has a // consistent element type. export function mergeDeepArray(sources) { var target = sources[0] || {}; var count = sources.length; if (count > 1) { var merger = new DeepMerger(); for (var i = 1; i < count; ++i) { target = merger.merge(target, sources[i]); } } return target; } var defaultReconciler = function (target, source, property) { return this.merge(target[property], source[property]); }; var DeepMerger = /** @class */ (function () { function DeepMerger(reconciler) { if (reconciler === void 0) { reconciler = defaultReconciler; } this.reconciler = reconciler; this.isObject = isNonNullObject; this.pastCopies = new Set(); } DeepMerger.prototype.merge = function (target, source) { var _this = this; var context = []; for (var _i = 2; _i < arguments.length; _i++) { context[_i - 2] = arguments[_i]; } if (isNonNullObject(source) && isNonNullObject(target)) { Object.keys(source).forEach(function (sourceKey) { if (hasOwnProperty.call(target, sourceKey)) { var targetValue = target[sourceKey]; if (source[sourceKey] !== targetValue) { var result = _this.reconciler.apply(_this, __spreadArray([target, source, sourceKey], context, false)); // A well-implemented reconciler may return targetValue to indicate // the merge changed nothing about the structure of the target. if (result !== targetValue) { target = _this.shallowCopyForMerge(target); target[sourceKey] = result; } } } else { // If there is no collision, the target can safely share memory with // the source, and the recursion can terminate here. target = _this.shallowCopyForMerge(target); target[sourceKey] = source[sourceKey]; } }); return target; } // If source (or target) is not an object, let source replace target. return source; }; DeepMerger.prototype.shallowCopyForMerge = function (value) { if (isNonNullObject(value)) { if (!this.pastCopies.has(value)) { if (Array.isArray(value)) { value = value.slice(0); } else { value = __assign({ __proto__: Object.getPrototypeOf(value) }, value); } this.pastCopies.add(value); } } return value; }; return DeepMerger; }()); export { DeepMerger }; //# sourceMappingURL=mergeDeep.js.map