metaforecast/node_modules/json2csv/lib/transforms/unwind.js
2021-01-12 13:43:41 +01:00

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;