in src/core/system.js [356:440]
function systemExtend(dest={}, src={}) {
if(!isObject(dest)) {
return {}
}
if(!isObject(src)) {
return dest
}
// Wrap components
// Parses existing components in the system, and prepares them for wrapping via getComponents
if(src.wrapComponents) {
objMap(src.wrapComponents, (wrapperFn, key) => {
const ori = dest.components && dest.components[key]
if(ori && Array.isArray(ori)) {
dest.components[key] = ori.concat([wrapperFn])
delete src.wrapComponents[key]
} else if(ori) {
dest.components[key] = [ori, wrapperFn]
delete src.wrapComponents[key]
}
})
if(!Object.keys(src.wrapComponents).length) {
// only delete wrapComponents if we've matched all of our wrappers to components
// this handles cases where the component to wrap may be out of our scope,
// but a higher recursive `combinePlugins` call will be able to handle it.
delete src.wrapComponents
}
}
// Account for wrapActions, make it an array and append to it
// Modifies `src`
// 80% of this code is just safe traversal. We need to address that ( ie: use a lib )
const { statePlugins } = dest
if(isObject(statePlugins)) {
for(let namespace in statePlugins) {
const namespaceObj = statePlugins[namespace]
if(!isObject(namespaceObj)) {
continue
}
const { wrapActions, wrapSelectors } = namespaceObj
// process action wrapping
if (isObject(wrapActions)) {
for(let actionName in wrapActions) {
let action = wrapActions[actionName]
// This should only happen if dest is the first plugin, since invocations after that will ensure its an array
if(!Array.isArray(action)) {
action = [action]
wrapActions[actionName] = action // Put the value inside an array
}
if(src && src.statePlugins && src.statePlugins[namespace] && src.statePlugins[namespace].wrapActions && src.statePlugins[namespace].wrapActions[actionName]) {
src.statePlugins[namespace].wrapActions[actionName] = wrapActions[actionName].concat(src.statePlugins[namespace].wrapActions[actionName])
}
}
}
// process selector wrapping
if (isObject(wrapSelectors)) {
for(let selectorName in wrapSelectors) {
let selector = wrapSelectors[selectorName]
// This should only happen if dest is the first plugin, since invocations after that will ensure its an array
if(!Array.isArray(selector)) {
selector = [selector]
wrapSelectors[selectorName] = selector // Put the value inside an array
}
if(src && src.statePlugins && src.statePlugins[namespace] && src.statePlugins[namespace].wrapSelectors && src.statePlugins[namespace].wrapSelectors[selectorName]) {
src.statePlugins[namespace].wrapSelectors[selectorName] = wrapSelectors[selectorName].concat(src.statePlugins[namespace].wrapSelectors[selectorName])
}
}
}
}
}
return deepExtend(dest, src)
}