import { stringify as stringifyCSV } from 'csv-stringify/sync' import { XMLBuilder } from 'fast-xml-parser' import { stringify as stringifyYAML } from 'yaml' import { encode as encodeToon } from '../../src/index' /** * Format converters registry * * @remarks * All formatters attempt to preserve semantic equivalence with the source data, * meaning the converted data should represent the same information. However, * CSV has inherent limitations with nested structures (see `toCSV` docs). */ export const formatters: Record string> = { json: data => JSON.stringify(data, undefined, 2), toon: data => encodeToon(data), csv: data => toCSV(data), xml: data => toXML(data), yaml: data => stringifyYAML(data), } /** * Convert data to CSV format * * @remarks * Limitations: CSV is designed for flat tabular data only. * * This formatter: * - Only handles top-level objects with arrays of flat objects * - Cannot properly represent deeply nested structures (nested arrays/objects within rows) * - Loses nested structure information during conversion * - May produce misleading results for datasets with complex nesting (e.g., e-commerce orders with nested items) * * For datasets with nested structures, CSV comparisons may not be fair or representative * of how CSV would typically be used in practice. */ function toCSV(data: unknown): string { const sections: string[] = [] // Handle top-level object with arrays if (typeof data === 'object' && data !== null && !Array.isArray(data)) { for (const [key, value] of Object.entries(data)) { if (Array.isArray(value) && value.length > 0) { sections.push(`# ${key}`) sections.push(stringifyCSV(value, { header: true })) } } return sections.join('\n').trim() } // Root-level array if (Array.isArray(data) && data.length > 0) { return stringifyCSV(data, { header: true }).trim() } return '' } /** * Convert data to XML format * * @remarks * Uses `fast-xml-parser` to generate well-formatted XML with: * - 2-space indentation for readability * - Empty nodes suppressed * - Proper escaping of special characters */ function toXML(data: unknown): string { const builder = new XMLBuilder({ format: true, indentBy: ' ', suppressEmptyNode: true, }) return builder.build(data) }