UNPKG

datum-merge

Version:

Simplified diff and merging for deeply nested objects

96 lines (95 loc) 3.95 kB
import { isArrayOfAny, emptyObject, isObject, isString } from "./type-utils"; import { deepClone, getObjectKeys } from "./datum-utils"; import { deepDiffTyped } from "./diff-high"; import { UpdateCode, mergeScalarField, mergeVectorField } from "./merge-low"; export function updateCodeInfo(mergeCode) { if (!isString(mergeCode)) { return { enable: false }; } const allowUnset = [ UpdateCode.Y, UpdateCode.D, UpdateCode.U, UpdateCode.XR, UpdateCode.XD, UpdateCode.XI ].includes(mergeCode); const allowInsert = [ UpdateCode.Y, UpdateCode.I, UpdateCode.B, UpdateCode.XR, UpdateCode.XM, UpdateCode.XS, UpdateCode.XF ].includes(mergeCode); const allowUpdate = [ UpdateCode.Y, UpdateCode.H, UpdateCode.U, UpdateCode.B, UpdateCode.XR, UpdateCode.XS, UpdateCode.XF, UpdateCode.XM, UpdateCode.XI, UpdateCode.XD ].includes(mergeCode); return { insert: allowInsert, update: allowUpdate, unset: allowUnset, enable: allowInsert || allowUpdate || allowUnset, }; } export function shallowMerge(target, source, scalarCode, vectorCode, excludeKeys, includeKeys) { const sourceKeys = getObjectKeys(source, excludeKeys, includeKeys); if (!(sourceKeys === null || sourceKeys === void 0 ? void 0 : sourceKeys.length)) { return false; } let changed = false; for (const label of sourceKeys) { if (isArrayOfAny(target[label]) || isArrayOfAny(source[label])) { if (mergeVectorField(target, source, label, vectorCode !== null && vectorCode !== void 0 ? vectorCode : scalarCode)) { changed = true; } continue; } if (mergeScalarField(target, source, label, scalarCode)) changed = true; } return changed; } export function immutableMerge(target, source, scalarCode, vectorCode) { const targetCopy = deepClone(target); shallowMerge(targetCopy, source, scalarCode, vectorCode); return targetCopy; } ; export function deepMerge(target, source, scalarCode, vectorCode, nestedCode) { const sourceKeys = getObjectKeys(source); if (!(sourceKeys === null || sourceKeys === void 0 ? void 0 : sourceKeys.length)) { return false; } let changed = false; for (const label of sourceKeys) { if (isArrayOfAny(target[label]) || isArrayOfAny(source[label])) { if (mergeVectorField(target, source, label, vectorCode)) { changed = true; } continue; } if (isObject(target[label]) && isObject(source[label])) { if (nestedCode === UpdateCode.N) continue; if (nestedCode === UpdateCode.Y) { if (mergeScalarField(target, source, label, scalarCode)) changed = true; continue; } if (deepMerge(target[label], source[label], nestedCode.startsWith("X") ? scalarCode : nestedCode, nestedCode.startsWith("X") ? nestedCode : vectorCode, nestedCode)) { changed = true; } continue; } if (mergeScalarField(target, source, label, scalarCode)) { changed = true; } } return changed; } export function immutableDeepMerge(target, source, scalarCode, vectorCode, nestedCode) { const targetCopy = deepClone(target); deepMerge(targetCopy, source, scalarCode, vectorCode !== null && vectorCode !== void 0 ? vectorCode : scalarCode, nestedCode !== null && nestedCode !== void 0 ? nestedCode : scalarCode); return targetCopy; } ; export function diffFromMerge(target, source, scalarCode, vectorCode, nestedCode, orderInd = false) { const targetCopy = immutableDeepMerge(target, source, scalarCode, vectorCode, nestedCode); const delta = deepDiffTyped(target, targetCopy, orderInd); return emptyObject(delta) ? false : delta; }