93 lines
2.4 KiB
JavaScript
93 lines
2.4 KiB
JavaScript
import { s as serialize } from '../shared/ohash.D__AXeF1.mjs';
|
|
export { i as isEqual } from '../shared/ohash.D__AXeF1.mjs';
|
|
|
|
function diff(obj1, obj2) {
|
|
const h1 = _toHashedObject(obj1);
|
|
const h2 = _toHashedObject(obj2);
|
|
return _diff(h1, h2);
|
|
}
|
|
function _diff(h1, h2) {
|
|
const diffs = [];
|
|
const allProps = /* @__PURE__ */ new Set([
|
|
...Object.keys(h1.props || {}),
|
|
...Object.keys(h2.props || {})
|
|
]);
|
|
if (h1.props && h2.props) {
|
|
for (const prop of allProps) {
|
|
const p1 = h1.props[prop];
|
|
const p2 = h2.props[prop];
|
|
if (p1 && p2) {
|
|
diffs.push(..._diff(h1.props?.[prop], h2.props?.[prop]));
|
|
} else if (p1 || p2) {
|
|
diffs.push(
|
|
new DiffEntry((p2 || p1).key, p1 ? "removed" : "added", p2, p1)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
if (allProps.size === 0 && h1.hash !== h2.hash) {
|
|
diffs.push(new DiffEntry((h2 || h1).key, "changed", h2, h1));
|
|
}
|
|
return diffs;
|
|
}
|
|
function _toHashedObject(obj, key = "") {
|
|
if (obj && typeof obj !== "object") {
|
|
return new DiffHashedObject(key, obj, serialize(obj));
|
|
}
|
|
const props = {};
|
|
const hashes = [];
|
|
for (const _key in obj) {
|
|
props[_key] = _toHashedObject(obj[_key], key ? `${key}.${_key}` : _key);
|
|
hashes.push(props[_key].hash);
|
|
}
|
|
return new DiffHashedObject(key, obj, `{${hashes.join(":")}}`, props);
|
|
}
|
|
class DiffEntry {
|
|
constructor(key, type, newValue, oldValue) {
|
|
this.key = key;
|
|
this.type = type;
|
|
this.newValue = newValue;
|
|
this.oldValue = oldValue;
|
|
}
|
|
toString() {
|
|
return this.toJSON();
|
|
}
|
|
toJSON() {
|
|
switch (this.type) {
|
|
case "added": {
|
|
return `Added \`${this.key}\``;
|
|
}
|
|
case "removed": {
|
|
return `Removed \`${this.key}\``;
|
|
}
|
|
case "changed": {
|
|
return `Changed \`${this.key}\` from \`${this.oldValue?.toString() || "-"}\` to \`${this.newValue.toString()}\``;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
class DiffHashedObject {
|
|
constructor(key, value, hash, props) {
|
|
this.key = key;
|
|
this.value = value;
|
|
this.hash = hash;
|
|
this.props = props;
|
|
}
|
|
toString() {
|
|
if (this.props) {
|
|
return `{${Object.keys(this.props).join(",")}}`;
|
|
} else {
|
|
return JSON.stringify(this.value);
|
|
}
|
|
}
|
|
toJSON() {
|
|
const k = this.key || ".";
|
|
if (this.props) {
|
|
return `${k}({${Object.keys(this.props).join(",")}})`;
|
|
}
|
|
return `${k}(${this.value})`;
|
|
}
|
|
}
|
|
|
|
export { diff };
|