convert-buddy-js 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/chunk-DESHN2IK.js.map +1 -0
  2. package/dist/{chunk-WBKHAQCT.js → chunk-EW7HKBIV.js} +3 -2
  3. package/dist/chunk-EW7HKBIV.js.map +1 -0
  4. package/dist/{chunk-C3RSVYQF.js → chunk-KMYCJF2Y.js} +2 -2
  5. package/dist/chunk-KMYCJF2Y.js.map +1 -0
  6. package/dist/src/bench/datasets.d.ts +12 -0
  7. package/dist/src/bench/datasets.js +149 -0
  8. package/dist/src/bench/datasets.js.map +1 -0
  9. package/dist/src/bench/runner-with-competitors.d.ts +2 -0
  10. package/dist/src/bench/runner-with-competitors.js +330 -0
  11. package/dist/src/bench/runner-with-competitors.js.map +1 -0
  12. package/dist/src/bench/runner.d.ts +2 -0
  13. package/dist/src/bench/runner.js +160 -0
  14. package/dist/src/bench/runner.js.map +1 -0
  15. package/dist/src/src/index.js +191 -0
  16. package/dist/src/src/index.js.map +1 -0
  17. package/dist/src/src/node.js +59 -0
  18. package/dist/src/src/node.js.map +1 -0
  19. package/dist/src/src/smoke-test.d.ts +2 -0
  20. package/dist/src/src/smoke-test.js +210 -0
  21. package/dist/src/src/smoke-test.js.map +1 -0
  22. package/dist/wasm/nodejs/convert_buddy.d.ts +52 -0
  23. package/dist/wasm/nodejs/convert_buddy.js +637 -0
  24. package/dist/wasm/nodejs/convert_buddy_bg.wasm +0 -0
  25. package/dist/wasm/nodejs/convert_buddy_bg.wasm.d.ts +31 -0
  26. package/dist/wasm/nodejs/package.json +13 -0
  27. package/dist/wasm/web/convert_buddy.d.ts +107 -0
  28. package/dist/wasm/web/convert_buddy.js +695 -0
  29. package/dist/wasm/web/convert_buddy_bg.wasm +0 -0
  30. package/dist/wasm/web/convert_buddy_bg.wasm.d.ts +31 -0
  31. package/dist/wasm/web/package.json +17 -0
  32. package/package.json +5 -11
  33. package/wasm-node.cjs +10 -1
  34. package/dist/src/index.js +0 -17
  35. package/dist/src/node.js +0 -21
  36. /package/dist/src/{index.d.ts → src/index.d.ts} +0 -0
  37. /package/dist/src/{node.d.ts → src/node.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../bench/datasets.ts"],"sourcesContent":["/**\r\n * Dataset generators for benchmarking\r\n */\r\n\r\nexport function generateCsvDataset(rows: number, cols: number): Uint8Array {\r\n const encoder = new TextEncoder();\r\n let csv = \"\";\r\n\r\n // Generate headers\r\n const headers = Array.from({ length: cols }, (_, i) => `column_${i}`);\r\n csv += headers.join(\",\") + \"\\n\";\r\n\r\n // Generate rows\r\n for (let i = 0; i < rows; i++) {\r\n const row = Array.from({ length: cols }, (_, j) => {\r\n // Mix of data types\r\n if (j % 4 === 0) {\r\n return `\"text_${i}_${j}\"`; // Quoted string\r\n } else if (j % 4 === 1) {\r\n return i * j; // Number\r\n } else if (j % 4 === 2) {\r\n return `value_${i}`; // Unquoted string\r\n } else {\r\n return `\"quoted, with comma ${i}\"`; // Quoted with comma\r\n }\r\n });\r\n csv += row.join(\",\") + \"\\n\";\r\n }\r\n\r\n return encoder.encode(csv);\r\n}\r\n\r\nexport function generateNdjsonDataset(records: number, fields: number): Uint8Array {\r\n const encoder = new TextEncoder();\r\n let ndjson = \"\";\r\n\r\n for (let i = 0; i < records; i++) {\r\n const obj: Record<string, any> = {};\r\n \r\n for (let j = 0; j < fields; j++) {\r\n const key = `field_${j}`;\r\n \r\n // Mix of data types\r\n if (j % 5 === 0) {\r\n obj[key] = `string_value_${i}_${j}`;\r\n } else if (j % 5 === 1) {\r\n obj[key] = i * j;\r\n } else if (j % 5 === 2) {\r\n obj[key] = i % 2 === 0;\r\n } else if (j % 5 === 3) {\r\n obj[key] = null;\r\n } else {\r\n obj[key] = { nested: `value_${i}`, count: j };\r\n }\r\n }\r\n \r\n ndjson += JSON.stringify(obj) + \"\\n\";\r\n }\r\n\r\n return encoder.encode(ndjson);\r\n}\r\n\r\nexport function generateXmlDataset(records: number, fields: number): Uint8Array {\r\n const encoder = new TextEncoder();\r\n let xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<root>\\n';\r\n\r\n for (let i = 0; i < records; i++) {\r\n xml += ` <record id=\"${i}\">\\n`;\r\n \r\n for (let j = 0; j < fields; j++) {\r\n const value = `value_${i}_${j}`;\r\n xml += ` <field_${j}>${value}</field_${j}>\\n`;\r\n }\r\n \r\n xml += ` </record>\\n`;\r\n }\r\n\r\n xml += \"</root>\\n\";\r\n return encoder.encode(xml);\r\n}\r\n\r\nexport function generateJsonDataset(records: number, fields: number): Uint8Array {\r\n const encoder = new TextEncoder();\r\n const array = [];\r\n\r\n for (let i = 0; i < records; i++) {\r\n const obj: Record<string, any> = {};\r\n \r\n for (let j = 0; j < fields; j++) {\r\n const key = `field_${j}`;\r\n \r\n if (j % 4 === 0) {\r\n obj[key] = `string_value_${i}_${j}`;\r\n } else if (j % 4 === 1) {\r\n obj[key] = i * j;\r\n } else if (j % 4 === 2) {\r\n obj[key] = i % 2 === 0;\r\n } else {\r\n obj[key] = { nested: `value_${i}` };\r\n }\r\n }\r\n \r\n array.push(obj);\r\n }\r\n\r\n return encoder.encode(JSON.stringify(array));\r\n}\r\n\r\n// Generate realistic CSV with various edge cases\r\nexport function generateRealisticCsv(rows: number): Uint8Array {\r\n const encoder = new TextEncoder();\r\n let csv = \"id,name,email,age,city,description\\n\";\r\n\r\n const cities = [\"New York\", \"London\", \"Tokyo\", \"Paris\", \"Berlin\"];\r\n const names = [\"Alice\", \"Bob\", \"Charlie\", \"Diana\", \"Eve\"];\r\n\r\n for (let i = 0; i < rows; i++) {\r\n const name = names[i % names.length];\r\n const email = `${name.toLowerCase()}${i}@example.com`;\r\n const age = 20 + (i % 50);\r\n const city = cities[i % cities.length];\r\n const description = `\"This is a longer description with, commas and \"\"quotes\"\" for record ${i}\"`;\r\n \r\n csv += `${i},${name},${email},${age},${city},${description}\\n`;\r\n }\r\n\r\n return encoder.encode(csv);\r\n}\r\n\r\n// Generate wide CSV (many columns)\r\nexport function generateWideCsv(rows: number, cols: number = 100): Uint8Array {\r\n const encoder = new TextEncoder();\r\n \r\n // Headers\r\n const headers = Array.from({ length: cols }, (_, i) => `col_${i}`);\r\n let csv = headers.join(\",\") + \"\\n\";\r\n\r\n // Data\r\n for (let i = 0; i < rows; i++) {\r\n const row = Array.from({ length: cols }, (_, j) => i * cols + j);\r\n csv += row.join(\",\") + \"\\n\";\r\n }\r\n\r\n return encoder.encode(csv);\r\n}\r\n\r\n// Generate NDJSON with large objects\r\nexport function generateLargeObjectNdjson(records: number): Uint8Array {\r\n const encoder = new TextEncoder();\r\n let ndjson = \"\";\r\n\r\n for (let i = 0; i < records; i++) {\r\n const obj = {\r\n id: i,\r\n timestamp: new Date().toISOString(),\r\n user: {\r\n name: `User ${i}`,\r\n email: `user${i}@example.com`,\r\n profile: {\r\n age: 20 + (i % 50),\r\n city: \"City\",\r\n bio: \"A\".repeat(100), // Large string\r\n },\r\n },\r\n data: Array.from({ length: 10 }, (_, j) => ({\r\n key: `key_${j}`,\r\n value: i * j,\r\n })),\r\n metadata: {\r\n created: new Date().toISOString(),\r\n updated: new Date().toISOString(),\r\n tags: [\"tag1\", \"tag2\", \"tag3\"],\r\n },\r\n };\r\n \r\n ndjson += JSON.stringify(obj) + \"\\n\";\r\n }\r\n\r\n return encoder.encode(ndjson);\r\n}\r\n"],"mappings":"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","names":[]}
