@@ -14,21 +14,19 @@ function getLeanDiff(
14
14
showOnly : ObjectDiffOptions [ "showOnly" ] = DEFAULT_OBJECT_DIFF_OPTIONS . showOnly ,
15
15
) : ObjectDiff [ "diff" ] {
16
16
const { statuses, granularity } = showOnly ;
17
- return diff . reduce (
18
- ( acc , value ) => {
19
- if ( granularity === GRANULARITY . DEEP && value . diff ) {
20
- const leanDiff = getLeanDiff ( value . diff , showOnly ) ;
21
- if ( leanDiff . length > 0 ) {
22
- return [ ... acc , { ... value , diff : leanDiff } ] ;
23
- }
17
+ const res : ObjectDiff [ " diff" ] = [ ] ;
18
+ for ( let i = 0 ; i < diff . length ; i ++ ) {
19
+ const value = diff [ i ] ;
20
+ if ( granularity === GRANULARITY . DEEP && value . diff ) {
21
+ const leanDiff = getLeanDiff ( value . diff , showOnly ) ;
22
+ if ( leanDiff . length > 0 ) {
23
+ res . push ( { ... value , diff : leanDiff } ) ;
24
24
}
25
- if ( statuses . includes ( value . status ) ) {
26
- return [ ...acc , value ] ;
27
- }
28
- return acc ;
29
- } ,
30
- [ ] as ObjectDiff [ "diff" ] ,
31
- ) ;
25
+ } else if ( statuses . includes ( value . status ) ) {
26
+ res . push ( value ) ;
27
+ }
28
+ }
29
+ return res ;
32
30
}
33
31
34
32
function getObjectStatus ( diff : ObjectDiff [ "diff" ] ) : OBJECT_STATUS {
@@ -50,34 +48,37 @@ function formatSingleObjectDiff(
50
48
} ;
51
49
}
52
50
const diff : ObjectDiff [ "diff" ] = [ ] ;
53
- Object . entries ( data ) . forEach ( ( [ property , value ] ) => {
51
+
52
+ for ( const [ property , value ] of Object . entries ( data ) ) {
54
53
if ( isObject ( value ) ) {
55
54
const subPropertiesDiff : Diff [ ] = [ ] ;
56
- Object . entries ( value ) . forEach ( ( [ subProperty , subValue ] ) => {
55
+ for ( const [ subProperty , subValue ] of Object . entries ( value ) ) {
57
56
subPropertiesDiff . push ( {
58
57
property : subProperty ,
59
58
previousValue : status === OBJECT_STATUS . ADDED ? undefined : subValue ,
60
59
currentValue : status === OBJECT_STATUS . ADDED ? subValue : undefined ,
61
60
status,
62
61
} ) ;
63
- } ) ;
64
- return diff . push ( {
62
+ }
63
+ diff . push ( {
65
64
property,
66
65
previousValue :
67
66
status === OBJECT_STATUS . ADDED ? undefined : data [ property ] ,
68
67
currentValue : status === OBJECT_STATUS . ADDED ? value : undefined ,
69
68
status,
70
69
diff : subPropertiesDiff ,
71
70
} ) ;
71
+ } else {
72
+ diff . push ( {
73
+ property,
74
+ previousValue :
75
+ status === OBJECT_STATUS . ADDED ? undefined : data [ property ] ,
76
+ currentValue : status === OBJECT_STATUS . ADDED ? value : undefined ,
77
+ status,
78
+ } ) ;
72
79
}
73
- return diff . push ( {
74
- property,
75
- previousValue :
76
- status === OBJECT_STATUS . ADDED ? undefined : data [ property ] ,
77
- currentValue : status === OBJECT_STATUS . ADDED ? value : undefined ,
78
- status,
79
- } ) ;
80
- } ) ;
80
+ }
81
+
81
82
if ( options . showOnly && options . showOnly . statuses . length > 0 ) {
82
83
return {
83
84
type : "object" ,
@@ -92,20 +93,6 @@ function formatSingleObjectDiff(
92
93
} ;
93
94
}
94
95
95
- function getPreviousMatch (
96
- previousValue : unknown | undefined ,
97
- nextSubProperty : unknown ,
98
- options ?: ObjectDiffOptions ,
99
- ) : unknown | undefined {
100
- if ( ! previousValue ) {
101
- return undefined ;
102
- }
103
- const previousMatch = Object . entries ( previousValue ) . find ( ( [ subPreviousKey ] ) =>
104
- isEqual ( subPreviousKey , nextSubProperty , options ) ,
105
- ) ;
106
- return previousMatch ? previousMatch [ 1 ] : undefined ;
107
- }
108
-
109
96
function getValueStatus (
110
97
previousValue : unknown ,
111
98
nextValue : unknown ,
@@ -117,92 +104,61 @@ function getValueStatus(
117
104
return OBJECT_STATUS . UPDATED ;
118
105
}
119
106
120
- function getPropertyStatus ( subPropertiesDiff : Diff [ ] ) : OBJECT_STATUS {
121
- return subPropertiesDiff . some (
122
- ( property ) => property . status !== OBJECT_STATUS . EQUAL ,
123
- )
124
- ? OBJECT_STATUS . UPDATED
125
- : OBJECT_STATUS . EQUAL ;
126
- }
127
-
128
- function getDeletedProperties (
129
- previousValue : Record < string , unknown > | undefined ,
130
- nextValue : Record < string , unknown > ,
131
- ) : { property : string ; value : unknown } [ ] | undefined {
132
- if ( ! previousValue ) return undefined ;
133
- const prevKeys = Object . keys ( previousValue ) ;
134
- const nextKeys = Object . keys ( nextValue ) ;
135
- const deletedKeys = prevKeys . filter ( ( prevKey ) => ! nextKeys . includes ( prevKey ) ) ;
136
- if ( deletedKeys . length > 0 ) {
137
- return deletedKeys . map ( ( deletedKey ) => ( {
138
- property : deletedKey ,
139
- value : previousValue [ deletedKey ] ,
140
- } ) ) ;
141
- }
142
- return undefined ;
143
- }
144
-
145
- function getSubPropertiesDiff (
146
- previousValue : Record < string , unknown > | undefined ,
107
+ function getDiff (
108
+ previousValue : Record < string , unknown > | undefined = { } ,
147
109
nextValue : Record < string , unknown > ,
148
110
options ?: ObjectDiffOptions ,
149
111
) : Diff [ ] {
150
- const subPropertiesDiff : Diff [ ] = [ ] ;
151
- let subDiff : Diff [ ] ;
152
- const deletedMainSubProperties = getDeletedProperties (
153
- previousValue ,
154
- nextValue ,
155
- ) ;
156
- if ( deletedMainSubProperties ) {
157
- deletedMainSubProperties . forEach ( ( deletedProperty ) => {
158
- subPropertiesDiff . push ( {
159
- property : deletedProperty . property ,
160
- previousValue : deletedProperty . value ,
112
+ const diff : Diff [ ] = [ ] ;
113
+ const allKeys = new Set ( [
114
+ ...Object . keys ( previousValue ) ,
115
+ ...Object . keys ( nextValue ) ,
116
+ ] ) ;
117
+
118
+ for ( const property of allKeys ) {
119
+ const prevSubValue = previousValue [ property ] ;
120
+ const nextSubValue = nextValue [ property ] ;
121
+ if ( ! ( property in nextValue ) ) {
122
+ diff . push ( {
123
+ property,
124
+ previousValue : prevSubValue ,
161
125
currentValue : undefined ,
162
126
status : OBJECT_STATUS . DELETED ,
163
127
} ) ;
164
- } ) ;
165
- }
166
- Object . entries ( nextValue ) . forEach ( ( [ nextSubProperty , nextSubValue ] ) => {
167
- const previousMatch = getPreviousMatch (
168
- previousValue ,
169
- nextSubProperty ,
170
- options ,
171
- ) ;
172
- if ( ! previousMatch ) {
173
- return subPropertiesDiff . push ( {
174
- property : nextSubProperty ,
175
- previousValue : previousMatch ,
128
+ continue ;
129
+ }
130
+ if ( ! ( property in previousValue ) ) {
131
+ diff . push ( {
132
+ property,
133
+ previousValue : undefined ,
176
134
currentValue : nextSubValue ,
177
- status :
178
- ! previousValue || ! ( nextSubProperty in previousValue )
179
- ? OBJECT_STATUS . ADDED
180
- : previousMatch === nextSubValue
181
- ? OBJECT_STATUS . EQUAL
182
- : OBJECT_STATUS . UPDATED ,
135
+ status : OBJECT_STATUS . ADDED ,
183
136
} ) ;
137
+ continue ;
184
138
}
185
- if ( isObject ( nextSubValue ) ) {
186
- const data : Diff [ ] = getSubPropertiesDiff (
187
- previousMatch as Record < string , unknown > ,
188
- nextSubValue ,
189
- options ,
139
+ if ( isObject ( nextSubValue ) && isObject ( prevSubValue ) ) {
140
+ const subDiff = getDiff ( prevSubValue , nextSubValue , options ) ;
141
+ const isUpdated = subDiff . some (
142
+ ( entry ) => entry . status !== OBJECT_STATUS . EQUAL ,
190
143
) ;
191
- if ( data && data . length > 0 ) {
192
- subDiff = data ;
193
- }
194
- }
195
- if ( previousMatch ) {
196
- subPropertiesDiff . push ( {
197
- property : nextSubProperty ,
198
- previousValue : previousMatch ,
144
+ diff . push ( {
145
+ property,
146
+ previousValue : prevSubValue ,
147
+ currentValue : nextSubValue ,
148
+ status : isUpdated ? OBJECT_STATUS . UPDATED : OBJECT_STATUS . EQUAL ,
149
+ ...( isUpdated && { diff : subDiff } ) ,
150
+ } ) ;
151
+ } else {
152
+ const status = getValueStatus ( prevSubValue , nextSubValue , options ) ;
153
+ diff . push ( {
154
+ property,
155
+ previousValue : prevSubValue ,
199
156
currentValue : nextSubValue ,
200
- status : getValueStatus ( previousMatch , nextSubValue , options ) ,
201
- ...( ! ! subDiff && { diff : subDiff } ) ,
157
+ status,
202
158
} ) ;
203
159
}
204
- } ) ;
205
- return subPropertiesDiff ;
160
+ }
161
+ return diff ;
206
162
}
207
163
208
164
/**
@@ -234,66 +190,12 @@ export function getObjectDiff(
234
190
if ( ! nextData ) {
235
191
return formatSingleObjectDiff ( prevData , OBJECT_STATUS . DELETED , options ) ;
236
192
}
237
- const diff : ObjectDiff [ "diff" ] = [ ] ;
238
- Object . entries ( nextData ) . forEach ( ( [ nextProperty , nextValue ] ) => {
239
- const previousValue = prevData [ nextProperty ] ;
240
- if ( ! previousValue ) {
241
- return diff . push ( {
242
- property : nextProperty ,
243
- previousValue,
244
- currentValue : nextValue ,
245
- status : ! ( nextProperty in prevData )
246
- ? OBJECT_STATUS . ADDED
247
- : previousValue === nextValue
248
- ? OBJECT_STATUS . EQUAL
249
- : OBJECT_STATUS . UPDATED ,
250
- } ) ;
251
- }
252
- if ( isObject ( nextValue ) ) {
253
- const subPropertiesDiff : Diff [ ] = getSubPropertiesDiff (
254
- previousValue as Record < string , unknown > ,
255
- nextValue ,
256
- options ,
257
- ) ;
258
- const subPropertyStatus = getPropertyStatus ( subPropertiesDiff ) ;
259
- return diff . push ( {
260
- property : nextProperty ,
261
- previousValue,
262
- currentValue : nextValue ,
263
- status : subPropertyStatus ,
264
- ...( subPropertyStatus !== OBJECT_STATUS . EQUAL && {
265
- diff : subPropertiesDiff ,
266
- } ) ,
267
- } ) ;
268
- }
269
- return diff . push ( {
270
- property : nextProperty ,
271
- previousValue,
272
- currentValue : nextValue ,
273
- status : getValueStatus ( previousValue , nextValue , options ) ,
274
- } ) ;
275
- } ) ;
276
- const deletedProperties = getDeletedProperties ( prevData , nextData ) ;
277
- if ( deletedProperties ) {
278
- deletedProperties . forEach ( ( deletedProperty ) => {
279
- diff . push ( {
280
- property : deletedProperty . property ,
281
- previousValue : deletedProperty . value ,
282
- currentValue : undefined ,
283
- status : OBJECT_STATUS . DELETED ,
284
- } ) ;
285
- } ) ;
286
- }
287
- if ( options . showOnly && options . showOnly . statuses . length > 0 ) {
288
- return {
289
- type : "object" ,
290
- status : getObjectStatus ( diff ) ,
291
- diff : getLeanDiff ( diff , options . showOnly ) ,
292
- } ;
293
- }
193
+ const diff : ObjectDiff [ "diff" ] = getDiff ( prevData , nextData , options ) ;
194
+ const status = getObjectStatus ( diff ) ;
195
+ const showLeanDiff = ( options ?. showOnly ?. statuses ?. length || 0 ) > 0 ;
294
196
return {
295
197
type : "object" ,
296
- status : getObjectStatus ( diff ) ,
297
- diff,
198
+ status,
199
+ diff : showLeanDiff ? getLeanDiff ( diff , options . showOnly ) : diff ,
298
200
} ;
299
201
}
0 commit comments