import { NodePathSegmentFormatter } from "../types" ; import { WalkNode } from "../node" ; import { apply } from "./apply" ; type NodeComparison = { path : string ; a ? : any ; b ? : any ; hasDifference : boolean ; difference ? : 'added' | 'removed' | { before : any ; after : any ; } ; } ; const defaultFormatter = ( { key , isArrayMember : isArr } ) => isArr ? `[${ key }]` : `.${ key }` ; export function compare ( a , b , leavesOnly = false , formatter = defaultFormatter ) { const aNodes = { } ; const bNodes = { } ; apply ( a , n => aNodes [ n . getPath ( formatter ) ] = n ) ; apply ( b , n => bNodes [ n . getPath ( formatter ) ] = n ) ; return [ ... new Set < string > ( [ ... Object . keys ( aNodes ) , ... Object . keys ( bNodes ) ] ) ] . filter ( key => ! leavesOnly || ( aNodes [ key ] || bNodes [ key ] ) ! . nodeType === 'value' ) . map ( key => { const aNode = aNodes [ key ] ; const bNode = bNodes [ key ] ; const removed = aNode && ! bNode ; const added = bNode && ! aNode ; const changed = aNode && bNode && ! Object . is ( aNode . val , bNode . val ) ; let delta = { path : key , hasDifference : removed || added || changed } ; if ( added ) { delta . difference = 'added' ; delta . b = bNode ?. val ; } else if ( removed ) { delta . difference = 'removed' ; delta . a = aNode ?. val ; } else if ( changed ) { delta . difference = { before : aNode ?. val , after : bNode ?. val } ; delta . a = aNode ?. val ; delta . b = bNode ?. val ; } return delta ; } ) ; }