65 lines
1.9 KiB
JavaScript
65 lines
1.9 KiB
JavaScript
import { trailingSlash, Tree } from "@weborigami/async-tree";
|
|
|
|
/**
|
|
* Given an old tree and a new tree, return a tree of changes indicated
|
|
* by the values: "added", "changed", or "deleted".
|
|
*
|
|
* @typedef {import("@weborigami/async-tree").Treelike} Treelike
|
|
*
|
|
* @this {import("@weborigami/types").AsyncTree|null}
|
|
* @param {Treelike} oldTreelike
|
|
* @param {Treelike} newTreelike
|
|
*/
|
|
export default async function changes(oldTreelike, newTreelike) {
|
|
const oldTree = Tree.from(oldTreelike, { deep: true, parent: this });
|
|
const newTree = Tree.from(newTreelike, { deep: true, parent: this });
|
|
|
|
const oldKeys = Array.from(await oldTree.keys());
|
|
const newKeys = Array.from(await newTree.keys());
|
|
|
|
const oldKeysNormalized = oldKeys.map(trailingSlash.remove);
|
|
const newKeysNormalized = newKeys.map(trailingSlash.remove);
|
|
|
|
let result;
|
|
|
|
for (const oldKey of oldKeys) {
|
|
const oldNormalized = trailingSlash.remove(oldKey);
|
|
if (!newKeysNormalized.includes(oldNormalized)) {
|
|
result ??= {};
|
|
result[oldKey] = "deleted";
|
|
continue;
|
|
}
|
|
|
|
const oldValue = await oldTree.get(oldKey);
|
|
const newValue = await newTree.get(oldKey);
|
|
|
|
if (Tree.isAsyncTree(oldValue) && Tree.isAsyncTree(newValue)) {
|
|
const treeChanges = await changes.call(this, oldValue, newValue);
|
|
if (treeChanges && Object.keys(treeChanges).length > 0) {
|
|
result ??= {};
|
|
result[oldKey] = treeChanges;
|
|
}
|
|
} else if (oldValue?.toString && newValue?.toString) {
|
|
const oldText = oldValue.toString();
|
|
const newText = newValue.toString();
|
|
if (oldText !== newText) {
|
|
result ??= {};
|
|
result[oldKey] = "changed";
|
|
}
|
|
} else {
|
|
result ??= {};
|
|
result[oldKey] = "changed";
|
|
}
|
|
}
|
|
|
|
for (const newKey of newKeys) {
|
|
const newNormalized = trailingSlash.remove(newKey);
|
|
if (!oldKeysNormalized.includes(newNormalized)) {
|
|
result ??= {};
|
|
result[newKey] = "added";
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|