type Cell = string | number | null | undefined /** * RFC 4180 CSV. By default starts with a BOM so Excel opens UTF-8 correctly (`bom: false` for machine * uploads such as OSHA's ITA). Cells a spreadsheet would treat as a formula are prefixed with an * apostrophe (CSV injection). */ export function toCsv(header: string[], rows: Cell[][], { bom = true }: { bom?: boolean } = {}): string { const cell = (value: Cell) => { let text = value === null || value === undefined ? '' : String(value) if (/^[=+\-@\t\r]/.test(text)) text = `'${text}` return /[",\r\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text } return (bom ? '\uFEFF' : '') + [header, ...rows].map((row) => row.map(cell).join(',')).join('\r\n') + '\r\n' }