@@ -14,21 +14,19 @@ function getLeanDiff(
1414 showOnly : ObjectDiffOptions [ "showOnly" ] = DEFAULT_OBJECT_DIFF_OPTIONS . showOnly ,
1515) : ObjectDiff [ "diff" ] {
1616 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 } ) ;
2424 }
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 ;
3230}
3331
3432function getObjectStatus ( diff : ObjectDiff [ "diff" ] ) : OBJECT_STATUS {
@@ -50,34 +48,37 @@ function formatSingleObjectDiff(
5048 } ;
5149 }
5250 const diff : ObjectDiff [ "diff" ] = [ ] ;
53- Object . entries ( data ) . forEach ( ( [ property , value ] ) => {
51+
52+ for ( const [ property , value ] of Object . entries ( data ) ) {
5453 if ( isObject ( value ) ) {
5554 const subPropertiesDiff : Diff [ ] = [ ] ;
56- Object . entries ( value ) . forEach ( ( [ subProperty , subValue ] ) => {
55+ for ( const [ subProperty , subValue ] of Object . entries ( value ) ) {
5756 subPropertiesDiff . push ( {
5857 property : subProperty ,
5958 previousValue : status === OBJECT_STATUS . ADDED ? undefined : subValue ,
6059 currentValue : status === OBJECT_STATUS . ADDED ? subValue : undefined ,
6160 status,
6261 } ) ;
63- } ) ;
64- return diff . push ( {
62+ }
63+ diff . push ( {
6564 property,
6665 previousValue :
6766 status === OBJECT_STATUS . ADDED ? undefined : data [ property ] ,
6867 currentValue : status === OBJECT_STATUS . ADDED ? value : undefined ,
6968 status,
7069 diff : subPropertiesDiff ,
7170 } ) ;
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+ } ) ;
7279 }
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+
8182 if ( options . showOnly && options . showOnly . statuses . length > 0 ) {
8283 return {
8384 type : "object" ,
@@ -92,20 +93,6 @@ function formatSingleObjectDiff(
9293 } ;
9394}
9495
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-
10996function getValueStatus (
11097 previousValue : unknown ,
11198 nextValue : unknown ,
@@ -117,92 +104,61 @@ function getValueStatus(
117104 return OBJECT_STATUS . UPDATED ;
118105}
119106
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 = { } ,
147109 nextValue : Record < string , unknown > ,
148110 options ?: ObjectDiffOptions ,
149111) : 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 ,
161125 currentValue : undefined ,
162126 status : OBJECT_STATUS . DELETED ,
163127 } ) ;
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 ,
176134 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 ,
183136 } ) ;
137+ continue ;
184138 }
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 ,
190143 ) ;
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 ,
199156 currentValue : nextSubValue ,
200- status : getValueStatus ( previousMatch , nextSubValue , options ) ,
201- ...( ! ! subDiff && { diff : subDiff } ) ,
157+ status,
202158 } ) ;
203159 }
204- } ) ;
205- return subPropertiesDiff ;
160+ }
161+ return diff ;
206162}
207163
208164/**
@@ -234,66 +190,12 @@ export function getObjectDiff(
234190 if ( ! nextData ) {
235191 return formatSingleObjectDiff ( prevData , OBJECT_STATUS . DELETED , options ) ;
236192 }
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 ;
294196 return {
295197 type : "object" ,
296- status : getObjectStatus ( diff ) ,
297- diff,
198+ status,
199+ diff : showLeanDiff ? getLeanDiff ( diff , options . showOnly ) : diff ,
298200 } ;
299201}
0 commit comments