@@ -7,7 +7,8 @@ async function loadWasmModule() {
7
7
  const mod2 = require2("../wasm-node.cjs");
8
8
  return mod2;
9
9
  }
10
- const mod = await import("../wasm/web/convert_buddy.js");
10
+ const wasmUrl = new URL("./web/convert_buddy.js", import.meta.url);
11
+ const mod = await import(wasmUrl.href);
11
12
  return mod;
12
13
  }
13
14
  var ConvertBuddy = class _ConvertBuddy {
@@ -189,4 +190,4 @@ export {
189
190
  convert,
190
191
  convertToString
191
192
  };
192
- //# sourceMappingURL=chunk-WBKHAQCT.js.map
193
+ //# sourceMappingURL=chunk-EW7HKBIV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type Format = \"csv\" | \"ndjson\" | \"json\" | \"xml\";\r\nexport type DetectInput =\r\n | Uint8Array\r\n | ArrayBuffer\r\n | string\r\n | ReadableStream<Uint8Array>\r\n | AsyncIterable<Uint8Array>;\r\n\r\nexport type CsvDetection = {\r\n delimiter: string;\r\n fields: string[];\r\n};\r\n\r\nexport type DetectOptions = {\r\n maxBytes?: number;\r\n debug?: boolean;\r\n};\r\n\r\nexport type ConvertBuddyOptions = {\r\n debug?: boolean;\r\n profile?: boolean;\r\n inputFormat?: Format;\r\n outputFormat?: Format;\r\n chunkTargetBytes?: number;\r\n parallelism?: number; // Node only - number of worker threads\r\n csvConfig?: CsvConfig;\r\n xmlConfig?: XmlConfig;\r\n};\r\n\r\nexport type CsvConfig = {\r\n delimiter?: string;\r\n quote?: string;\r\n hasHeaders?: boolean;\r\n trimWhitespace?: boolean;\r\n};\r\n\r\nexport type XmlConfig = {\r\n recordElement?: string;\r\n trimText?: boolean;\r\n includeAttributes?: boolean;\r\n expandEntities?: boolean;\r\n};\r\n\r\nexport type Stats = {\r\n bytesIn: number;\r\n bytesOut: number;\r\n chunksIn: number;\r\n recordsProcessed: number;\r\n parseTimeMs: number;\r\n transformTimeMs: number;\r\n writeTimeMs: number;\r\n maxBufferSize: number;\r\n currentPartialSize: number;\r\n throughputMbPerSec: number;\r\n};\r\n\r\ntype WasmModule = {\r\n default?: unknown;\r\n init: (debugEnabled: boolean) => void;\r\n Converter: new (debug: boolean) => {\r\n push: (chunk: Uint8Array) => Uint8Array;\r\n finish: () => Uint8Array;\r\n getStats: () => Stats;\r\n };\r\n detectFormat?: (sample: Uint8Array) => string | null | undefined;\r\n detectCsvFields?: (sample: Uint8Array) => CsvDetection | null | undefined;\r\n __wbg_set_wasm?: (wasm: unknown) => void;\r\n};\r\n\r\nasync function loadWasmModule(): Promise<WasmModule> {\r\n const isNode =\r\n typeof process !== \"undefined\" &&\r\n !!(process as any).versions?.node;\r\n\r\n if (isNode) {\r\n const { createRequire } = await import(\"node:module\");\r\n const require = createRequire(import.meta.url);\r\n const mod = require(\"../wasm-node.cjs\");\r\n return mod as WasmModule;\r\n }\r\n\r\n const wasmUrl = new URL(\"./web/convert_buddy.js\", import.meta.url);\r\n const mod = (await import(wasmUrl.href)) as unknown as WasmModule;\r\n return mod;\r\n}\r\n\r\nexport class ConvertBuddy {\r\n private converter: any;\r\n private debug: boolean;\r\n private profile: boolean;\r\n\r\n private constructor(converter: any, debug: boolean, profile: boolean) {\r\n this.converter = converter;\r\n this.debug = debug;\r\n this.profile = profile;\r\n }\r\n\r\n static async create(opts: ConvertBuddyOptions = {}): Promise<ConvertBuddy> {\r\n const debug = !!opts.debug;\r\n const profile = !!opts.profile;\r\n\r\n const wasmModule = await loadWasmModule();\r\n\r\n if (typeof wasmModule.default === \"function\") {\r\n await (wasmModule.default as () => Promise<void>)();\r\n }\r\n\r\n wasmModule.init(debug);\r\n\r\n let converter;\r\n if (opts.inputFormat && opts.outputFormat) {\r\n // Use withConfig for custom formats\r\n const Converter = (wasmModule as any).Converter;\r\n converter = Converter.withConfig(\r\n debug,\r\n opts.inputFormat,\r\n opts.outputFormat,\r\n opts.chunkTargetBytes || 1024 * 1024,\r\n profile,\r\n opts.csvConfig,\r\n opts.xmlConfig\r\n );\r\n } else {\r\n converter = new wasmModule.Converter(debug);\r\n }\r\n\r\n if (debug) console.log(\"[convert-buddy-js] initialized\", opts);\r\n return new ConvertBuddy(converter, debug, profile);\r\n }\r\n\r\n push(chunk: Uint8Array): Uint8Array {\r\n if (this.debug) console.log(\"[convert-buddy-js] push\", chunk.byteLength);\r\n return this.converter.push(chunk);\r\n }\r\n\r\n finish(): Uint8Array {\r\n if (this.debug) console.log(\"[convert-buddy-js] finish\");\r\n return this.converter.finish();\r\n }\r\n\r\n stats(): Stats {\r\n return this.converter.getStats();\r\n }\r\n}\r\n\r\nasync function readSample(\r\n input: DetectInput,\r\n maxBytes = 256 * 1024\r\n): Promise<Uint8Array> {\r\n if (typeof input === \"string\") {\r\n const encoded = new TextEncoder().encode(input);\r\n return encoded.length > maxBytes ? encoded.slice(0, maxBytes) : encoded;\r\n }\r\n\r\n if (input instanceof Uint8Array) {\r\n return input.length > maxBytes ? input.slice(0, maxBytes) : input;\r\n }\r\n\r\n if (input instanceof ArrayBuffer) {\r\n const bytes = new Uint8Array(input);\r\n return bytes.length > maxBytes ? bytes.slice(0, maxBytes) : bytes;\r\n }\r\n\r\n if (isReadableStream(input)) {\r\n const reader = input.getReader();\r\n const chunks: Uint8Array[] = [];\r\n let total = 0;\r\n\r\n while (total < maxBytes) {\r\n const { value, done } = await reader.read();\r\n if (done || !value) break;\r\n const slice = total + value.length > maxBytes\r\n ? value.slice(0, maxBytes - total)\r\n : value;\r\n chunks.push(slice);\r\n total += slice.length;\r\n }\r\n\r\n if (total >= maxBytes) {\r\n await reader.cancel();\r\n }\r\n\r\n return concatChunks(chunks, total);\r\n }\r\n\r\n const chunks: Uint8Array[] = [];\r\n let total = 0;\r\n\r\n for await (const chunk of input as AsyncIterable<Uint8Array>) {\r\n if (total >= maxBytes) {\r\n break;\r\n }\r\n const data = chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk);\r\n const slice = total + data.length > maxBytes\r\n ? data.slice(0, maxBytes - total)\r\n : data;\r\n chunks.push(slice);\r\n total += slice.length;\r\n }\r\n\r\n return concatChunks(chunks, total);\r\n}\r\n\r\nfunction concatChunks(chunks: Uint8Array[], total: number): Uint8Array {\r\n const result = new Uint8Array(total);\r\n let offset = 0;\r\n for (const chunk of chunks) {\r\n result.set(chunk, offset);\r\n offset += chunk.length;\r\n }\r\n return result;\r\n}\r\n\r\nfunction isReadableStream(\r\n input: DetectInput\r\n): input is ReadableStream<Uint8Array> {\r\n return typeof (input as ReadableStream<Uint8Array>)?.getReader === \"function\";\r\n}\r\n\r\nasync function loadDetectionWasm(debug: boolean): Promise<WasmModule> {\r\n const wasmModule = await loadWasmModule();\r\n if (typeof wasmModule.default === \"function\") {\r\n await (wasmModule.default as () => Promise<void>)();\r\n }\r\n wasmModule.init(debug);\r\n return wasmModule;\r\n}\r\n\r\nexport async function detectFormat(\r\n input: DetectInput,\r\n opts: DetectOptions = {}\r\n): Promise<Format | \"unknown\"> {\r\n const wasmModule = await loadDetectionWasm(!!opts.debug);\r\n const sample = await readSample(input, opts.maxBytes);\r\n const format = wasmModule.detectFormat?.(sample);\r\n return (format as Format) ?? \"unknown\";\r\n}\r\n\r\nexport async function detectCsvFieldsAndDelimiter(\r\n input: DetectInput,\r\n opts: DetectOptions = {}\r\n): Promise<CsvDetection | null> {\r\n const wasmModule = await loadDetectionWasm(!!opts.debug);\r\n const sample = await readSample(input, opts.maxBytes);\r\n const result = wasmModule.detectCsvFields?.(sample);\r\n return result ?? null;\r\n}\r\n\r\n// Web Streams TransformStream adapter\r\nexport class ConvertBuddyTransformStream extends TransformStream<Uint8Array, Uint8Array> {\r\n constructor(opts: ConvertBuddyOptions = {}) {\r\n let buddy: ConvertBuddy | null = null;\r\n\r\n super({\r\n async start(controller) {\r\n buddy = await ConvertBuddy.create(opts);\r\n },\r\n\r\n transform(chunk, controller) {\r\n if (!buddy) {\r\n throw new Error(\"ConvertBuddy not initialized\");\r\n }\r\n\r\n const output = buddy.push(chunk);\r\n if (output.length > 0) {\r\n controller.enqueue(output);\r\n }\r\n },\r\n\r\n flush(controller) {\r\n if (!buddy) {\r\n return;\r\n }\r\n\r\n const output = buddy.finish();\r\n if (output.length > 0) {\r\n controller.enqueue(output);\r\n }\r\n\r\n if (opts.profile) {\r\n const stats = buddy.stats();\r\n console.log(\"[convert-buddy] Performance Stats:\", stats);\r\n }\r\n },\r\n });\r\n }\r\n}\r\n\r\n// Utility: Convert entire buffer/string\r\nexport async function convert(\r\n input: Uint8Array | string,\r\n opts: ConvertBuddyOptions = {}\r\n): Promise<Uint8Array> {\r\n const buddy = await ConvertBuddy.create(opts);\r\n\r\n const inputBytes = typeof input === \"string\" \r\n ? new TextEncoder().encode(input)\r\n : input;\r\n\r\n const output = buddy.push(inputBytes);\r\n const final = buddy.finish();\r\n\r\n // Combine outputs\r\n const result = new Uint8Array(output.length + final.length);\r\n result.set(output, 0);\r\n result.set(final, output.length);\r\n\r\n if (opts.profile) {\r\n const stats = buddy.stats();\r\n console.log(\"[convert-buddy] Performance Stats:\", stats);\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// Utility: Convert and return as string\r\nexport async function convertToString(\r\n input: Uint8Array | string,\r\n opts: ConvertBuddyOptions = {}\r\n): Promise<string> {\r\n const result = await convert(input, opts);\r\n return new TextDecoder().decode(result);\r\n}\r\n"],"mappings":"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","names":["require","mod","chunks","total"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ConvertBuddy
3
- } from "./chunk-WBKHAQCT.js";
3
+ } from "./chunk-EW7HKBIV.js";
4
4
 
