JSON Merge Patch Application (RFC 7386)

Apply RFC 7386 merge patches without mutating the target, treating null as deletion, replacing arrays and rejecting unsafe object keys.

JavascriptData Integrity

Code

snippet
function isPlainObject(value) {
  if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
  const prototype = Object.getPrototypeOf(value);
  return prototype === Object.prototype || prototype === null;
}

function cloneJson(value) {
  return value === undefined ? undefined : structuredClone(value);
}

export function applyMergePatch(target, patch) {
  if (!isPlainObject(patch)) return cloneJson(patch);
  const result = isPlainObject(target) ? { ...target } : {};
  for (const [key, value] of Object.entries(patch)) {
    if (key === "__proto__" || key === "constructor" || key === "prototype") {
      throw new TypeError("unsafe patch key: " + key);
    }
    if (value === null) {
      delete result[key];
      continue;
    }
    result[key] = applyMergePatch(result[key], value);
  }
  return result;
}