import type { OutputColumnMetadata } from "@internal/clickhouse"; /** * Escape a value for CSV format. * - Wraps in quotes if the value contains commas, quotes, or newlines * - Escapes quotes by doubling them */ function escapeCSVValue(value: unknown): string { if (value === null || value === undefined) { return ""; } const stringValue = typeof value === "object" ? JSON.stringify(value) : String(value); // Check if we need to quote the value if ( stringValue.includes(",") || stringValue.includes('"') || stringValue.includes("\n") || stringValue.includes("\r") ) { // Escape quotes by doubling them and wrap in quotes return `"${stringValue.replace(/"/g, '""')}"`; } return stringValue; } /** * Convert query result rows to CSV format. * * @param rows - Array of row objects from query results * @param columns - Column metadata describing the result columns * @returns CSV string with header row and data rows */ export function rowsToCSV( rows: Record[], columns: OutputColumnMetadata[] ): string { if (columns.length === 0) { return ""; } const columnNames = columns.map((col) => col.name); // Header row const headerRow = columnNames.map(escapeCSVValue).join(","); // Data rows const dataRows = rows.map((row) => columnNames.map((name) => escapeCSVValue(row[name])).join(",") ); return [headerRow, ...dataRows].join("\n"); } /** * Convert query result rows to JSON format. * * @param rows - Array of row objects from query results * @returns Formatted JSON string */ export function rowsToJSON(rows: Record[]): string { return JSON.stringify(rows, null, 2); } /** * Trigger a file download in the browser. * * @param content - The file content as a string * @param filename - The name for the downloaded file * @param mimeType - The MIME type of the file */ export function downloadFile(content: string, filename: string, mimeType: string): void { const blob = new Blob([content], { type: mimeType }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = filename; a.click(); URL.revokeObjectURL(url); }