Superdiff provides a complete and readable diff for both arrays and objects. Plus, it supports stream and file inputs for handling large datasets efficiently, is battle-tested, has zero dependencies, and is super fast.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
1.8 KiB

2 years ago
import { STATUS, ListDiff, ListData } from "./model";
import { isEqual } from "./utils";
function formatSingleListDiff(
listData: ListData,
status: "added" | "removed"
): ListDiff {
return {
type: "list",
diff: listData.map((data) => ({ value: data, status })),
};
}
export const getListDiff = (
prevList: ListData[] | undefined | null,
nextList: ListData[] | undefined | null
): ListDiff => {
if (!prevList && !nextList) {
return {
type: "list",
diff: [],
};
}
if (!prevList) {
return formatSingleListDiff(nextList, "added");
}
if (!nextList) {
return formatSingleListDiff(prevList, "removed");
}
const diff: ListDiff["diff"] = [];
nextList.forEach((nextValue, i) => {
const prevIndex = prevList.findIndex((prevValue) =>
isEqual(prevValue, nextValue)
);
const indexDiff = prevIndex === -1 ? null : i - prevIndex;
if (indexDiff === 0) {
return diff.push({
value: nextValue,
prevIndex,
newIndex: i,
indexDiff,
status: STATUS.EQUAL,
});
}
if (prevIndex === -1) {
return diff.push({
value: nextValue,
prevIndex: null,
newIndex: i,
indexDiff,
status: STATUS.ADDED,
});
}
return diff.push({
value: nextValue,
prevIndex,
newIndex: i,
indexDiff,
status: STATUS.MOVED,
});
});
prevList.forEach((prevValue, i) => {
if (!nextList.some((nextValue) => isEqual(nextValue, prevValue))) {
return diff.splice(i, 0, {
value: prevValue,
prevIndex: i,
newIndex: null,
indexDiff: null,
status: STATUS.DELETED,
});
}
});
return {
type: "list",
diff,
};
};
export function hasListChanged(listDiff: ListDiff): boolean {
return listDiff.diff.some((d) => d.status !== STATUS.EQUAL);
}