Skip to content

Commit bc08321

Browse files
committed
refactor: expose diff function types
1 parent 622d237 commit bc08321

File tree

1 file changed

+49
-39
lines changed

1 file changed

+49
-39
lines changed

src/diff.ts

+49-39
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,77 @@
11
import { objectHash, HashOptions } from "./object-hash";
22

3-
export function diff(obj1: any, obj2: any, opts: HashOptions = {}): any[] {
3+
export function diff(
4+
obj1: any,
5+
obj2: any,
6+
opts: HashOptions = {}
7+
): DiffEntry[] {
48
const h1 = _toHashedObject(obj1, opts);
59
const h2 = _toHashedObject(obj2, opts);
610
return _diff(h1, h2, opts);
711
}
812

9-
function _diff(h1: HashEntry, h2: HashEntry, opts: HashOptions = {}): any[] {
13+
function _diff(
14+
h1: DiffHashedObject,
15+
h2: DiffHashedObject,
16+
opts: HashOptions = {}
17+
): DiffEntry[] {
1018
const diffs = [];
1119

1220
const allProps = new Set([
13-
...Object.keys(h1.$props || {}),
14-
...Object.keys(h2.$props || {}),
21+
...Object.keys(h1.props || {}),
22+
...Object.keys(h2.props || {}),
1523
]);
16-
if (h1.$props && h2.$props) {
24+
if (h1.props && h2.props) {
1725
for (const prop of allProps) {
18-
const p1 = h1.$props[prop];
19-
const p2 = h2.$props[prop];
26+
const p1 = h1.props[prop];
27+
const p2 = h2.props[prop];
2028
if (p1 && p2) {
21-
diffs.push(..._diff(h1.$props?.[prop], h2.$props?.[prop], opts));
22-
} else if (p1) {
23-
diffs.push(new DiffEntry("removed", p1));
24-
} else if (p2) {
25-
diffs.push(new DiffEntry("added", p2));
29+
diffs.push(..._diff(h1.props?.[prop], h2.props?.[prop], opts));
30+
} else if (p1 || p2) {
31+
diffs.push(
32+
new DiffEntry((p2 || p1).key, p1 ? "removed" : "added", p2, p1)
33+
);
2634
}
2735
}
2836
}
2937

30-
if (allProps.size === 0 && h1.$hash !== h2.$hash) {
31-
diffs.push(new DiffEntry("changed", h1, h2));
38+
if (allProps.size === 0 && h1.hash !== h2.hash) {
39+
diffs.push(new DiffEntry((h2 || h1).key, "changed", h2, h1));
3240
}
3341

3442
return diffs;
3543
}
3644

37-
function _toHashedObject(obj, opts: HashOptions, key = ""): HashEntry {
45+
function _toHashedObject(obj, opts: HashOptions, key = ""): DiffHashedObject {
3846
if (obj && typeof obj !== "object") {
39-
return new HashEntry(key, obj, objectHash(obj, opts));
47+
return new DiffHashedObject(key, obj, objectHash(obj, opts));
4048
}
41-
const $props: Record<string, HashEntry> = {};
49+
const props: Record<string, DiffHashedObject> = {};
4250
const hashes = [];
4351
for (const _key in obj) {
44-
$props[_key] = _toHashedObject(
52+
props[_key] = _toHashedObject(
4553
obj[_key],
4654
opts,
4755
key ? `${key}.${_key}` : _key
4856
);
49-
hashes.push($props[_key].$hash);
57+
hashes.push(props[_key].hash);
5058
}
51-
return new HashEntry(key, obj, `{${hashes.join(":")}}`, $props);
59+
return new DiffHashedObject(key, obj, `{${hashes.join(":")}}`, props);
5260
}
5361

5462
// --- Internal classes ---
5563

56-
class DiffEntry {
64+
export class DiffEntry {
5765
// eslint-disable-next-line no-useless-constructor
58-
private key: string;
5966
constructor(
67+
public key: string,
6068
public type: "changed" | "added" | "removed",
61-
public o1: HashEntry,
62-
public o2?: HashEntry
63-
) {
64-
this.key = o1.$key || ".";
69+
public newValue: DiffHashedObject,
70+
public oldValue?: DiffHashedObject
71+
) {}
72+
73+
toString() {
74+
return this.toJSON();
6575
}
6676

6777
toJSON() {
@@ -73,33 +83,33 @@ class DiffEntry {
7383
case "changed":
7484
return `[~] Changed ${
7585
this.key
76-
} from ${this.o1.toString()} to ${this.o2.toString()}`;
86+
} from ${this.oldValue.toString()} to ${this.newValue.toString()}`;
7787
}
7888
}
7989
}
8090

81-
class HashEntry {
91+
export class DiffHashedObject {
8292
// eslint-disable-next-line no-useless-constructor
8393
constructor(
84-
public $key: string,
85-
public $value: any,
86-
public $hash?: string,
87-
public $props?: Record<string, HashEntry>
94+
public key: string,
95+
public value: any,
96+
public hash?: string,
97+
public props?: Record<string, DiffHashedObject>
8898
) {}
8999

90100
toString() {
91-
if (!this.$props) {
92-
return JSON.stringify(this.$value);
101+
if (!this.props) {
102+
return JSON.stringify(this.value);
93103
} else {
94-
return `{${Object.keys(this.$props).join(",")}}`;
104+
return `{${Object.keys(this.props).join(",")}}`;
95105
}
96106
}
97107

98108
toJSON() {
99-
const k = this.$key || "<root>";
100-
if (this.$props) {
101-
return `${k}({${Object.keys(this.$props).join(",")}})`;
109+
const k = this.key || ".";
110+
if (this.props) {
111+
return `${k}({${Object.keys(this.props).join(",")}})`;
102112
}
103-
return `${k}(${this.$value})`;
113+
return `${k}(${this.value})`;
104114
}
105115
}

0 commit comments

Comments
 (0)