UNPKG

@sap/cds-dk

Version:

Command line client and development toolkit for the SAP Cloud Application Programming Model

75 lines (70 loc) 2.76 kB
const { elementsSorter } = require('./as-json') /** * Serializes the given JSON data to CSV format * @param {object} data JSON data to serialize * @param {object} csn the model * @param {{ headerOnly: boolean, separator: boolean }} options * @returns {Promise<string>} CSV string */ module.exports = async (data={}, csn, { headerOnly=false, separator=',' }={}) => { // We might need multiple passes if data for associations/compositions is created on the fly. // So loop as long as there is some non-string data left. while (Object.values(data).some(d => typeof d === 'object')) { Object.entries(data) .filter(([_, value]) => typeof value === 'object') .map(([name]) => csn.definitions[name]) .forEach(entity => { const entityData = data[entity.name] const header = [] const records = [] for (let i = 0; i < entityData.length; i++) { let record = [] const elements = Object.values(entity.elements).sort(elementsSorter(csn)) for (const element of elements) { const name = element.name let value = entityData[i][name] if (value === undefined) continue if (element._type === 'cds.Composition') { data[element.target] = value // Add object for a new entity. Next pass will process it. } else if (element._type === 'cds.Association') { if (element.on) { continue // skip unmanaged associations with explicit on condition } if (i === 0) { header.push(...Object.keys(value).map(foreignKey => name + '_' + foreignKey)) } record.push(...Object.values(value)) } else if (element.is_struct && element.type !== 'cds.Map') { if (i === 0) { header.push(...Object.keys(value).map(structField => name + '_' + structField)) } record.push(...Object.values(value)) } else { if (i === 0) header.push(name) if (Array.isArray(value) || typeof value === 'object') { // `array of`/`many` and `cds.Map` value = JSON.stringify(value) } value = escape(value) record.push(value) } } records.push(record.join(separator)) } let res = header.join(separator) if (!headerOnly) res += '\n' + records.join('\n') data[entity.name] = res function escape(value) { if (typeof value === 'string' && (value.includes('"') || value.includes(separator))) { return `"${value.replace(/"/g, '""')}"` // escape double quotes, then quote the value } return value } }) } return data }