5
5
  // src/node.ts
6
6
  async function loadNodeTransform() {
@@ -60,4 +60,4 @@ async function createNodeTransform(opts = {}) {
60
60
  export {
61
61
  createNodeTransform
62
62
  };
63
- //# sourceMappingURL=chunk-C3RSVYQF.js.map
63
+ //# sourceMappingURL=chunk-KMYCJF2Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/node.ts"],"sourcesContent":["import type { Transform as NodeTransform } from \"node:stream\";\r\n\r\nimport { ConvertBuddy, type ConvertBuddyOptions } from \"./index\";\r\n\r\nexport * from \"./index\";\r\n\r\n// Node.js Transform Stream adapter\r\nasync function loadNodeTransform(): Promise<typeof import(\"node:stream\").Transform> {\r\n const isNode =\r\n typeof process !== \"undefined\" &&\r\n !!(process as any).versions?.node;\r\n\r\n if (!isNode) {\r\n throw new Error(\"createNodeTransform is only available in Node.js runtimes.\");\r\n }\r\n\r\n const streamModule = await import(\"node:stream\");\r\n return streamModule.Transform;\r\n}\r\n\r\nexport async function createNodeTransform(\r\n opts: ConvertBuddyOptions = {}\r\n): Promise<NodeTransform> {\r\n let buddy: ConvertBuddy | null = null;\r\n let initPromise: Promise<void> | null = null;\r\n\r\n const Transform = await loadNodeTransform();\r\n const transform = new Transform({\r\n async transform(chunk: Buffer, encoding: string, callback: Function) {\r\n try {\r\n if (!buddy) {\r\n if (!initPromise) {\r\n initPromise = ConvertBuddy.create(opts).then((b) => {\r\n buddy = b;\r\n });\r\n }\r\n await initPromise;\r\n }\r\n\r\n const input = new Uint8Array(chunk);\r\n const output = buddy!.push(input);\r\n\r\n if (output.length > 0) {\r\n this.push(Buffer.from(output));\r\n }\r\n\r\n callback();\r\n } catch (err) {\r\n callback(err);\r\n }\r\n },\r\n\r\n async flush(callback: Function) {\r\n try {\r\n if (buddy) {\r\n const output = buddy.finish();\r\n if (output.length > 0) {\r\n this.push(Buffer.from(output));\r\n }\r\n\r\n if (opts.profile) {\r\n const stats = buddy.stats();\r\n console.log(\"[convert-buddy] Performance Stats:\", stats);\r\n }\r\n }\r\n callback();\r\n } catch (err) {\r\n callback(err);\r\n }\r\n },\r\n });\r\n\r\n return transform;\r\n}\r\n"],"mappings":";;;;;AAOA,eAAe,oBAAqE;AAClF,QAAM,SACJ,OAAO,YAAY,eACnB,CAAC,CAAE,QAAgB,UAAU;AAE/B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,4DAA4D;AAAA,EAC9E;AAEA,QAAM,eAAe,MAAM,OAAO,QAAa;AAC/C,SAAO,aAAa;AACtB;AAEA,eAAsB,oBACpB,OAA4B,CAAC,GACL;AACxB,MAAI,QAA6B;AACjC,MAAI,cAAoC;AAExC,QAAM,YAAY,MAAM,kBAAkB;AAC1C,QAAM,YAAY,IAAI,UAAU;AAAA,IAC9B,MAAM,UAAU,OAAe,UAAkB,UAAoB;AACnE,UAAI;AACF,YAAI,CAAC,OAAO;AACV,cAAI,CAAC,aAAa;AAChB,0BAAc,aAAa,OAAO,IAAI,EAAE,KAAK,CAAC,MAAM;AAClD,sBAAQ;AAAA,YACV,CAAC;AAAA,UACH;AACA,gBAAM;AAAA,QACR;AAEA,cAAM,QAAQ,IAAI,WAAW,KAAK;AAClC,cAAM,SAAS,MAAO,KAAK,KAAK;AAEhC,YAAI,OAAO,SAAS,GAAG;AACrB,eAAK,KAAK,OAAO,KAAK,MAAM,CAAC;AAAA,QAC/B;AAEA,iBAAS;AAAA,MACX,SAAS,KAAK;AACZ,iBAAS,GAAG;AAAA,MACd;AAAA,IACF;AAAA,IAEA,MAAM,MAAM,UAAoB;AAC9B,UAAI;AACF,YAAI,OAAO;AACT,gBAAM,SAAS,MAAM,OAAO;AAC5B,cAAI,OAAO,SAAS,GAAG;AACrB,iBAAK,KAAK,OAAO,KAAK,MAAM,CAAC;AAAA,UAC/B;AAEA,cAAI,KAAK,SAAS;AAChB,kBAAM,QAAQ,MAAM,MAAM;AAC1B,oBAAQ,IAAI,sCAAsC,KAAK;AAAA,UACzD;AAAA,QACF;AACA,iBAAS;AAAA,MACX,SAAS,KAAK;AACZ,iBAAS,GAAG;AAAA,MACd;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;","names":[]}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Dataset generators for benchmarking
3
+ */
4
+ declare function generateCsvDataset(rows: number, cols: number): Uint8Array;
5
+ declare function generateNdjsonDataset(records: number, fields: number): Uint8Array;
6
+ declare function generateXmlDataset(records: number, fields: number): Uint8Array;
7
+ declare function generateJsonDataset(records: number, fields: number): Uint8Array;
8
+ declare function generateRealisticCsv(rows: number): Uint8Array;
9
+ declare function generateWideCsv(rows: number, cols?: number): Uint8Array;
10
+ declare function generateLargeObjectNdjson(records: number): Uint8Array;
11
+
12
+ export { generateCsvDataset, generateJsonDataset, generateLargeObjectNdjson, generateNdjsonDataset, generateRealisticCsv, generateWideCsv, generateXmlDataset };
@@ -0,0 +1,149 @@
1
+ function generateCsvDataset(rows, cols) {
2
+ const encoder = new TextEncoder();
3
+ let csv = "";
4
+ const headers = Array.from({ length: cols }, (_, i) => `column_${i}`);
5
+ csv += headers.join(",") + "\n";
6
+ for (let i = 0; i < rows; i++) {
7
+ const row = Array.from({ length: cols }, (_, j) => {
8
+ if (j % 4 === 0) {
9
+ return `"text_${i}_${j}"`;
10
+ } else if (j % 4 === 1) {
11
+ return i * j;
12
+ } else if (j % 4 === 2) {
13
+ return `value_${i}`;
14
+ } else {
15
+ return `"quoted, with comma ${i}"`;
16
+ }
17
+ });
18
+ csv += row.join(",") + "\n";
19
+ }
20
+ return encoder.encode(csv);
21
+ }
22
+ function generateNdjsonDataset(records, fields) {
23
+ const encoder = new TextEncoder();
24
+ let ndjson = "";
25
+ for (let i = 0; i < records; i++) {
26
+ const obj = {};
27
+ for (let j = 0; j < fields; j++) {
28
+ const key = `field_${j}`;
29
+ if (j % 5 === 0) {
30
+ obj[key] = `string_value_${i}_${j}`;
31
+ } else if (j % 5 === 1) {
32
+ obj[key] = i * j;
33
+ } else if (j % 5 === 2) {
34
+ obj[key] = i % 2 === 0;
35
+ } else if (j % 5 === 3) {
36
+ obj[key] = null;
37
+ } else {
38
+ obj[key] = { nested: `value_${i}`, count: j };
39
+ }
40
+ }
41
+ ndjson += JSON.stringify(obj) + "\n";
42
+ }
43
+ return encoder.encode(ndjson);
44
+ }
45
+ function generateXmlDataset(records, fields) {
46
+ const encoder = new TextEncoder();
47
+ let xml = '<?xml version="1.0" encoding="UTF-8"?>\n<root>\n';
48
+ for (let i = 0; i < records; i++) {
49
+ xml += ` <record id="${i}">
50
+ `;
51
+ for (let j = 0; j < fields; j++) {
52
+ const value = `value_${i}_${j}`;
53
+ xml += ` <field_${j}>${value}</field_${j}>
54
+ `;
55
+ }
56
+ xml += ` </record>
57
+ `;
58
+ }
59
+ xml += "</root>\n";
60
+ return encoder.encode(xml);
61
+ }
62
+ function generateJsonDataset(records, fields) {
63
+ const encoder = new TextEncoder();
64
+ const array = [];
65
+ for (let i = 0; i < records; i++) {
66
+ const obj = {};
67
+ for (let j = 0; j < fields; j++) {
68
+ const key = `field_${j}`;
69
+ if (j % 4 === 0) {
70
+ obj[key] = `string_value_${i}_${j}`;
71
+ } else if (j % 4 === 1) {
72
+ obj[key] = i * j;
73
+ } else if (j % 4 === 2) {
74
+ obj[key] = i % 2 === 0;
75
+ } else {
76
+ obj[key] = { nested: `value_${i}` };
77
+ }
78
+ }
79
+ array.push(obj);
80
+ }
81
+ return encoder.encode(JSON.stringify(array));
82
+ }
83
+ function generateRealisticCsv(rows) {
84
+ const encoder = new TextEncoder();
85
+ let csv = "id,name,email,age,city,description\n";
86
+ const cities = ["New York", "London", "Tokyo", "Paris", "Berlin"];
87
+ const names = ["Alice", "Bob", "Charlie", "Diana", "Eve"];
88
+ for (let i = 0; i < rows; i++) {
89
+ const name = names[i % names.length];
90
+ const email = `${name.toLowerCase()}${i}@example.com`;
91
+ const age = 20 + i % 50;
92
+ const city = cities[i % cities.length];
93
+ const description = `"This is a longer description with, commas and ""quotes"" for record ${i}"`;
94
+ csv += `${i},${name},${email},${age},${city},${description}
95
+ `;
96
+ }
97
+ return encoder.encode(csv);
98
+ }
99
+ function generateWideCsv(rows, cols = 100) {
100
+ const encoder = new TextEncoder();
101
+ const headers = Array.from({ length: cols }, (_, i) => `col_${i}`);
102
+ let csv = headers.join(",") + "\n";
103
+ for (let i = 0; i < rows; i++) {
104
+ const row = Array.from({ length: cols }, (_, j) => i * cols + j);
105
+ csv += row.join(",") + "\n";
106
+ }
107
+ return encoder.encode(csv);
108
+ }
109
+ function generateLargeObjectNdjson(records) {
110
+ const encoder = new TextEncoder();
111
+ let ndjson = "";
112
+ for (let i = 0; i < records; i++) {
113
+ const obj = {
114
+ id: i,
115
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
116
+ user: {
117
+ name: `User ${i}`,
118
+ email: `user${i}@example.com`,
119
+ profile: {
120
+ age: 20 + i % 50,
121
+ city: "City",
122
+ bio: "A".repeat(100)
123
+ // Large string
124
+ }
125
+ },
126
+ data: Array.from({ length: 10 }, (_, j) => ({
127
+ key: `key_${j}`,
128
+ value: i * j
129
+ })),
130
+ metadata: {
131
+ created: (/* @__PURE__ */ new Date()).toISOString(),
132
+ updated: (/* @__PURE__ */ new Date()).toISOString(),
133
+ tags: ["tag1", "tag2", "tag3"]
134
+ }
135
+ };
136
+ ndjson += JSON.stringify(obj) + "\n";
137
+ }
138
+ return encoder.encode(ndjson);
139
+ }
140
+ export {
141
+ generateCsvDataset,
142
+ generateJsonDataset,
143
+ generateLargeObjectNdjson,
144
+ generateNdjsonDataset,
145
+ generateRealisticCsv,
146
+ generateWideCsv,
147
+ generateXmlDataset
148
+ };
149
+ //# sourceMappingURL=datasets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../bench/datasets.ts"],"sourcesContent":["/**\r\n * Dataset generators for benchmarking\r\n */\r\n\r\nexport function generateCsvDataset(rows: number, cols: number): Uint8Array {\r\n const encoder = new TextEncoder();\r\n let csv = \"\";\r\n\r\n // Generate headers\r\n const headers = Array.from({ length: cols }, (_, i) => `column_${i}`);\r\n csv += headers.join(\",\") + \"\\n\";\r\n\r\n // Generate rows\r\n for (let i = 0; i < rows; i++) {\r\n const row = Array.from({ length: cols }, (_, j) => {\r\n // Mix of data types\r\n if (j % 4 === 0) {\r\n return `\"text_${i}_${j}\"`; // Quoted string\r\n } else if (j % 4 === 1) {\r\n return i * j; // Number\r\n } else if (j % 4 === 2) {\r\n return `value_${i}`; // Unquoted string\r\n } else {\r\n return `\"quoted, with comma ${i}\"`; // Quoted with comma\r\n }\r\n });\r\n csv += row.join(\",\") + \"\\n\";\r\n }\r\n\r\n return encoder.encode(csv);\r\n}\r\n\r\nexport function generateNdjsonDataset(records: number, fields: number): Uint8Array {\r\n const encoder = new TextEncoder();\r\n let ndjson = \"\";\r\n\r\n for (let i = 0; i < records; i++) {\r\n const obj: Record<string, any> = {};\r\n \r\n for (let j = 0; j < fields; j++) {\r\n const key = `field_${j}`;\r\n \r\n // Mix of data types\r\n if (j % 5 === 0) {\r\n obj[key] = `string_value_${i}_${j}`;\r\n } else if (j % 5 === 1) {\r\n obj[key] = i * j;\r\n } else if (j % 5 === 2) {\r\n obj[key] = i % 2 === 0;\r\n } else if (j % 5 === 3) {\r\n obj[key] = null;\r\n } else {\r\n obj[key] = { nested: `value_${i}`, count: j };\r\n }\r\n }\r\n \r\n ndjson += JSON.stringify(obj) + \"\\n\";\r\n }\r\n\r\n return encoder.encode(ndjson);\r\n}\r\n\r\nexport function generateXmlDataset(records: number, fields: number): Uint8Array {\r\n const encoder = new TextEncoder();\r\n let xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<root>\\n';\r\n\r\n for (let i = 0; i < records; i++) {\r\n xml += ` <record id=\"${i}\">\\n`;\r\n \r\n for (let j = 0; j < fields; j++) {\r\n const value = `value_${i}_${j}`;\r\n xml += ` <field_${j}>${value}</field_${j}>\\n`;\r\n }\r\n \r\n xml += ` </record>\\n`;\r\n }\r\n\r\n xml += \"</root>\\n\";\r\n return encoder.encode(xml);\r\n}\r\n\r\nexport function generateJsonDataset(records: number, fields: number): Uint8Array {\r\n const encoder = new TextEncoder();\r\n const array = [];\r\n\r\n for (let i = 0; i < records; i++) {\r\n const obj: Record<string, any> = {};\r\n \r\n for (let j = 0; j < fields; j++) {\r\n const key = `field_${j}`;\r\n \r\n if (j % 4 === 0) {\r\n obj[key] = `string_value_${i}_${j}`;\r\n } else if (j % 4 === 1) {\r\n obj[key] = i * j;\r\n } else if (j % 4 === 2) {\r\n obj[key] = i % 2 === 0;\r\n } else {\r\n obj[key] = { nested: `value_${i}` };\r\n }\r\n }\r\n \r\n array.push(obj);\r\n }\r\n\r\n return encoder.encode(JSON.stringify(array));\r\n}\r\n\r\n// Generate realistic CSV with various edge cases\r\nexport function generateRealisticCsv(rows: number): Uint8Array {\r\n const encoder = new TextEncoder();\r\n let csv = \"id,name,email,age,city,description\\n\";\r\n\r\n const cities = [\"New York\", \"London\", \"Tokyo\", \"Paris\", \"Berlin\"];\r\n const names = [\"Alice\", \"Bob\", \"Charlie\", \"Diana\", \"Eve\"];\r\n\r\n for (let i = 0; i < rows; i++) {\r\n const name = names[i % names.length];\r\n const email = `${name.toLowerCase()}${i}@example.com`;\r\n const age = 20 + (i % 50);\r\n const city = cities[i % cities.length];\r\n const description = `\"This is a longer description with, commas and \"\"quotes\"\" for record ${i}\"`;\r\n \r\n csv += `${i},${name},${email},${age},${city},${description}\\n`;\r\n }\r\n\r\n return encoder.encode(csv);\r\n}\r\n\r\n// Generate wide CSV (many columns)\r\nexport function generateWideCsv(rows: number, cols: number = 100): Uint8Array {\r\n const encoder = new TextEncoder();\r\n \r\n // Headers\r\n const headers = Array.from({ length: cols }, (_, i) => `col_${i}`);\r\n let csv = headers.join(\",\") + \"\\n\";\r\n\r\n // Data\r\n for (let i = 0; i < rows; i++) {\r\n const row = Array.from({ length: cols }, (_, j) => i * cols + j);\r\n csv += row.join(\",\") + \"\\n\";\r\n }\r\n\r\n return encoder.encode(csv);\r\n}\r\n\r\n// Generate NDJSON with large objects\r\nexport function generateLargeObjectNdjson(records: number): Uint8Array {\r\n const encoder = new TextEncoder();\r\n let ndjson = \"\";\r\n\r\n for (let i = 0; i < records; i++) {\r\n const obj = {\r\n id: i,\r\n timestamp: new Date().toISOString(),\r\n user: {\r\n name: `User ${i}`,\r\n email: `user${i}@example.com`,\r\n profile: {\r\n age: 20 + (i % 50),\r\n city: \"City\",\r\n bio: \"A\".repeat(100), // Large string\r\n },\r\n },\r\n data: Array.from({ length: 10 }, (_, j) => ({\r\n key: `key_${j}`,\r\n value: i * j,\r\n })),\r\n metadata: {\r\n created: new Date().toISOString(),\r\n updated: new Date().toISOString(),\r\n tags: [\"tag1\", \"tag2\", \"tag3\"],\r\n },\r\n };\r\n \r\n ndjson += JSON.stringify(obj) + \"\\n\";\r\n }\r\n\r\n return encoder.encode(ndjson);\r\n}\r\n"],"mappings":"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","names":[]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,330 @@
1
+ import { performance } from "node:perf_hooks";
2
+ import { convert } from "../src/index.js";
3
+ import { generateCsvDataset, generateNdjsonDataset, generateXmlDataset } from "./datasets.js";
4
+ import * as fs from "node:fs";
5
+ import * as path from "node:path";
6
+ async function benchmarkConversion(tool, conversion, size, data, opts) {
7
+ const startMem = process.memoryUsage().heapUsed;
8
+ const start = performance.now();
9
+ const result = await convert(data, opts);
10
+ const end = performance.now();
11
+ const endMem = process.memoryUsage().heapUsed;
12
+ const latencyMs = end - start;
13
+ const throughputMbps = data.length / (1024 * 1024) / (latencyMs / 1e3);
14
+ const memoryMb = (endMem - startMem) / (1024 * 1024);
15
+ const records = result.filter((b) => b === 10).length;
16
+ const recordsPerSec = records / (latencyMs / 1e3);
17
+ return {
18
+ tool,
19
+ conversion,
20
+ size,
21
+ dataset: `${(data.length / (1024 * 1024)).toFixed(2)} MB`,
22
+ throughputMbps: parseFloat(throughputMbps.toFixed(2)),
23
+ latencyMs: parseFloat(latencyMs.toFixed(2)),
24
+ memoryMb: parseFloat(memoryMb.toFixed(2)),
25
+ recordsPerSec: parseFloat(recordsPerSec.toFixed(0))
26
+ };
27
+ }
28
+ async function benchmarkPapaParse(conversion, size, csvData) {
29
+ try {
30
+ const papaModule = await import("papaparse");
31
+ const Papa = papaModule.default || papaModule;
32
+ const data = new TextEncoder().encode(csvData);
33
+ const startMem = process.memoryUsage().heapUsed;
34
+ const start = performance.now();
35
+ const result = Papa.parse(csvData, { header: true });
36
+ const ndjson = result.data.map((row) => JSON.stringify(row)).join("\n");
37
+ const end = performance.now();
38
+ const endMem = process.memoryUsage().heapUsed;
39
+ const latencyMs = end - start;
40
+ const throughputMbps = data.length / (1024 * 1024) / (latencyMs / 1e3);
41
+ const memoryMb = (endMem - startMem) / (1024 * 1024);
42
+ const recordsPerSec = result.data.length / (latencyMs / 1e3);
43
+ return {
44
+ tool: "PapaParse",
45
+ conversion,
46
+ size,
47
+ dataset: `${(data.length / (1024 * 1024)).toFixed(2)} MB`,
48
+ throughputMbps: parseFloat(throughputMbps.toFixed(2)),
49
+ latencyMs: parseFloat(latencyMs.toFixed(2)),
50
+ memoryMb: parseFloat(memoryMb.toFixed(2)),
51
+ recordsPerSec: parseFloat(recordsPerSec.toFixed(0))
52
+ };
53
+ } catch (error) {
54
+ console.log(`\u26A0\uFE0F PapaParse not available: ${error}`);
55
+ return null;
56
+ }
57
+ }
58
+ async function benchmarkCsvParse(conversion, size, csvData) {
59
+ try {
60
+ const { parse } = await import("csv-parse/sync");
61
+ const data = new TextEncoder().encode(csvData);
62
+ const startMem = process.memoryUsage().heapUsed;
63
+ const start = performance.now();
64
+ const records = parse(csvData, { columns: true });
65
+ const ndjson = records.map((row) => JSON.stringify(row)).join("\n");
66
+ const end = performance.now();
67
+ const endMem = process.memoryUsage().heapUsed;
68
+ const latencyMs = end - start;
69
+ const throughputMbps = data.length / (1024 * 1024) / (latencyMs / 1e3);
70
+ const memoryMb = (endMem - startMem) / (1024 * 1024);
71
+ const recordsPerSec = records.length / (latencyMs / 1e3);
72
+ return {
73
+ tool: "csv-parse",
74
+ conversion,
75
+ size,
76
+ dataset: `${(data.length / (1024 * 1024)).toFixed(2)} MB`,
77
+ throughputMbps: parseFloat(throughputMbps.toFixed(2)),
78
+ latencyMs: parseFloat(latencyMs.toFixed(2)),
79
+ memoryMb: parseFloat(memoryMb.toFixed(2)),
80
+ recordsPerSec: parseFloat(recordsPerSec.toFixed(0))
81
+ };
82
+ } catch (error) {
83
+ console.log(`\u26A0\uFE0F csv-parse not available: ${error}`);
84
+ return null;
85
+ }
86
+ }
87
+ async function benchmarkFastCsv(conversion, size, csvData) {
88
+ try {
89
+ const fastCsvModule = await import("fast-csv");
90
+ const fastCsv = fastCsvModule.default ?? fastCsvModule;
91
+ const { Readable: Readable2 } = await import("stream");
92
+ const data = new TextEncoder().encode(csvData);
93
+ const startMem = process.memoryUsage().heapUsed;
94
+ const start = performance.now();
95
+ const rows = [];
96
+ await new Promise((resolve, reject) => {
97
+ Readable2.from([csvData]).pipe(fastCsv.parse({ headers: true })).on("data", (row) => rows.push(row)).on("end", () => resolve()).on("error", reject);
98
+ });
99
+ const ndjson = rows.map((row) => JSON.stringify(row)).join("\n");
100
+ const end = performance.now();
101
+ const endMem = process.memoryUsage().heapUsed;
102
+ const latencyMs = end - start;
103
+ const throughputMbps = data.length / (1024 * 1024) / (latencyMs / 1e3);
104
+ const memoryMb = (endMem - startMem) / (1024 * 1024);
105
+ const recordsPerSec = rows.length / (latencyMs / 1e3);
106
+ return {
107
+ tool: "fast-csv",
108
+ conversion,
109
+ size,
110
+ dataset: `${(data.length / (1024 * 1024)).toFixed(2)} MB`,
111
+ throughputMbps: parseFloat(throughputMbps.toFixed(2)),
112
+ latencyMs: parseFloat(latencyMs.toFixed(2)),
113
+ memoryMb: parseFloat(memoryMb.toFixed(2)),
114
+ recordsPerSec: parseFloat(recordsPerSec.toFixed(0))
115
+ };
116
+ } catch (error) {
117
+ console.log(`\u26A0\uFE0F fast-csv not available: ${error}`);
118
+ return null;
119
+ }
120
+ }
121
+ async function benchmarkFastXmlParser(conversion, size, xmlData) {
122
+ try {
123
+ const fastXmlModule = await import("fast-xml-parser");
124
+ const XMLParser = fastXmlModule.XMLParser ?? fastXmlModule.default?.XMLParser ?? fastXmlModule.default;
125
+ const data = new TextEncoder().encode(xmlData);
126
+ const startMem = process.memoryUsage().heapUsed;
127
+ const start = performance.now();
128
+ if (typeof XMLParser !== "function") {
129
+ throw new TypeError("XMLParser constructor not available");
130
+ }
131
+ const parser = new XMLParser();
132
+ const parsed = parser.parse(xmlData);
133
+ const records = Array.isArray(parsed?.root?.record) ? parsed.root.record : parsed?.root?.record ? [parsed.root.record] : [];
134
+ const ndjson = records.map((row) => JSON.stringify(row)).join("\n");
135
+ const end = performance.now();
136
+ const endMem = process.memoryUsage().heapUsed;
137
+ const latencyMs = end - start;
138
+ const throughputMbps = data.length / (1024 * 1024) / (latencyMs / 1e3);
139
+ const memoryMb = (endMem - startMem) / (1024 * 1024);
140
+ const recordsPerSec = records.length / (latencyMs / 1e3);
141
+ return {
142
+ tool: "fast-xml-parser",
143
+ conversion,
144
+ size,
145
+ dataset: `${(data.length / (1024 * 1024)).toFixed(2)} MB`,
146
+ throughputMbps: parseFloat(throughputMbps.toFixed(2)),
147
+ latencyMs: parseFloat(latencyMs.toFixed(2)),
148
+ memoryMb: parseFloat(memoryMb.toFixed(2)),
149
+ recordsPerSec: parseFloat(recordsPerSec.toFixed(0))
150
+ };
151
+ } catch (error) {
152
+ console.log(`\u26A0\uFE0F fast-xml-parser not available: ${error}`);
153
+ return null;
154
+ }
155
+ }
156
+ async function runBenchmarks() {
157
+ console.log("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
158
+ console.log("\u2551 Convert Buddy Comprehensive Benchmarks \u2551");
159
+ console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n");
160
+ const results = [];
161
+ console.log("Generating datasets...\n");
162
+ const csvSmall = generateCsvDataset(1e3, 10);
163
+ const csvMedium = generateCsvDataset(1e4, 10);
164
+ const csvLarge = generateCsvDataset(1e5, 10);
165
+ const csvSmallStr = new TextDecoder().decode(csvSmall);
166
+ const csvMediumStr = new TextDecoder().decode(csvMedium);
167
+ const csvLargeStr = new TextDecoder().decode(csvLarge);
168
+ const ndjsonSmall = generateNdjsonDataset(1e3, 10);
169
+ const ndjsonMedium = generateNdjsonDataset(1e4, 10);
170
+ const ndjsonLarge = generateNdjsonDataset(1e5, 10);
171
+ const xmlSmall = generateXmlDataset(1e3, 10);
172
+ const xmlMedium = generateXmlDataset(1e4, 10);
173
+ const xmlLarge = generateXmlDataset(1e5, 10);
174
+ const xmlSmallStr = new TextDecoder().decode(xmlSmall);
175
+ const xmlMediumStr = new TextDecoder().decode(xmlMedium);
176
+ const xmlLargeStr = new TextDecoder().decode(xmlLarge);
177
+ console.log("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
178
+ console.log("\u2551 CSV \u2192 NDJSON Benchmarks \u2551");
179
+ console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n");
180
+ console.log("Benchmarking CSV \u2192 NDJSON (small)...");
181
+ results.push(
182
+ await benchmarkConversion("convert-buddy", "CSV\u2192NDJSON", "small", csvSmall, {
183
+ inputFormat: "csv",
184
+ outputFormat: "ndjson"
185
+ })
186
+ );
187
+ const papaSmall = await benchmarkPapaParse("CSV\u2192NDJSON", "small", csvSmallStr);
188
+ if (papaSmall) results.push(papaSmall);
189
+ const csvParseSmall = await benchmarkCsvParse("CSV\u2192NDJSON", "small", csvSmallStr);
190
+ if (csvParseSmall) results.push(csvParseSmall);
191
+ const fastCsvSmall = await benchmarkFastCsv("CSV\u2192NDJSON", "small", csvSmallStr);
192
+ if (fastCsvSmall) results.push(fastCsvSmall);
193
+ console.log("Benchmarking CSV \u2192 NDJSON (medium)...");
194
+ results.push(
195
+ await benchmarkConversion("convert-buddy", "CSV\u2192NDJSON", "medium", csvMedium, {
196
+ inputFormat: "csv",
197
+ outputFormat: "ndjson"
198
+ })
199
+ );
200
+ const papaMedium = await benchmarkPapaParse("CSV\u2192NDJSON", "medium", csvMediumStr);
201
+ if (papaMedium) results.push(papaMedium);
202
+ const csvParseMedium = await benchmarkCsvParse("CSV\u2192NDJSON", "medium", csvMediumStr);
203
+ if (csvParseMedium) results.push(csvParseMedium);
204
+ const fastCsvMedium = await benchmarkFastCsv("CSV\u2192NDJSON", "medium", csvMediumStr);
205
+ if (fastCsvMedium) results.push(fastCsvMedium);
206
+ console.log("Benchmarking CSV \u2192 NDJSON (large)...");
207
+ results.push(
208
+ await benchmarkConversion("convert-buddy", "CSV\u2192NDJSON", "large", csvLarge, {
209
+ inputFormat: "csv",
210
+ outputFormat: "ndjson"
211
+ })
212
+ );
213
+ const papaLarge = await benchmarkPapaParse("CSV\u2192NDJSON", "large", csvLargeStr);
214
+ if (papaLarge) results.push(papaLarge);
215
+ const csvParseLarge = await benchmarkCsvParse("CSV\u2192NDJSON", "large", csvLargeStr);
216
+ if (csvParseLarge) results.push(csvParseLarge);
217
+ const fastCsvLarge = await benchmarkFastCsv("CSV\u2192NDJSON", "large", csvLargeStr);
218
+ if (fastCsvLarge) results.push(fastCsvLarge);
219
+ console.log("\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
220
+ console.log("\u2551 NDJSON Benchmarks \u2551");
221
+ console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n");
222
+ console.log("Benchmarking NDJSON \u2192 JSON (small)...");
223
+ results.push(
224
+ await benchmarkConversion("convert-buddy", "NDJSON\u2192JSON", "small", ndjsonSmall, {
225
+ inputFormat: "ndjson",
226
+ outputFormat: "json"
227
+ })
228
+ );
229
+ console.log("Benchmarking NDJSON \u2192 JSON (medium)...");
230
+ results.push(
231
+ await benchmarkConversion("convert-buddy", "NDJSON\u2192JSON", "medium", ndjsonMedium, {
232
+ inputFormat: "ndjson",
233
+ outputFormat: "json"
234
+ })
235
+ );
236
+ console.log("Benchmarking NDJSON \u2192 JSON (large)...");
237
+ results.push(
238
+ await benchmarkConversion("convert-buddy", "NDJSON\u2192JSON", "large", ndjsonLarge, {
239
+ inputFormat: "ndjson",
240
+ outputFormat: "json"
241
+ })
242
+ );
243
+ console.log("Benchmarking NDJSON passthrough (large)...");
244
+ results.push(
245
+ await benchmarkConversion("convert-buddy", "NDJSON\u2192NDJSON", "large", ndjsonLarge, {
246
+ inputFormat: "ndjson",
247
+ outputFormat: "ndjson"
248
+ })
249
+ );
250
+ console.log("\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
251
+ console.log("\u2551 XML \u2192 NDJSON Benchmarks \u2551");
252
+ console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n");
253
+ console.log("Benchmarking XML \u2192 NDJSON (small)...");
254
+ results.push(
255
+ await benchmarkConversion("convert-buddy", "XML\u2192NDJSON", "small", xmlSmall, {
256
+ inputFormat: "xml",
257
+ outputFormat: "ndjson",
258
+ xmlConfig: { recordElement: "record" }
259
+ })
260
+ );
261
+ const fastXmlSmall = await benchmarkFastXmlParser("XML\u2192NDJSON", "small", xmlSmallStr);
262
+ if (fastXmlSmall) results.push(fastXmlSmall);
263
+ console.log("Benchmarking XML \u2192 NDJSON (medium)...");
264
+ results.push(
265
+ await benchmarkConversion("convert-buddy", "XML\u2192NDJSON", "medium", xmlMedium, {
266
+ inputFormat: "xml",
267
+ outputFormat: "ndjson",
268
+ xmlConfig: { recordElement: "record" }
269
+ })
270
+ );
271
+ const fastXmlMedium = await benchmarkFastXmlParser("XML\u2192NDJSON", "medium", xmlMediumStr);
272
+ if (fastXmlMedium) results.push(fastXmlMedium);
273
+ console.log("Benchmarking XML \u2192 NDJSON (large)...");
274
+ results.push(
275
+ await benchmarkConversion("convert-buddy", "XML\u2192NDJSON", "large", xmlLarge, {
276
+ inputFormat: "xml",
277
+ outputFormat: "ndjson",
278
+ xmlConfig: { recordElement: "record" }
279
+ })
280
+ );
281
+ const fastXmlLarge = await benchmarkFastXmlParser("XML\u2192NDJSON", "large", xmlLargeStr);
282
+ if (fastXmlLarge) results.push(fastXmlLarge);
283
+ console.log("\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
284
+ console.log("\u2551 All Benchmark Results \u2551");
285
+ console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n");
286
+ console.table(results);
287
+ const outputPath = path.join(process.cwd(), "bench-results.json");
288
+ fs.writeFileSync(outputPath, JSON.stringify(results, null, 2));
289
+ console.log(`
290
+ Results saved to: ${outputPath}`);
291
+ const printComparisonBySize = (conversion, title) => {
292
+ console.log("\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
293
+ console.log(`\u2551 ${title.padEnd(34)}\u2551`);
294
+ console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n");
295
+ for (const size of ["small", "medium", "large"]) {
296
+ const conversionResults = results.filter(
297
+ (r) => r.conversion === conversion && r.size === size
298
+ );
299
+ if (conversionResults.length === 0) {
300
+ continue;
301
+ }
302
+ const sorted = conversionResults.sort((a, b) => b.throughputMbps - a.throughputMbps);
303
+ console.log(`
304
+ ${size.toUpperCase()} (${sorted[0].dataset}):`);
305
+ sorted.forEach((r, i) => {
306
+ const speedup = i === 0 ? "" : ` (${(sorted[0].throughputMbps / r.throughputMbps).toFixed(2)}x slower)`;
307
+ console.log(
308
+ ` ${i + 1}. ${r.tool.padEnd(15)} ${r.throughputMbps.toString().padStart(8)} MB/s ${r.recordsPerSec.toLocaleString().padStart(10)} rec/s${speedup}`
309
+ );
310
+ });
311
+ }
312
+ };
313
+ printComparisonBySize("CSV\u2192NDJSON", "CSV\u2192NDJSON Comparison by Size");
314
+ printComparisonBySize("XML\u2192NDJSON", "XML\u2192NDJSON Comparison by Size");
315
+ console.log("\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
316
+ console.log("\u2551 Summary Statistics \u2551");
317
+ console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n");
318
+ const convertBuddyResults = results.filter((r) => r.tool === "convert-buddy");
319
+ const avgThroughput = convertBuddyResults.reduce((sum, r) => sum + r.throughputMbps, 0) / convertBuddyResults.length;
320
+ const maxThroughput = Math.max(...convertBuddyResults.map((r) => r.throughputMbps));
321
+ const maxRecordsPerSec = Math.max(...convertBuddyResults.map((r) => r.recordsPerSec));
322
+ console.log(`convert-buddy Performance:`);
323
+ console.log(` Average Throughput: ${avgThroughput.toFixed(2)} MB/s`);
324
+ console.log(` Peak Throughput: ${maxThroughput.toFixed(2)} MB/s`);
325
+ console.log(` Peak Records/sec: ${maxRecordsPerSec.toLocaleString()}`);
326
+ console.log(` Conversions Tested: ${new Set(convertBuddyResults.map((r) => r.conversion)).size}`);
327
+ console.log(` Total Benchmarks: ${convertBuddyResults.length}`);
328
+ }
329
+ runBenchmarks().catch(console.error);
330
+ //# sourceMappingURL=runner-with-competitors.js.map