Files
HolodoriCalc/scripts/holodoridb-diff.mjs
T

22 lines
1.2 KiB
JavaScript

import { isDeepStrictEqual } from 'node:util';
// Use row IDs so insertion/reordering does not masquerade as changed records.
export function jsonChanges(before, after, location = '$') {
if (isDeepStrictEqual(before, after)) return [];
if (Array.isArray(before) && Array.isArray(after)) {
const keyed = rows => rows.every(row => row && typeof row === 'object' && (row.id ?? row.data?.id) != null)
&& new Set(rows.map(row => row.id ?? row.data.id)).size === rows.length;
if (keyed(before) && keyed(after)) {
const index = rows => Object.fromEntries(rows.map(row => [row.id ?? row.data.id, row]));
return jsonChanges(index(before), index(after), location);
}
}
if (before && after && typeof before === 'object' && typeof after === 'object'
&& !Array.isArray(before) && !Array.isArray(after)) {
return [...new Set([...Object.keys(before), ...Object.keys(after)])].flatMap(key =>
jsonChanges(before[key], after[key], `${location}[${JSON.stringify(key)}]`));
}
return [{ path: location, type: before === undefined ? 'added' : after === undefined ? 'deleted' : 'modified',
...(before === undefined ? {} : { before }), ...(after === undefined ? {} : { after }) }];
}