import { filterInPlace } from "./_utils.ts";
const { hasOwn } = Object;
export function deepMerge(record, other, options) {
    const result = {};
    const keys = new Set([
        ...getKeys(record),
        ...getKeys(other),
    ]);
    for (const key of keys) {
        if (key === "__proto__") {
            continue;
        }
        const a = record[key];
        if (!hasOwn(other, key)) {
            result[key] = a;
            continue;
        }
        const b = other[key];
        if (isNonNullObject(a) && isNonNullObject(b)) {
            result[key] = mergeObjects(a, b, options);
            continue;
        }
        result[key] = b;
    }
    return result;
}
function mergeObjects(left, right, options = {
    arrays: "merge",
    sets: "merge",
    maps: "merge",
}) {
    if (isMergeable(left) && isMergeable(right)) {
        return deepMerge(left, right);
    }
    if (isIterable(left) && isIterable(right)) {
        if ((Array.isArray(left)) && (Array.isArray(right))) {
            if (options.arrays === "merge") {
                return left.concat(right);
            }
            return right;
        }
        if ((left instanceof Map) && (right instanceof Map)) {
            if (options.maps === "merge") {
                return new Map([
                    ...left,
                    ...right,
                ]);
            }
            return right;
        }
        if ((left instanceof Set) && (right instanceof Set)) {
            if (options.sets === "merge") {
                return new Set([
                    ...left,
                    ...right,
                ]);
            }
            return right;
        }
    }
    return right;
}
function isMergeable(value) {
    return Object.getPrototypeOf(value) === Object.prototype;
}
function isIterable(value) {
    return typeof value[Symbol.iterator] === "function";
}
function isNonNullObject(value) {
    return value !== null && typeof value === "object";
}
function getKeys(record) {
    const ret = Object.getOwnPropertySymbols(record);
    filterInPlace(ret, (key) => Object.prototype.propertyIsEnumerable.call(record, key));
    ret.push(...Object.keys(record));
    return ret;
}
//# sourceMappingURL=data:application/json;base64,[encoded data, 18204 characters]