1
1
import { objectHash , HashOptions } from "./object-hash" ;
2
2
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 [ ] {
4
8
const h1 = _toHashedObject ( obj1 , opts ) ;
5
9
const h2 = _toHashedObject ( obj2 , opts ) ;
6
10
return _diff ( h1 , h2 , opts ) ;
7
11
}
8
12
9
- function _diff ( h1 : HashEntry , h2 : HashEntry , opts : HashOptions = { } ) : any [ ] {
13
+ function _diff (
14
+ h1 : DiffHashedObject ,
15
+ h2 : DiffHashedObject ,
16
+ opts : HashOptions = { }
17
+ ) : DiffEntry [ ] {
10
18
const diffs = [ ] ;
11
19
12
20
const allProps = new Set ( [
13
- ...Object . keys ( h1 . $ props || { } ) ,
14
- ...Object . keys ( h2 . $ props || { } ) ,
21
+ ...Object . keys ( h1 . props || { } ) ,
22
+ ...Object . keys ( h2 . props || { } ) ,
15
23
] ) ;
16
- if ( h1 . $ props && h2 . $ props) {
24
+ if ( h1 . props && h2 . props ) {
17
25
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 ] ;
20
28
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
+ ) ;
26
34
}
27
35
}
28
36
}
29
37
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 ) ) ;
32
40
}
33
41
34
42
return diffs ;
35
43
}
36
44
37
- function _toHashedObject ( obj , opts : HashOptions , key = "" ) : HashEntry {
45
+ function _toHashedObject ( obj , opts : HashOptions , key = "" ) : DiffHashedObject {
38
46
if ( obj && typeof obj !== "object" ) {
39
- return new HashEntry ( key , obj , objectHash ( obj , opts ) ) ;
47
+ return new DiffHashedObject ( key , obj , objectHash ( obj , opts ) ) ;
40
48
}
41
- const $ props : Record < string , HashEntry > = { } ;
49
+ const props : Record < string , DiffHashedObject > = { } ;
42
50
const hashes = [ ] ;
43
51
for ( const _key in obj ) {
44
- $ props[ _key ] = _toHashedObject (
52
+ props [ _key ] = _toHashedObject (
45
53
obj [ _key ] ,
46
54
opts ,
47
55
key ? `${ key } .${ _key } ` : _key
48
56
) ;
49
- hashes . push ( $ props[ _key ] . $ hash) ;
57
+ hashes . push ( props [ _key ] . hash ) ;
50
58
}
51
- return new HashEntry ( key , obj , `{${ hashes . join ( ":" ) } }` , $ props) ;
59
+ return new DiffHashedObject ( key , obj , `{${ hashes . join ( ":" ) } }` , props ) ;
52
60
}
53
61
54
62
// --- Internal classes ---
55
63
56
- class DiffEntry {
64
+ export class DiffEntry {
57
65
// eslint-disable-next-line no-useless-constructor
58
- private key : string ;
59
66
constructor (
67
+ public key : string ,
60
68
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 ( ) ;
65
75
}
66
76
67
77
toJSON ( ) {
@@ -73,33 +83,33 @@ class DiffEntry {
73
83
case "changed" :
74
84
return `[~] Changed ${
75
85
this . key
76
- } from ${ this . o1 . toString ( ) } to ${ this . o2 . toString ( ) } `;
86
+ } from ${ this . oldValue . toString ( ) } to ${ this . newValue . toString ( ) } `;
77
87
}
78
88
}
79
89
}
80
90
81
- class HashEntry {
91
+ export class DiffHashedObject {
82
92
// eslint-disable-next-line no-useless-constructor
83
93
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 >
88
98
) { }
89
99
90
100
toString ( ) {
91
- if ( ! this . $ props) {
92
- return JSON . stringify ( this . $ value) ;
101
+ if ( ! this . props ) {
102
+ return JSON . stringify ( this . value ) ;
93
103
} else {
94
- return `{${ Object . keys ( this . $ props) . join ( "," ) } }` ;
104
+ return `{${ Object . keys ( this . props ) . join ( "," ) } }` ;
95
105
}
96
106
}
97
107
98
108
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 ( "," ) } })` ;
102
112
}
103
- return `${ k } (${ this . $ value} )` ;
113
+ return `${ k } (${ this . value } )` ;
104
114
}
105
115
}
0 commit comments