/** * CSV formatter * Produces a single CSV line: timestamp,measurement,field1=val1,field2=val2,... * * Values are escaped if they contain commas or quotes. * * @param {string} measurement - The measurement name (e.g. node name) * @param {object} metadata - { fields, tags } * - fields: key/value pairs of changed data points * - tags: flat key/value string pairs (included as columns) * @returns {string} CSV-formatted line */ function format(measurement, metadata) { const { fields, tags } = metadata; const timestamp = new Date().toISOString(); const parts = [escapeCSV(timestamp), escapeCSV(measurement)]; // Append tags first, then fields if (tags) { for (const key of Object.keys(tags).sort()) { parts.push(escapeCSV(`${key}=${tags[key]}`)); } } for (const key of Object.keys(fields).sort()) { parts.push(escapeCSV(`${key}=${fields[key]}`)); } return parts.join(','); } /** * Escapes a value for safe inclusion in a CSV field. * Wraps in double quotes if the value contains a comma, quote, or newline. */ function escapeCSV(value) { const str = String(value); if (str.includes(',') || str.includes('"') || str.includes('\n')) { return '"' + str.replace(/"/g, '""') + '"'; } return str; } module.exports = { format };