@peter.naydenov/dt-queries
Version:
Set of DT-toolbox query functions
142 lines (130 loc) • 7.82 kB
JavaScript
/**
* Combine: Preserve all values from incoming and original data
* - use all data structures from the incoming data;
* - combine original and incoming values into arrays;
* - incoming data structure has a priority;
* - arrays extend existing array with incoming values;
*/
function combine ( storage, inData ) {
const crumbs = [];
storage.look ( ({ name, flatData, breadcrumbs, links, next }) => {
let inRow;
const isArray = flatData instanceof Array;
crumbs.push ( breadcrumbs )
if ( isArray ) {
let
arr = []
, linkArr = []
;
flatData.forEach ( (el,i) => { // Check for extra incoming structures
const
checkIndex = `${breadcrumbs}/${i}`
, extraRow = inData.index( checkIndex )
;
if ( !extraRow ) {
arr.push ( el )
}
else {
const
extraFlat = extraRow[1]
, isExtraArray = extraFlat instanceof Array
;
if ( isExtraArray ) extraFlat.push ( el )
else extraFlat['___history'] = el
storage.set ( i, extraFlat )
crumbs.push ( checkIndex )
linkArr.push ( checkIndex )
}
})
inRow = inData.index ( breadcrumbs )
if ( !inRow ) {
storage.set ( name, arr )
// Check if parent has property with this name:
let tmp = breadcrumbs.split( '/' );
tmp.pop ()
let
parent = tmp.join ( '/' )
, propOwner = inData.index ( parent )[1]
, prop = propOwner[name]
;
if ( prop ) storage.push ( name, prop )
}
else {
let isInRowArray = inRow[1] instanceof Array;
if ( isInRowArray ) {
inRow[1].forEach ( el => {
if ( !arr.includes(el) ) arr.push ( el )
})
storage.set ( name, arr )
}
else {
arr.push ( inRow[1] )
}
}
if ( breadcrumbs.includes('/')) storage.connect ([breadcrumbs])
storage.connect ( linkArr )
return next ()
} // if isArray
let
entries = Object.entries ( flatData )
, entryKeys = Object.keys ( flatData )
;
storage.set ( name, {})
if ( breadcrumbs.includes('/')) storage.connect ([breadcrumbs])
inRow = inData.index ( breadcrumbs )
entries.forEach ( ([k,v]) => {
const
checkKey = `${breadcrumbs}/${k}`
, extraData = inData.index ( checkKey )
;
if ( !extraData ) {
const
[ ,updateObject ] = inRow ? inRow : []
, update = updateObject[k]
;
if ( update ) {
storage.set ( k, [ v, update ])
storage.connect ([checkKey])
crumbs.push ( checkKey )
}
else {
storage.save ( name, k , v )
}
}
else {
const isExtraArray = extraData[1] instanceof Array;
if ( isExtraArray ) {
storage.set ( k, [])
storage.push ( k, v )
extraData[1].forEach ( el => storage.push (k,el) )
}
else {
storage.set ( k, extraData[1] )
storage.save ( k, '___history', v )
}
storage.connect ([checkKey])
}
})
// Fulfill key/values that only incoming objects has
inData.query ( inStorage => {
let linkProps = links.map ( ([,child]) => child );
inStorage.look (({key,value, breadcrumbs:inBreadcrumbs, next }) => {
if ( inBreadcrumbs !== breadcrumbs ) return next () // Scan corresponding objects only
if ( linkProps.includes(key) ) return
if ( !entryKeys.includes(key) && key!= null ) storage.save ( name, key, value )
})
})
return next ()
}) // look storage
inData.query ( inStorage => { // Fulfill the new structures from incoming data
inStorage.look (({ name, flatData, breadcrumbs, next }) => {
if ( !crumbs.includes(breadcrumbs) ) {
storage.set ( name, flatData )
storage.connect([breadcrumbs])
return next ()
}
}) // look inStorage
}) // query inData
} // combine func.
export default combine