import { cloneValue , mergeValues } from "./history" ; import { EntryPropertyType , FormatBEntry , FormatBGroup , FormatBKeyValueObject , FormatBVault } from "../../types" ; function cloneEntry ( entry ) { return { id : entry . id , p : Object . assign ( { } , entry . p ) , a : Object . assign ( { } , entry . a ) , g : entry . g } ; } function cloneGroup ( group ) { return { id : group . id , t : group . t , g : group . g , a : Object . assign ( { } , group . a ) } ; } function mergeProperties ( propsA , propsB , type ) { const allKeys = [ ... new Set ( [ ... Object . keys ( propsA ) , ... Object . keys ( propsB ) ] ) ] ; return allKeys . reduce ( ( output , nextKey ) => { if ( ( propsA [ nextKey ] && ! propsB [ nextKey ] ) || ( ! propsA [ nextKey ] && propsB [ nextKey ] ) ) { output [ nextKey ] = cloneValue ( propsA [ nextKey ] || propsB [ nextKey ] ) ; } else { output [ nextKey ] = mergeValues ( propsA [ nextKey ] , propsB [ nextKey ] , type ) ; } return output ; } , { } ) ; } export function mergeRawVaults ( base , incoming ) { const newVault = { id : base . id , a : mergeProperties ( base . a , incoming . a , EntryPropertyType . Attribute ) , g : [ ] , e : [ ] , c : base . c } ; const uniqueGroupsBase = base . g . filter ( group => ! incoming . g . find ( inGroup => inGroup . id === group . id ) ) ; const uniqueGroupsIncoming = incoming . g . filter ( group => ! base . g . find ( baseGroup => baseGroup . id === group . id ) ) ; [ ... uniqueGroupsBase , ... uniqueGroupsIncoming ] . forEach ( group => { newVault . g . push ( cloneGroup ( group ) ) ; } ) ; base . g . forEach ( baseGroup => { if ( uniqueGroupsBase . indexOf ( baseGroup ) >= 0 ) return ; const incomingGroup = incoming . g . find ( ing => ing . id === baseGroup . id ) ; const newGroup = cloneGroup ( incomingGroup ) ; newGroup . a = mergeProperties ( baseGroup . a , incomingGroup . a , EntryPropertyType . Attribute ) ; newVault . g . push ( newGroup ) ; } ) ; const uniqueEntriesBase = base . e . filter ( entry => ! incoming . e . find ( inEntry => inEntry . id === entry . id ) ) ; const uniqueEntriesIncoming = incoming . e . filter ( entry => ! base . e . find ( baseEntry => baseEntry . id === entry . id ) ) ; [ ... uniqueEntriesBase , ... uniqueEntriesIncoming ] . forEach ( entry => { newVault . e . push ( cloneEntry ( entry ) ) ; } ) ; base . e . forEach ( baseEntry => { if ( uniqueEntriesBase . indexOf ( baseEntry ) >= 0 ) return ; const incomingEntry = incoming . e . find ( ing => ing . id === baseEntry . id ) ; const newEntry = cloneEntry ( incomingEntry ) ; newEntry . p = mergeProperties ( baseEntry . p , incomingEntry . p , EntryPropertyType . Property ) ; newEntry . a = mergeProperties ( baseEntry . a , incomingEntry . a , EntryPropertyType . Attribute ) ; newVault . e . push ( newEntry ) ; } ) ; return newVault ; }