63 lines
2.0 KiB
JavaScript
63 lines
2.0 KiB
JavaScript
|
|
||
|
const lodashGet = require('lodash.get');
|
||
|
const { setProp, unsetProp, flattenReducer } = require('../utils');
|
||
|
|
||
|
function getUnwindablePaths(obj, currentPath) {
|
||
|
return Object.keys(obj).reduce((unwindablePaths, key) => {
|
||
|
const newPath = currentPath ? `${currentPath}.${key}` : key;
|
||
|
const value = obj[key];
|
||
|
|
||
|
if (typeof value === 'object'
|
||
|
&& value !== null
|
||
|
&& !Array.isArray(value)
|
||
|
&& Object.prototype.toString.call(value.toJSON) !== '[object Function]'
|
||
|
&& Object.keys(value).length) {
|
||
|
unwindablePaths = unwindablePaths.concat(getUnwindablePaths(value, newPath));
|
||
|
} else if (Array.isArray(value)) {
|
||
|
unwindablePaths.push(newPath);
|
||
|
unwindablePaths = unwindablePaths.concat(value
|
||
|
.map(arrObj => getUnwindablePaths(arrObj, newPath))
|
||
|
.reduce(flattenReducer, [])
|
||
|
.filter((item, index, arr) => arr.indexOf(item) !== index));
|
||
|
}
|
||
|
|
||
|
return unwindablePaths;
|
||
|
}, []);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Performs the unwind recursively in specified sequence
|
||
|
*
|
||
|
* @param {String[]} unwindPaths The paths as strings to be used to deconstruct the array
|
||
|
* @returns {Object => Array} Array of objects containing all rows after unwind of chosen paths
|
||
|
*/
|
||
|
function unwind({ paths = undefined, blankOut = false } = {}) {
|
||
|
function unwindReducer(rows, unwindPath) {
|
||
|
return rows
|
||
|
.map(row => {
|
||
|
const unwindArray = lodashGet(row, unwindPath);
|
||
|
|
||
|
if (!Array.isArray(unwindArray)) {
|
||
|
return row;
|
||
|
}
|
||
|
|
||
|
if (!unwindArray.length) {
|
||
|
return unsetProp(row, unwindPath);
|
||
|
}
|
||
|
|
||
|
return unwindArray.map((unwindRow, index) => {
|
||
|
const clonedRow = (blankOut && index > 0)
|
||
|
? {}
|
||
|
: row;
|
||
|
|
||
|
return setProp(clonedRow, unwindPath, unwindRow);
|
||
|
});
|
||
|
})
|
||
|
.reduce(flattenReducer, []);
|
||
|
}
|
||
|
|
||
|
paths = Array.isArray(paths) ? paths : (paths ? [paths] : undefined);
|
||
|
return dataRow => (paths || getUnwindablePaths(dataRow)).reduce(unwindReducer, [dataRow]);
|
||
|
}
|
||
|
|
||
|
module.exports = unwind;
|