File size: 1,383 Bytes
68d7816 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | export interface RecordDiff {
readonly added: readonly string[];
readonly removed: readonly string[];
readonly changed: readonly string[];
}
export function diffRecords<T>(
previous: Readonly<Record<string, T>> | undefined,
current: Readonly<Record<string, T>> | undefined,
): RecordDiff {
const prev = previous ?? {};
const curr = current ?? {};
const added: string[] = [];
const removed: string[] = [];
const changed: string[] = [];
for (const key of Object.keys(curr)) {
if (!(key in prev)) {
added.push(key);
} else if (!deepEqual(prev[key], curr[key])) {
changed.push(key);
}
}
for (const key of Object.keys(prev)) {
if (!(key in curr)) {
removed.push(key);
}
}
return { added, removed, changed };
}
export function deepEqual(a: unknown, b: unknown): boolean {
if (Object.is(a, b)) return true;
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;
if (Array.isArray(a) !== Array.isArray(b)) return false;
const aKeys = Object.keys(a);
const bKeys = Object.keys(b);
if (aKeys.length !== bKeys.length) return false;
for (const key of aKeys) {
if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
if (!deepEqual((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key])) {
return false;
}
}
return true;
}
|