All checks were successful
farmcontrol/farmcontrol-api/pipeline/head This commit looks good
55 lines
1.7 KiB
JavaScript
55 lines
1.7 KiB
JavaScript
/**
|
|
* Convert a value to a CSV cell-friendly format.
|
|
* Primitives pass through; objects/arrays are stringified; dates are formatted.
|
|
*/
|
|
function toCsvValue(val) {
|
|
if (val === null || val === undefined) return '';
|
|
if (val instanceof Date) return val.toISOString();
|
|
if (typeof val === 'number' || typeof val === 'boolean') return String(val);
|
|
if (typeof val === 'string') return val;
|
|
if (typeof val === 'object') {
|
|
if (Array.isArray(val)) return val.map(toCsvValue).join(', ');
|
|
return JSON.stringify(val);
|
|
}
|
|
return String(val);
|
|
}
|
|
|
|
/**
|
|
* Escape a CSV field per RFC 4180: wrap in double quotes, escape internal quotes by doubling.
|
|
*/
|
|
function escapeCsvField(str) {
|
|
if (str == null) return '""';
|
|
const s = String(str);
|
|
if (s.includes('"') || s.includes(',') || s.includes('\n') || s.includes('\r')) {
|
|
return '"' + s.replace(/"/g, '""') + '"';
|
|
}
|
|
return s;
|
|
}
|
|
|
|
/**
|
|
* Generate a CSV buffer from tabular data.
|
|
* @param {Array<Object>} data - Array of row objects (keys = column headers)
|
|
* @param {Object} options - Options
|
|
* @param {string[]} [options.columnOrder] - Optional column order (uses Object.keys of first row if not provided)
|
|
* @returns {Buffer} CSV file as buffer
|
|
*/
|
|
export function generateCsvTable(data, options = {}) {
|
|
const { columnOrder } = options;
|
|
|
|
if (!data || data.length === 0) {
|
|
return Buffer.from('', 'utf8');
|
|
}
|
|
|
|
const keys = columnOrder || Object.keys(data[0]).filter((k) => !k.startsWith('@'));
|
|
const headerRow = keys.map((k) => escapeCsvField(k)).join(',');
|
|
const lines = [headerRow];
|
|
|
|
for (const row of data) {
|
|
const values = keys.map((key) => escapeCsvField(toCsvValue(row[key])));
|
|
lines.push(values.join(','));
|
|
}
|
|
|
|
const csv = lines.join('\n');
|
|
return Buffer.from(csv, 'utf8');
|
|
}
|