UNPKG

datum-merge

Version:

Simplified diff and merging for deeply nested objects

81 lines (80 loc) 2.83 kB
import { emptyObject, isString } from "./type-utils"; import { createValueKeys, deepClone, getObjectKeys } from "./datum-utils"; import { asLodashPath, deepPatchLog } from "./patch-low"; import { UpdateCode } from "./merge-low"; import { detailMerge, fillUpdateCodes } from "./merge-conf"; export function customMergePatch(target, source, mergeConf, excludeKeys) { switch (mergeConf) { case UpdateCode.C: return false; case UpdateCode.T: return []; case UpdateCode.N: return false; case UpdateCode.Y: return bypassMergePatch(target, source); } const mergeCodes = fillUpdateCodes(source, mergeConf, false, excludeKeys); if (emptyObject(mergeCodes)) { return false; } const targetBkp = deepClone(target); const changed = detailMerge(target, source, mergeCodes); const patch = deepMergeLog(targetBkp, target, mergeCodes); if (changed || (patch === null || patch === void 0 ? void 0 : patch.length) > 0) { return patch; } return false; } export function bypassMergePatch(target, source) { const sourceKeys = getObjectKeys(source !== null && source !== void 0 ? source : {}); if (!source || !sourceKeys.length) { return false; } const mergeCodes = createValueKeys(sourceKeys, UpdateCode.Y); const targetBkp = deepClone(target); Object.assign(target, Object.assign({}, source)); const patch = deepMergeLog(targetBkp, target, mergeCodes); return !(patch === null || patch === void 0 ? void 0 : patch.length) ? false : patch; } export function deepMergeLog(lhsObj, rhsObj, mergeCodes) { const mergeLog = deepPatchLog(lhsObj, rhsObj, false, true); if (!(mergeLog === null || mergeLog === void 0 ? void 0 : mergeLog.length)) { return []; } const opCodeMap = { "add": UpdateCode.I, "replace": UpdateCode.H, "remove": UpdateCode.D, "test": UpdateCode.N, }; for (const patchItem of mergeLog) { const pathParts = asLodashPath(patchItem.path); patchItem.code = !mergeCodes ? opCodeMap[patchItem.op] : selectPathCode(mergeCodes, pathParts); } return mergeLog; } ; export function selectPathCode(mergeCodes, pathParts) { if (!mergeCodes || emptyObject(mergeCodes)) { return UpdateCode.N; } let currConf = mergeCodes; for (let itr = 0; itr < pathParts.length; itr++) { const part = pathParts[itr]; const partConf = currConf[part]; if (!partConf) { return UpdateCode.N; } if (isString(partConf)) { return partConf; } if (itr === pathParts.length - 1) { return UpdateCode.I; } currConf = partConf; } return UpdateCode.N; }