UNPKG

json2csv

Version:
60 lines (50 loc) 1.99 kB
const lodashGet = require('lodash.get'); const { setProp, unsetProp } = 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 .flatMap(arrObj => getUnwindablePaths(arrObj, newPath)) .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 .flatMap(row => { const unwindArray = lodashGet(row, unwindPath); if (!Array.isArray(unwindArray)) { return row; } if (!unwindArray.length) { return unsetProp(row, unwindPath); } const baseNewRow = blankOut ? {} : row; const [firstRow, ...restRows] = unwindArray; return [ setProp(row, unwindPath, firstRow), ...restRows.map(unwindRow => setProp(baseNewRow, unwindPath, unwindRow)) ]; }); } paths = Array.isArray(paths) ? paths : (paths ? [paths] : undefined); return dataRow => (paths || getUnwindablePaths(dataRow)).reduce(unwindReducer, [dataRow]); } module.exports = unwind;