import { keys , isFunction , difference , filter , union , pick , each , assign , isEqual } from 'lodash' ; export interface IDiffObject { removed : string [ ] ; added : string [ ] ; changed : string [ ] ; keys : string [ ] ; } param { string } key returns { boolean } const filterPrivateAndMethods = function ( obj ) { return function ( key ) { if ( isFunction ( obj [ key ] ) ) return false ; if ( key . charAt ( 0 ) === '$' ) return false ; return key . charAt ( 0 ) !== '_' ; } ; } ; export function applyDiff ( target , source ) { const diff = { removed : [ ] , added : [ ] , changed : [ ] , keys : [ ] , } ; const targetKeys = keys ( target ) . filter ( filterPrivateAndMethods ( target ) ) ; const sourceKeys = keys ( source ) . filter ( filterPrivateAndMethods ( source ) ) ; diff . removed = difference ( targetKeys , sourceKeys ) ; diff . added = difference ( sourceKeys , targetKeys ) ; diff . changed = filter ( sourceKeys , ( key ) => ! isEqual ( target [ key ] , source [ key ] ) ) ; diff . keys = union ( diff . changed , diff . removed , diff . added ) ; each ( diff . removed , ( key ) => { delete target [ key ] ; } ) ; assign ( target , pick ( source , diff . changed ) ) ; assign ( target , pick ( source , diff . added ) ) ; return diff ; }