export function deepMergeDocuments(base, override) {
    const merged = {};
    const scopes = new Set([...Object.keys(base), ...Object.keys(override)]);
    for (const scope of scopes) {
        const baseScope = getOwnRecordEntry(base, scope);
        const overrideScope = getOwnRecordEntry(override, scope);
        const nextScope = mergeScope(scope, baseScope, overrideScope);
        if (Object.keys(nextScope).length > 0) {
            setOwnEntry(merged, scope, nextScope);
        }
    }
    return merged;
}
function mergeScope(scope, baseScope, overrideScope) {
    if (scope === "runtime") {
        return mergeRuntimeScope(baseScope, overrideScope);
    }
    const scopeEntries = Object.entries(overrideScope).filter(([, value]) => value !== undefined);
    const merged = {};
    for (const [key, value] of Object.entries(baseScope)) {
        setOwnEntry(merged, key, value);
    }
    for (const [key, value] of scopeEntries) {
        setOwnEntry(merged, key, value);
    }
    return merged;
}
function mergeRuntimeScope(baseScope, overrideScope, path = []) {
    const merged = {};
    const keys = new Set([...Object.keys(baseScope), ...Object.keys(overrideScope)]);
    for (const key of keys) {
        const baseValue = getOwnEntry(baseScope, key);
        const overrideValue = getOwnEntry(overrideScope, key);
        if (overrideValue === undefined) {
            if (baseValue !== undefined) {
                setOwnEntry(merged, key, baseValue);
            }
            continue;
        }
        if (isRecord(baseValue) && isRecord(overrideValue)) {
            setOwnEntry(merged, key, mergeRuntimeScope(baseValue, overrideValue, [...path, key]));
            continue;
        }
        setOwnEntry(merged, key, overrideValue);
    }
    return merged;
}
function isRecord(value) {
    return Boolean(value && typeof value === "object" && !Array.isArray(value));
}
function getOwnEntry(record, key) {
    return Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;
}
function getOwnRecordEntry(record, key) {
    const value = getOwnEntry(record, key);
    return isRecord(value) ? value : {};
}
function setOwnEntry(target, key, value) {
    Object.defineProperty(target, key, {
        value,
        enumerable: true,
        writable: true,
        configurable: true
    });
}
