95 lines
2.2 KiB
JavaScript
95 lines
2.2 KiB
JavaScript
import { isArray, zip, isObject, uniq, isEqual } from 'lodash/fp';
|
|
|
|
const createContext = ()=>({
|
|
path: []
|
|
});
|
|
/**
|
|
* Compute differences between two JSON objects and returns them
|
|
*
|
|
* @param a - First object
|
|
* @param b - Second object
|
|
* @param ctx - Context used to keep track of the current path during recursion
|
|
*/ const diff = (a, b, ctx = createContext())=>{
|
|
const diffs = [];
|
|
const { path } = ctx;
|
|
const aType = typeof a;
|
|
const bType = typeof b;
|
|
// Define helpers
|
|
const added = ()=>{
|
|
diffs.push({
|
|
kind: 'added',
|
|
path,
|
|
type: bType,
|
|
value: b
|
|
});
|
|
return diffs;
|
|
};
|
|
const deleted = ()=>{
|
|
diffs.push({
|
|
kind: 'deleted',
|
|
path,
|
|
type: aType,
|
|
value: a
|
|
});
|
|
return diffs;
|
|
};
|
|
const modified = ()=>{
|
|
diffs.push({
|
|
kind: 'modified',
|
|
path,
|
|
types: [
|
|
aType,
|
|
bType
|
|
],
|
|
values: [
|
|
a,
|
|
b
|
|
]
|
|
});
|
|
return diffs;
|
|
};
|
|
if (isArray(a) && isArray(b)) {
|
|
let k = 0;
|
|
for (const [aItem, bItem] of zip(a, b)){
|
|
const kCtx = {
|
|
path: [
|
|
...path,
|
|
k.toString()
|
|
]
|
|
};
|
|
const kDiffs = diff(aItem, bItem, kCtx);
|
|
diffs.push(...kDiffs);
|
|
k += 1;
|
|
}
|
|
return diffs;
|
|
}
|
|
if (isObject(a) && isObject(b)) {
|
|
const keys = uniq(Object.keys(a).concat(Object.keys(b)));
|
|
for (const key of keys){
|
|
const aValue = a[key];
|
|
const bValue = b[key];
|
|
const nestedDiffs = diff(aValue, bValue, {
|
|
path: [
|
|
...path,
|
|
key
|
|
]
|
|
});
|
|
diffs.push(...nestedDiffs);
|
|
}
|
|
return diffs;
|
|
}
|
|
if (!isEqual(a, b)) {
|
|
if (aType === 'undefined') {
|
|
return added();
|
|
}
|
|
if (bType === 'undefined') {
|
|
return deleted();
|
|
}
|
|
return modified();
|
|
}
|
|
return diffs;
|
|
};
|
|
|
|
export { diff };
|
|
//# sourceMappingURL=json.mjs.map
|