convert-buddy-js 0.9.5 → 0.9.6
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.
- package/README.md +325 -55
- package/dist/src/browser.d.ts +103 -3
- package/dist/src/browser.js +66 -2
- package/dist/src/browser.js.map +1 -1
- package/dist/src/index.d.ts +112 -2
- package/dist/src/index.js +350 -23
- package/dist/src/index.js.map +1 -1
- package/dist/src/node.d.ts +30 -3
- package/dist/src/node.js +15 -1
- package/dist/src/node.js.map +1 -1
- package/dist/wasm/nodejs/convert_buddy.d.ts +9 -5
- package/dist/wasm/nodejs/convert_buddy.js +28 -19
- package/dist/wasm/nodejs/convert_buddy_bg.wasm +0 -0
- package/dist/wasm/nodejs/convert_buddy_bg.wasm.d.ts +1 -0
- package/dist/wasm/web/convert_buddy.d.ts +10 -5
- package/dist/wasm/web/convert_buddy.js +28 -19
- package/dist/wasm/web/convert_buddy_bg.wasm +0 -0
- package/dist/wasm/web/convert_buddy_bg.wasm.d.ts +1 -0
- package/package.json +1 -1
package/dist/src/browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/browser.ts"],"sourcesContent":["import { ConvertBuddy, type ConvertBuddyOptions, type Format, autoDetectConfig } from \"./index.js\";\r\n\r\nexport * from \"./index.js\";\r\n\r\nexport type BrowserConvertOptions = ConvertBuddyOptions & {\r\n // Additional browser-specific options can go here\r\n};\r\n\r\n/**\r\n * Convert a browser File or Blob object to a string.\r\n * Handles streaming internally using FileReader and web streams.\r\n * \r\n * @example\r\n * // From file input\r\n * const fileInput = document.querySelector('input[type=\"file\"]');\r\n * const file = fileInput.files[0];\r\n * const result = await convertFileToString(file, {\r\n * inputFormat: \"csv\",\r\n * outputFormat: \"json\"\r\n * });\r\n * \r\n * @example\r\n * // With auto-detection\r\n * const result = await convertFileToString(file, {\r\n * inputFormat: \"auto\",\r\n * outputFormat: \"ndjson\"\r\n * });\r\n */\r\nexport async function convertFileToString(\r\n file: File | Blob,\r\n opts: BrowserConvertOptions = {}\r\n): Promise<string> {\r\n const bytes = await convertFile(file, opts);\r\n return new TextDecoder().decode(bytes);\r\n}\r\n\r\n/**\r\n * Convert a browser File or Blob object to a Uint8Array.\r\n * Handles streaming internally using FileReader and web streams.\r\n * \r\n * @example\r\n * const file = fileInput.files[0];\r\n * const result = await convertFile(file, {\r\n * inputFormat: \"csv\",\r\n * outputFormat: \"json\",\r\n * onProgress: (stats) => {\r\n * console.log(`Progress: ${stats.bytesIn} bytes processed`);\r\n * }\r\n * });\r\n */\r\nexport async function convertFile(\r\n file: File | Blob,\r\n opts: BrowserConvertOptions = {}\r\n): Promise<Uint8Array> {\r\n // Handle auto-detection\r\n let actualOpts = { ...opts };\r\n \r\n if (opts.inputFormat === \"auto\") {\r\n // Read a sample for auto-detection\r\n const sampleSize = 256 * 1024; // 256KB\r\n const sampleBlob = file.slice(0, sampleSize);\r\n const sampleBuffer = await sampleBlob.arrayBuffer();\r\n const sample = new Uint8Array(sampleBuffer);\r\n \r\n const detected = await autoDetectConfig(sample, { debug: opts.debug });\r\n \r\n if (detected.format !== \"unknown\") {\r\n actualOpts.inputFormat = detected.format as Format;\r\n \r\n if (detected.csvConfig) {\r\n actualOpts.csvConfig = opts.csvConfig ? { ...detected.csvConfig, ...opts.csvConfig } : detected.csvConfig;\r\n }\r\n \r\n if (detected.xmlConfig) {\r\n actualOpts.xmlConfig = opts.xmlConfig ? { ...detected.xmlConfig, ...opts.xmlConfig } : detected.xmlConfig;\r\n }\r\n \r\n if (opts.debug) {\r\n console.log(\"[convert-buddy] Auto-detected format:\", detected.format);\r\n }\r\n } else {\r\n throw new Error(\"Could not auto-detect input format. Please specify inputFormat explicitly.\");\r\n }\r\n }\r\n \r\n const buddy = await ConvertBuddy.create(actualOpts);\r\n \r\n // Use streams API for efficient processing\r\n const stream = file.stream();\r\n const reader = stream.getReader();\r\n \r\n const chunks: Uint8Array[] = [];\r\n \r\n try {\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n \r\n if (done) break;\r\n \r\n if (buddy.isAborted()) {\r\n throw new Error(\"Conversion aborted\");\r\n }\r\n \r\n const output = buddy.push(value);\r\n if (output.length > 0) {\r\n chunks.push(output);\r\n }\r\n }\r\n \r\n const final = buddy.finish();\r\n if (final.length > 0) {\r\n chunks.push(final);\r\n }\r\n \r\n // Combine all chunks\r\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\r\n const result = new Uint8Array(totalLength);\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 \r\n if (opts.profile) {\r\n console.log(\"[convert-buddy] Performance Stats:\", buddy.stats());\r\n }\r\n \r\n return result;\r\n } catch (error) {\r\n reader.releaseLock();\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Convert a browser File or Blob and download the result as a file.\r\n * \r\n * @example\r\n * const fileInput = document.querySelector('input[type=\"file\"]');\r\n * const file = fileInput.files[0];\r\n * await convertFileToFile(file, \"output.json\", {\r\n * inputFormat: \"csv\",\r\n * outputFormat: \"json\"\r\n * });\r\n */\r\nexport async function convertFileToFile(\r\n inputFile: File | Blob,\r\n outputFilename: string,\r\n opts: BrowserConvertOptions = {}\r\n): Promise<void> {\r\n const result = await convertFile(inputFile, opts);\r\n \r\n // Create a download link\r\n const blob = new Blob([new Uint8Array(result)], { type: \"application/octet-stream\" });\r\n const url = URL.createObjectURL(blob);\r\n \r\n const link = document.createElement(\"a\");\r\n link.href = url;\r\n link.download = outputFilename;\r\n link.style.display = \"none\";\r\n \r\n document.body.appendChild(link);\r\n link.click();\r\n \r\n // Cleanup\r\n setTimeout(() => {\r\n document.body.removeChild(link);\r\n URL.revokeObjectURL(url);\r\n }, 100);\r\n}\r\n\r\n/**\r\n * Create a ReadableStream that converts data on-the-fly from a File or Blob.\r\n * Useful for piping through other stream processors.\r\n * \r\n * @example\r\n * const file = fileInput.files[0];\r\n * const stream = convertFileStream(file, {\r\n * inputFormat: \"csv\",\r\n * outputFormat: \"ndjson\"\r\n * });\r\n * \r\n * const reader = stream.getReader();\r\n * while (true) {\r\n * const { done, value } = await reader.read();\r\n * if (done) break;\r\n * // Process each chunk as it's converted\r\n * console.log(new TextDecoder().decode(value));\r\n * }\r\n */\r\nexport async function convertFileStream(\r\n file: File | Blob,\r\n opts: BrowserConvertOptions = {}\r\n): Promise<ReadableStream<Uint8Array>> {\r\n // Handle auto-detection\r\n let actualOpts = { ...opts };\r\n \r\n if (opts.inputFormat === \"auto\") {\r\n const sampleSize = 256 * 1024;\r\n const sampleBlob = file.slice(0, sampleSize);\r\n const sampleBuffer = await sampleBlob.arrayBuffer();\r\n const sample = new Uint8Array(sampleBuffer);\r\n \r\n const detected = await autoDetectConfig(sample, { debug: opts.debug });\r\n \r\n if (detected.format !== \"unknown\") {\r\n actualOpts.inputFormat = detected.format as Format;\r\n if (detected.csvConfig) {\r\n actualOpts.csvConfig = opts.csvConfig ? { ...detected.csvConfig, ...opts.csvConfig } : detected.csvConfig;\r\n }\r\n if (detected.xmlConfig) {\r\n actualOpts.xmlConfig = opts.xmlConfig ? { ...detected.xmlConfig, ...opts.xmlConfig } : detected.xmlConfig;\r\n }\r\n } else {\r\n throw new Error(\"Could not auto-detect input format.\");\r\n }\r\n }\r\n \r\n const buddy = await ConvertBuddy.create(actualOpts);\r\n const inputStream = file.stream();\r\n \r\n return new ReadableStream<Uint8Array>({\r\n async start(controller) {\r\n const reader = inputStream.getReader();\r\n \r\n try {\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n \r\n if (done) {\r\n const final = buddy.finish();\r\n if (final.length > 0) {\r\n controller.enqueue(final);\r\n }\r\n controller.close();\r\n break;\r\n }\r\n \r\n if (buddy.isAborted()) {\r\n controller.error(new Error(\"Conversion aborted\"));\r\n break;\r\n }\r\n \r\n const output = buddy.push(value);\r\n if (output.length > 0) {\r\n controller.enqueue(output);\r\n }\r\n }\r\n } catch (error) {\r\n controller.error(error);\r\n } finally {\r\n reader.releaseLock();\r\n }\r\n },\r\n });\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/browser.ts"],"sourcesContent":["import { ConvertBuddy, type ConvertBuddyOptions, type ConvertOptions, type Format, autoDetectConfig, detectFormat, getMimeType, getFileTypeConfig, convertAny as convertAnyCore, convertAnyToString as convertAnyToStringCore } from \"./index.js\";\r\n\r\nexport * from \"./index.js\";\r\n\r\nexport type BrowserConvertOptions = ConvertBuddyOptions & {\r\n // Additional browser-specific options can go here\r\n};\r\n\r\n/**\r\n * Ultra-simple convert function for browser.\r\n * Auto-detects input type (File, URL, string, etc.) and format.\r\n * \r\n * @example\r\n * // From File\r\n * const file = fileInput.files[0];\r\n * const result = await convert(file, { outputFormat: \"json\" });\r\n * \r\n * @example\r\n * // From URL\r\n * const result = await convert(\"https://example.com/data.csv\", { outputFormat: \"json\" });\r\n * \r\n * @example\r\n * // From string\r\n * const result = await convert(csvString, { outputFormat: \"json\" });\r\n */\r\nexport async function convert(\r\n input: string | Uint8Array | File | Blob | ReadableStream<Uint8Array>,\r\n opts: ConvertOptions\r\n): Promise<Uint8Array> {\r\n return convertAnyCore(input, opts);\r\n}\r\n\r\n/**\r\n * Ultra-simple convert function that returns a string.\r\n * \r\n * @example\r\n * const json = await convertToString(file, { outputFormat: \"json\" });\r\n * console.log(JSON.parse(json));\r\n */\r\nexport async function convertToString(\r\n input: string | Uint8Array | File | Blob | ReadableStream<Uint8Array>,\r\n opts: ConvertOptions\r\n): Promise<string> {\r\n return convertAnyToStringCore(input, opts);\r\n}\r\n\r\n/**\r\n * Convert a browser File or Blob object to a string.\r\n * Handles streaming internally using FileReader and web streams.\r\n * \r\n * @example\r\n * // From file input\r\n * const fileInput = document.querySelector('input[type=\"file\"]');\r\n * const file = fileInput.files[0];\r\n * const result = await convertFileToString(file, {\r\n * inputFormat: \"csv\",\r\n * outputFormat: \"json\"\r\n * });\r\n * \r\n * @example\r\n * // With auto-detection\r\n * const result = await convertFileToString(file, {\r\n * inputFormat: \"auto\",\r\n * outputFormat: \"ndjson\"\r\n * });\r\n */\r\nexport async function convertFileToString(\r\n file: File | Blob,\r\n opts: BrowserConvertOptions = {}\r\n): Promise<string> {\r\n const bytes = await convertFile(file, opts);\r\n return new TextDecoder().decode(bytes);\r\n}\r\n\r\n/**\r\n * Convert a browser File or Blob object to a Uint8Array.\r\n * Handles streaming internally using FileReader and web streams.\r\n * \r\n * @example\r\n * const file = fileInput.files[0];\r\n * const result = await convertFile(file, {\r\n * inputFormat: \"csv\",\r\n * outputFormat: \"json\",\r\n * onProgress: (stats) => {\r\n * console.log(`Progress: ${stats.bytesIn} bytes processed`);\r\n * }\r\n * });\r\n */\r\nexport async function convertFile(\r\n file: File | Blob,\r\n opts: BrowserConvertOptions = {}\r\n): Promise<Uint8Array> {\r\n // Handle auto-detection\r\n let actualOpts = { ...opts };\r\n \r\n if (opts.inputFormat === \"auto\") {\r\n // Read a sample for auto-detection\r\n const sampleSize = 256 * 1024; // 256KB\r\n const sampleBlob = file.slice(0, sampleSize);\r\n const sampleBuffer = await sampleBlob.arrayBuffer();\r\n const sample = new Uint8Array(sampleBuffer as ArrayBuffer);\r\n \r\n const detected = await autoDetectConfig(sample, { debug: opts.debug });\r\n \r\n if (detected.format !== \"unknown\") {\r\n actualOpts.inputFormat = detected.format as Format;\r\n \r\n if (detected.csvConfig) {\r\n actualOpts.csvConfig = opts.csvConfig ? { ...detected.csvConfig, ...opts.csvConfig } : detected.csvConfig;\r\n }\r\n \r\n if (detected.xmlConfig) {\r\n actualOpts.xmlConfig = opts.xmlConfig ? { ...detected.xmlConfig, ...opts.xmlConfig } : detected.xmlConfig;\r\n }\r\n \r\n if (opts.debug) {\r\n console.log(\"[convert-buddy] Auto-detected format:\", detected.format);\r\n }\r\n } else {\r\n throw new Error(\"Could not auto-detect input format. Please specify inputFormat explicitly.\");\r\n }\r\n }\r\n \r\n // Adaptive chunk sizing based on file size\r\n // Tuned to balance WASM boundary crossing reduction with memory efficiency\r\n if (!actualOpts.chunkTargetBytes) {\r\n const fileSize = file.size;\r\n actualOpts.chunkTargetBytes = Math.max(\r\n 512 * 1024, // minimum: 512KB\r\n Math.min(\r\n 1 * 1024 * 1024, // maximum: 1MB (conservative for memory)\r\n Math.floor(fileSize / 16) // 1/16 of file size\r\n )\r\n );\r\n if (opts.debug) {\r\n console.log(`[convert-buddy] Adaptive chunk sizing: ${fileSize} bytes → ${actualOpts.chunkTargetBytes} byte chunks`);\r\n }\r\n }\r\n \r\n const buddy = await ConvertBuddy.create(actualOpts);\r\n \r\n // Use streams API for efficient processing\r\n const stream = file.stream();\r\n const reader = stream.getReader();\r\n \r\n const chunks: Uint8Array[] = [];\r\n \r\n try {\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n \r\n if (done) break;\r\n \r\n if (buddy.isAborted()) {\r\n throw new Error(\"Conversion aborted\");\r\n }\r\n \r\n const output = buddy.push(value);\r\n if (output.length > 0) {\r\n chunks.push(output);\r\n }\r\n }\r\n \r\n const final = buddy.finish();\r\n if (final.length > 0) {\r\n chunks.push(final);\r\n }\r\n \r\n // Combine all chunks\r\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\r\n const result = new Uint8Array(totalLength);\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 \r\n if (opts.profile) {\r\n console.log(\"[convert-buddy] Performance Stats:\", buddy.stats());\r\n }\r\n \r\n return result;\r\n } catch (error) {\r\n reader.releaseLock();\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Convert a browser File or Blob and download the result as a file.\r\n * \r\n * @example\r\n * const fileInput = document.querySelector('input[type=\"file\"]');\r\n * const file = fileInput.files[0];\r\n * await convertFileToFile(file, \"output.json\", {\r\n * inputFormat: \"csv\",\r\n * outputFormat: \"json\"\r\n * });\r\n */\r\nexport async function convertFileToFile(\r\n inputFile: File | Blob,\r\n outputFilename: string,\r\n opts: BrowserConvertOptions = {}\r\n): Promise<void> {\r\n const result = await convertFile(inputFile, opts);\r\n \r\n // Create a download link\r\n const blob = new Blob([new Uint8Array(result)], { type: \"application/octet-stream\" });\r\n const url = URL.createObjectURL(blob);\r\n \r\n const link = document.createElement(\"a\");\r\n link.href = url;\r\n link.download = outputFilename;\r\n link.style.display = \"none\";\r\n \r\n document.body.appendChild(link);\r\n link.click();\r\n \r\n // Cleanup\r\n setTimeout(() => {\r\n document.body.removeChild(link);\r\n URL.revokeObjectURL(url);\r\n }, 100);\r\n}\r\n\r\n/**\r\n * Create a ReadableStream that converts data on-the-fly from a File or Blob.\r\n * Useful for piping through other stream processors.\r\n * \r\n * @example\r\n * const file = fileInput.files[0];\r\n * const stream = convertFileStream(file, {\r\n * inputFormat: \"csv\",\r\n * outputFormat: \"ndjson\"\r\n * });\r\n * \r\n * const reader = stream.getReader();\r\n * while (true) {\r\n * const { done, value } = await reader.read();\r\n * if (done) break;\r\n * // Process each chunk as it's converted\r\n * console.log(new TextDecoder().decode(value));\r\n * }\r\n */\r\nexport async function convertFileStream(\r\n file: File | Blob,\r\n opts: BrowserConvertOptions = {}\r\n): Promise<ReadableStream<Uint8Array>> {\r\n // Handle auto-detection\r\n let actualOpts = { ...opts };\r\n \r\n if (opts.inputFormat === \"auto\") {\r\n const sampleSize = 256 * 1024;\r\n const sampleBlob = file.slice(0, sampleSize);\r\n const sampleBuffer = await sampleBlob.arrayBuffer();\r\n const sample = new Uint8Array(sampleBuffer);\r\n \r\n const detected = await autoDetectConfig(sample, { debug: opts.debug });\r\n \r\n if (detected.format !== \"unknown\") {\r\n actualOpts.inputFormat = detected.format as Format;\r\n if (detected.csvConfig) {\r\n actualOpts.csvConfig = opts.csvConfig ? { ...detected.csvConfig, ...opts.csvConfig } : detected.csvConfig;\r\n }\r\n if (detected.xmlConfig) {\r\n actualOpts.xmlConfig = opts.xmlConfig ? { ...detected.xmlConfig, ...opts.xmlConfig } : detected.xmlConfig;\r\n }\r\n } else {\r\n throw new Error(\"Could not auto-detect input format.\");\r\n }\r\n }\r\n \r\n const buddy = await ConvertBuddy.create(actualOpts);\r\n const inputStream = file.stream();\r\n \r\n return new ReadableStream<Uint8Array>({\r\n async start(controller) {\r\n const reader = inputStream.getReader();\r\n \r\n try {\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n \r\n if (done) {\r\n const final = buddy.finish();\r\n if (final.length > 0) {\r\n controller.enqueue(final);\r\n }\r\n controller.close();\r\n break;\r\n }\r\n \r\n if (buddy.isAborted()) {\r\n controller.error(new Error(\"Conversion aborted\"));\r\n break;\r\n }\r\n \r\n const output = buddy.push(value);\r\n if (output.length > 0) {\r\n controller.enqueue(output);\r\n }\r\n }\r\n } catch (error) {\r\n controller.error(error);\r\n } finally {\r\n reader.releaseLock();\r\n }\r\n },\r\n });\r\n}\r\n/**\r\n * Auto-detect format and create a ReadableStream for conversion.\r\n * This is a convenience helper that combines format detection with streaming conversion.\r\n * \r\n * @example\r\n * const file = fileInput.files[0];\r\n * const stream = await autoConvertStream(file, { outputFormat: \"json\" });\r\n * \r\n * // Pipe to response\r\n * return new Response(stream);\r\n */\r\nexport async function autoConvertStream(\r\n file: File | Blob,\r\n opts: Omit<BrowserConvertOptions, \"inputFormat\"> & { outputFormat: Format }\r\n): Promise<ReadableStream<Uint8Array>> {\r\n return convertFileStream(file, {\r\n ...opts,\r\n inputFormat: \"auto\",\r\n });\r\n}\r\n\r\n/**\r\n * Stream a file conversion directly to a writable destination.\r\n * This is useful for streaming large conversions to disk using File System Access API\r\n * or to other writable streams.\r\n * \r\n * @example\r\n * // Using File System Access API\r\n * const fileInput = document.querySelector('input[type=\"file\"]');\r\n * const file = fileInput.files[0];\r\n * \r\n * const fileHandle = await window.showSaveFilePicker({\r\n * suggestedName: \"output.json\",\r\n * types: [{ description: \"JSON\", accept: { \"application/json\": [\".json\"] } }]\r\n * });\r\n * const writable = await fileHandle.createWritable();\r\n * \r\n * await convertStreamToWritable(file, writable, {\r\n * inputFormat: \"csv\",\r\n * outputFormat: \"json\",\r\n * onProgress: (stats) => console.log(`${stats.bytesIn} bytes processed`)\r\n * });\r\n * \r\n * @example\r\n * // With auto-detection\r\n * await convertStreamToWritable(file, writable, {\r\n * inputFormat: \"auto\",\r\n * outputFormat: \"ndjson\"\r\n * });\r\n */\r\nexport async function convertStreamToWritable(\r\n file: File | Blob,\r\n writable: WritableStream<Uint8Array> | FileSystemWritableFileStream,\r\n opts: BrowserConvertOptions = {}\r\n): Promise<void> {\r\n const outputStream = await convertFileStream(file, opts);\r\n await outputStream.pipeTo(writable);\r\n}\r\n\r\n/**\r\n * Check if File System Access API is supported in the current browser.\r\n * Use this to determine if you can use File System Access API features.\r\n * \r\n * @example\r\n * if (isFileSystemAccessSupported()) {\r\n * // Use File System Access API\r\n * const handle = await window.showSaveFilePicker();\r\n * } else {\r\n * // Fall back to download link\r\n * await convertFileToFile(file, \"output.json\", opts);\r\n * }\r\n */\r\nexport function isFileSystemAccessSupported(): boolean {\r\n return (\r\n typeof window !== \"undefined\" &&\r\n \"showSaveFilePicker\" in window &&\r\n \"showOpenFilePicker\" in window\r\n );\r\n}\r\n\r\n/**\r\n * Convert a file and save it using File System Access API with a user-selected location.\r\n * This provides a better UX than automatic downloads by letting users choose where to save.\r\n * Falls back to regular download if File System Access API is not supported.\r\n * \r\n * @example\r\n * const file = fileInput.files[0];\r\n * await convertAndSave(file, {\r\n * inputFormat: \"csv\",\r\n * outputFormat: \"json\",\r\n * suggestedName: \"output.json\"\r\n * });\r\n */\r\nexport async function convertAndSave(\r\n file: File | Blob,\r\n opts: BrowserConvertOptions & {\r\n suggestedName?: string;\r\n } = {}\r\n): Promise<void> {\r\n if (!isFileSystemAccessSupported()) {\r\n // Fall back to regular download\r\n const filename = opts.suggestedName || \"converted\";\r\n await convertFileToFile(file, filename, opts);\r\n return;\r\n }\r\n\r\n const outputFormat = opts.outputFormat || \"json\";\r\n const suggestedName = opts.suggestedName || `converted.${outputFormat}`;\r\n const types = getFileTypeConfig(outputFormat);\r\n\r\n try {\r\n const fileHandle = await (window as any).showSaveFilePicker({\r\n suggestedName,\r\n types,\r\n });\r\n\r\n const writable = await fileHandle.createWritable();\r\n await convertStreamToWritable(file, writable, opts);\r\n } catch (error: any) {\r\n // User cancelled or error occurred\r\n if (error?.name === \"AbortError\") {\r\n // User cancelled - this is fine, just return\r\n return;\r\n }\r\n // Re-throw other errors\r\n throw error;\r\n }\r\n}"],"mappings":"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","names":[]}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -20,11 +20,19 @@ type ConvertBuddyOptions = {
|
|
|
20
20
|
outputFormat?: Format;
|
|
21
21
|
chunkTargetBytes?: number;
|
|
22
22
|
parallelism?: number;
|
|
23
|
+
maxMemoryMB?: number;
|
|
23
24
|
csvConfig?: CsvConfig;
|
|
24
25
|
xmlConfig?: XmlConfig;
|
|
25
26
|
onProgress?: ProgressCallback;
|
|
26
27
|
progressIntervalBytes?: number;
|
|
27
28
|
};
|
|
29
|
+
type ConvertOptions = {
|
|
30
|
+
inputFormat?: Format | "auto";
|
|
31
|
+
outputFormat: Format;
|
|
32
|
+
csvConfig?: CsvConfig;
|
|
33
|
+
xmlConfig?: XmlConfig;
|
|
34
|
+
onProgress?: ProgressCallback;
|
|
35
|
+
};
|
|
28
36
|
type CsvConfig = {
|
|
29
37
|
delimiter?: string;
|
|
30
38
|
quote?: string;
|
|
@@ -58,7 +66,43 @@ declare class ConvertBuddy {
|
|
|
58
66
|
private onProgress?;
|
|
59
67
|
private progressIntervalBytes;
|
|
60
68
|
private lastProgressBytes;
|
|
61
|
-
private
|
|
69
|
+
private globalConfig;
|
|
70
|
+
private initialized;
|
|
71
|
+
simd: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Create a new ConvertBuddy instance with global configuration.
|
|
74
|
+
* This is useful when you want to set memory limits, debug mode, or other global settings.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* const buddy = new ConvertBuddy({ maxMemoryMB: 512, debug: true });
|
|
78
|
+
* const result = await buddy.convert(input, { outputFormat: "json" });
|
|
79
|
+
*/
|
|
80
|
+
constructor(opts?: ConvertBuddyOptions);
|
|
81
|
+
/**
|
|
82
|
+
* Convert input (string, Buffer, File, URL, etc.) to the desired output format.
|
|
83
|
+
* This is the main method for the new simplified API.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* // Auto-detect everything
|
|
87
|
+
* const buddy = new ConvertBuddy();
|
|
88
|
+
* const result = await buddy.convert("https://example.com/data.csv", { outputFormat: "json" });
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* // With configuration
|
|
92
|
+
* const buddy = new ConvertBuddy({ maxMemoryMB: 512 });
|
|
93
|
+
* const result = await buddy.convert(file, { inputFormat: "csv", outputFormat: "json" });
|
|
94
|
+
*/
|
|
95
|
+
convert(input: string | Uint8Array | File | Blob | ReadableStream<Uint8Array>, opts: ConvertOptions): Promise<Uint8Array>;
|
|
96
|
+
private convertFromUrl;
|
|
97
|
+
private convertFromString;
|
|
98
|
+
private convertFromBuffer;
|
|
99
|
+
private convertFromFile;
|
|
100
|
+
private convertFromBlob;
|
|
101
|
+
private convertFromStream;
|
|
102
|
+
/**
|
|
103
|
+
* Legacy create method for backward compatibility.
|
|
104
|
+
* Prefer using the constructor: new ConvertBuddy(opts)
|
|
105
|
+
*/
|
|
62
106
|
static create(opts?: ConvertBuddyOptions): Promise<ConvertBuddy>;
|
|
63
107
|
push(chunk: Uint8Array): Uint8Array;
|
|
64
108
|
finish(): Uint8Array;
|
|
@@ -84,5 +128,71 @@ declare class ConvertBuddyTransformStream extends TransformStream<Uint8Array, Ui
|
|
|
84
128
|
}
|
|
85
129
|
declare function convert(input: Uint8Array | string, opts?: ConvertBuddyOptions): Promise<Uint8Array>;
|
|
86
130
|
declare function convertToString(input: Uint8Array | string, opts?: ConvertBuddyOptions): Promise<string>;
|
|
131
|
+
/**
|
|
132
|
+
* Ultra-simple standalone convert function with auto-detection.
|
|
133
|
+
* Accepts any input type (URL, File, Buffer, string, stream) and automatically detects format.
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* // From URL
|
|
137
|
+
* import { convertAny } from "convert-buddy-js";
|
|
138
|
+
* const result = await convertAny("https://example.com/data.csv", { outputFormat: "json" });
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* // From File (browser)
|
|
142
|
+
* const file = fileInput.files[0];
|
|
143
|
+
* const result = await convertAny(file, { outputFormat: "ndjson" });
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* // From string data
|
|
147
|
+
* const result = await convertAny('{"name":"Ada"}', { outputFormat: "csv" });
|
|
148
|
+
*/
|
|
149
|
+
declare function convertAny(input: string | Uint8Array | File | Blob | ReadableStream<Uint8Array>, opts: ConvertOptions): Promise<Uint8Array>;
|
|
150
|
+
/**
|
|
151
|
+
* Ultra-simple standalone convert function that returns a string.
|
|
152
|
+
* Same as convertAny but decodes the output to a string.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* import { convertAnyToString } from "convert-buddy-js";
|
|
156
|
+
* const json = await convertAnyToString("https://example.com/data.csv", { outputFormat: "json" });
|
|
157
|
+
* console.log(JSON.parse(json));
|
|
158
|
+
*/
|
|
159
|
+
declare function convertAnyToString(input: string | Uint8Array | File | Blob | ReadableStream<Uint8Array>, opts: ConvertOptions): Promise<string>;
|
|
160
|
+
/**
|
|
161
|
+
* Get MIME type for a given format
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* const mimeType = getMimeType("json"); // "application/json"
|
|
165
|
+
*/
|
|
166
|
+
declare function getMimeType(format: Format): string;
|
|
167
|
+
/**
|
|
168
|
+
* Get file extension for a given format (without the dot)
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* const ext = getExtension("json"); // "json"
|
|
172
|
+
*/
|
|
173
|
+
declare function getExtension(format: Format): string;
|
|
174
|
+
/**
|
|
175
|
+
* Get suggested filename for a converted file
|
|
176
|
+
*
|
|
177
|
+
* @param originalName - Original filename
|
|
178
|
+
* @param outputFormat - Target format
|
|
179
|
+
* @param includeTimestamp - Whether to include a timestamp (default: false)
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* const name = getSuggestedFilename("data.csv", "json"); // "data.json"
|
|
183
|
+
* const name = getSuggestedFilename("data.csv", "json", true); // "data_converted_1234567890.json"
|
|
184
|
+
*/
|
|
185
|
+
declare function getSuggestedFilename(originalName: string, outputFormat: Format, includeTimestamp?: boolean): string;
|
|
186
|
+
/**
|
|
187
|
+
* Get File System Access API file type configuration for showSaveFilePicker
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* const types = getFileTypeConfig("json");
|
|
191
|
+
* const handle = await showSaveFilePicker({ types });
|
|
192
|
+
*/
|
|
193
|
+
declare function getFileTypeConfig(format: Format): Array<{
|
|
194
|
+
description: string;
|
|
195
|
+
accept: Record<string, string[]>;
|
|
196
|
+
}>;
|
|
87
197
|
|
|
88
|
-
export { ConvertBuddy, type ConvertBuddyOptions, ConvertBuddyTransformStream, type CsvConfig, type CsvDetection, type DetectInput, type DetectOptions, type Format, type ProgressCallback, type Stats, type XmlConfig, type XmlDetection, autoDetectConfig, convert, convertToString, detectCsvFieldsAndDelimiter, detectFormat, detectXmlElements };
|
|
198
|
+
export { ConvertBuddy, type ConvertBuddyOptions, ConvertBuddyTransformStream, type ConvertOptions, type CsvConfig, type CsvDetection, type DetectInput, type DetectOptions, type Format, type ProgressCallback, type Stats, type XmlConfig, type XmlDetection, autoDetectConfig, convert, convertAny, convertAnyToString, convertToString, detectCsvFieldsAndDelimiter, detectFormat, detectXmlElements, getExtension, getFileTypeConfig, getMimeType, getSuggestedFilename };
|
package/dist/src/index.js
CHANGED
|
@@ -1,14 +1,53 @@
|
|
|
1
|
+
let wasmModuleInstance = null;
|
|
2
|
+
let wasmModuleLoadPromise = null;
|
|
1
3
|
async function loadWasmModule() {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
if (wasmModuleInstance) {
|
|
5
|
+
return wasmModuleInstance;
|
|
6
|
+
}
|
|
7
|
+
if (wasmModuleLoadPromise) {
|
|
8
|
+
return wasmModuleLoadPromise;
|
|
9
|
+
}
|
|
10
|
+
wasmModuleLoadPromise = (async () => {
|
|
11
|
+
const isNode = typeof process !== "undefined" && !!process.versions?.node;
|
|
12
|
+
if (isNode) {
|
|
13
|
+
const { createRequire } = await import("node:module");
|
|
14
|
+
const require2 = createRequire(import.meta.url);
|
|
15
|
+
const mod2 = require2("../../wasm-node.cjs");
|
|
16
|
+
return mod2;
|
|
17
|
+
}
|
|
18
|
+
const wasmUrl = new URL("../wasm/web/convert_buddy.js", import.meta.url);
|
|
19
|
+
const mod = await import(wasmUrl.href);
|
|
20
|
+
return mod;
|
|
21
|
+
})();
|
|
22
|
+
try {
|
|
23
|
+
wasmModuleInstance = await wasmModuleLoadPromise;
|
|
24
|
+
return wasmModuleInstance;
|
|
25
|
+
} finally {
|
|
26
|
+
wasmModuleLoadPromise = null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
let wasmInitialized = false;
|
|
30
|
+
let wasmInitPromise = null;
|
|
31
|
+
async function initWasm(debug) {
|
|
32
|
+
if (wasmInitialized) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (wasmInitPromise) {
|
|
36
|
+
return wasmInitPromise;
|
|
37
|
+
}
|
|
38
|
+
wasmInitPromise = (async () => {
|
|
39
|
+
const wasmModule = await loadWasmModule();
|
|
40
|
+
if (typeof wasmModule.default === "function") {
|
|
41
|
+
await wasmModule.default();
|
|
42
|
+
}
|
|
43
|
+
wasmModule.init(debug);
|
|
44
|
+
wasmInitialized = true;
|
|
45
|
+
})();
|
|
46
|
+
try {
|
|
47
|
+
await wasmInitPromise;
|
|
48
|
+
} finally {
|
|
49
|
+
wasmInitPromise = null;
|
|
50
|
+
}
|
|
12
51
|
}
|
|
13
52
|
class ConvertBuddy {
|
|
14
53
|
converter;
|
|
@@ -19,26 +58,262 @@ class ConvertBuddy {
|
|
|
19
58
|
onProgress;
|
|
20
59
|
progressIntervalBytes;
|
|
21
60
|
lastProgressBytes = 0;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
61
|
+
globalConfig;
|
|
62
|
+
initialized = false;
|
|
63
|
+
simd;
|
|
64
|
+
/**
|
|
65
|
+
* Create a new ConvertBuddy instance with global configuration.
|
|
66
|
+
* This is useful when you want to set memory limits, debug mode, or other global settings.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* const buddy = new ConvertBuddy({ maxMemoryMB: 512, debug: true });
|
|
70
|
+
* const result = await buddy.convert(input, { outputFormat: "json" });
|
|
71
|
+
*/
|
|
72
|
+
constructor(opts = {}) {
|
|
73
|
+
this.debug = !!opts.debug;
|
|
74
|
+
this.profile = !!opts.profile;
|
|
75
|
+
this.simd = false;
|
|
76
|
+
this.globalConfig = opts;
|
|
27
77
|
this.progressIntervalBytes = opts.progressIntervalBytes || 1024 * 1024;
|
|
78
|
+
this.onProgress = opts.onProgress;
|
|
79
|
+
this.converter = null;
|
|
80
|
+
this.initialized = false;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Convert input (string, Buffer, File, URL, etc.) to the desired output format.
|
|
84
|
+
* This is the main method for the new simplified API.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* // Auto-detect everything
|
|
88
|
+
* const buddy = new ConvertBuddy();
|
|
89
|
+
* const result = await buddy.convert("https://example.com/data.csv", { outputFormat: "json" });
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* // With configuration
|
|
93
|
+
* const buddy = new ConvertBuddy({ maxMemoryMB: 512 });
|
|
94
|
+
* const result = await buddy.convert(file, { inputFormat: "csv", outputFormat: "json" });
|
|
95
|
+
*/
|
|
96
|
+
async convert(input, opts) {
|
|
97
|
+
const mergedOpts = {
|
|
98
|
+
...this.globalConfig,
|
|
99
|
+
...opts,
|
|
100
|
+
inputFormat: opts.inputFormat || this.globalConfig.inputFormat || "auto"
|
|
101
|
+
};
|
|
102
|
+
if (typeof input === "string") {
|
|
103
|
+
if (input.startsWith("http://") || input.startsWith("https://")) {
|
|
104
|
+
return this.convertFromUrl(input, mergedOpts);
|
|
105
|
+
} else {
|
|
106
|
+
return this.convertFromString(input, mergedOpts);
|
|
107
|
+
}
|
|
108
|
+
} else if (input instanceof Uint8Array) {
|
|
109
|
+
return this.convertFromBuffer(input, mergedOpts);
|
|
110
|
+
} else if (typeof File !== "undefined" && input instanceof File) {
|
|
111
|
+
return this.convertFromFile(input, mergedOpts);
|
|
112
|
+
} else if (typeof Blob !== "undefined" && input instanceof Blob) {
|
|
113
|
+
return this.convertFromBlob(input, mergedOpts);
|
|
114
|
+
} else if (typeof ReadableStream !== "undefined" && input instanceof ReadableStream) {
|
|
115
|
+
return this.convertFromStream(input, mergedOpts);
|
|
116
|
+
} else {
|
|
117
|
+
throw new Error("Unsupported input type");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async convertFromUrl(url, opts) {
|
|
121
|
+
const response = await fetch(url);
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
|
|
124
|
+
}
|
|
125
|
+
const stream = response.body;
|
|
126
|
+
if (!stream) {
|
|
127
|
+
throw new Error("Response body is null");
|
|
128
|
+
}
|
|
129
|
+
return this.convertFromStream(stream, opts);
|
|
130
|
+
}
|
|
131
|
+
async convertFromString(input, opts) {
|
|
132
|
+
const inputBytes = new TextEncoder().encode(input);
|
|
133
|
+
return this.convertFromBuffer(inputBytes, opts);
|
|
134
|
+
}
|
|
135
|
+
async convertFromBuffer(input, opts) {
|
|
136
|
+
let actualOpts = { ...opts };
|
|
137
|
+
if (opts.inputFormat === "auto") {
|
|
138
|
+
const detected = await autoDetectConfig(input, { debug: opts.debug });
|
|
139
|
+
if (detected.format !== "unknown") {
|
|
140
|
+
actualOpts.inputFormat = detected.format;
|
|
141
|
+
if (detected.csvConfig) {
|
|
142
|
+
actualOpts.csvConfig = opts.csvConfig ? { ...detected.csvConfig, ...opts.csvConfig } : detected.csvConfig;
|
|
143
|
+
}
|
|
144
|
+
if (detected.xmlConfig) {
|
|
145
|
+
actualOpts.xmlConfig = opts.xmlConfig ? { ...detected.xmlConfig, ...opts.xmlConfig } : detected.xmlConfig;
|
|
146
|
+
}
|
|
147
|
+
if (opts.debug) {
|
|
148
|
+
console.log("[convert-buddy] Auto-detected format:", detected.format);
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
throw new Error("Could not auto-detect input format. Please specify inputFormat explicitly.");
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const buddy = await ConvertBuddy.create(actualOpts);
|
|
155
|
+
const output = buddy.push(input);
|
|
156
|
+
const final = buddy.finish();
|
|
157
|
+
const result = new Uint8Array(output.length + final.length);
|
|
158
|
+
result.set(output, 0);
|
|
159
|
+
result.set(final, output.length);
|
|
160
|
+
if (opts.profile) {
|
|
161
|
+
const stats = buddy.stats();
|
|
162
|
+
console.log("[convert-buddy] Performance Stats:", stats);
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
async convertFromFile(file, opts) {
|
|
167
|
+
return this.convertFromBlob(file, opts);
|
|
168
|
+
}
|
|
169
|
+
async convertFromBlob(blob, opts) {
|
|
170
|
+
let actualOpts = { ...opts };
|
|
171
|
+
if (opts.inputFormat === "auto") {
|
|
172
|
+
const sampleSize = 256 * 1024;
|
|
173
|
+
const sampleBlob = blob.slice(0, sampleSize);
|
|
174
|
+
const sampleBuffer = await sampleBlob.arrayBuffer();
|
|
175
|
+
const sample = new Uint8Array(sampleBuffer);
|
|
176
|
+
const detected = await autoDetectConfig(sample, { debug: opts.debug });
|
|
177
|
+
if (detected.format !== "unknown") {
|
|
178
|
+
actualOpts.inputFormat = detected.format;
|
|
179
|
+
if (detected.csvConfig) {
|
|
180
|
+
actualOpts.csvConfig = opts.csvConfig ? { ...detected.csvConfig, ...opts.csvConfig } : detected.csvConfig;
|
|
181
|
+
}
|
|
182
|
+
if (detected.xmlConfig) {
|
|
183
|
+
actualOpts.xmlConfig = opts.xmlConfig ? { ...detected.xmlConfig, ...opts.xmlConfig } : detected.xmlConfig;
|
|
184
|
+
}
|
|
185
|
+
if (opts.debug) {
|
|
186
|
+
console.log("[convert-buddy] Auto-detected format:", detected.format);
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
throw new Error("Could not auto-detect input format. Please specify inputFormat explicitly.");
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
const buddy = await ConvertBuddy.create(actualOpts);
|
|
193
|
+
const stream = blob.stream();
|
|
194
|
+
const reader = stream.getReader();
|
|
195
|
+
const outputs = [];
|
|
196
|
+
try {
|
|
197
|
+
while (true) {
|
|
198
|
+
const { done, value } = await reader.read();
|
|
199
|
+
if (done) break;
|
|
200
|
+
const output = buddy.push(value);
|
|
201
|
+
if (output.length > 0) {
|
|
202
|
+
outputs.push(output);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const final = buddy.finish();
|
|
206
|
+
if (final.length > 0) {
|
|
207
|
+
outputs.push(final);
|
|
208
|
+
}
|
|
209
|
+
const totalLength = outputs.reduce((sum, arr) => sum + arr.length, 0);
|
|
210
|
+
const result = new Uint8Array(totalLength);
|
|
211
|
+
let offset = 0;
|
|
212
|
+
for (const output of outputs) {
|
|
213
|
+
result.set(output, offset);
|
|
214
|
+
offset += output.length;
|
|
215
|
+
}
|
|
216
|
+
if (opts.profile) {
|
|
217
|
+
const stats = buddy.stats();
|
|
218
|
+
console.log("[convert-buddy] Performance Stats:", stats);
|
|
219
|
+
}
|
|
220
|
+
return result;
|
|
221
|
+
} finally {
|
|
222
|
+
reader.releaseLock();
|
|
223
|
+
}
|
|
28
224
|
}
|
|
225
|
+
async convertFromStream(stream, opts) {
|
|
226
|
+
let actualOpts = { ...opts };
|
|
227
|
+
let firstChunks = [];
|
|
228
|
+
let totalSampleBytes = 0;
|
|
229
|
+
const maxSampleSize = 256 * 1024;
|
|
230
|
+
if (opts.inputFormat === "auto") {
|
|
231
|
+
const reader2 = stream.getReader();
|
|
232
|
+
try {
|
|
233
|
+
while (totalSampleBytes < maxSampleSize) {
|
|
234
|
+
const { done, value } = await reader2.read();
|
|
235
|
+
if (done || !value) break;
|
|
236
|
+
firstChunks.push(value);
|
|
237
|
+
totalSampleBytes += value.length;
|
|
238
|
+
}
|
|
239
|
+
const sample = new Uint8Array(totalSampleBytes);
|
|
240
|
+
let offset = 0;
|
|
241
|
+
for (const chunk of firstChunks) {
|
|
242
|
+
sample.set(chunk, offset);
|
|
243
|
+
offset += chunk.length;
|
|
244
|
+
}
|
|
245
|
+
const detected = await autoDetectConfig(sample, { debug: opts.debug });
|
|
246
|
+
if (detected.format !== "unknown") {
|
|
247
|
+
actualOpts.inputFormat = detected.format;
|
|
248
|
+
if (detected.csvConfig) {
|
|
249
|
+
actualOpts.csvConfig = opts.csvConfig ? { ...detected.csvConfig, ...opts.csvConfig } : detected.csvConfig;
|
|
250
|
+
}
|
|
251
|
+
if (detected.xmlConfig) {
|
|
252
|
+
actualOpts.xmlConfig = opts.xmlConfig ? { ...detected.xmlConfig, ...opts.xmlConfig } : detected.xmlConfig;
|
|
253
|
+
}
|
|
254
|
+
if (opts.debug) {
|
|
255
|
+
console.log("[convert-buddy] Auto-detected format:", detected.format);
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
throw new Error("Could not auto-detect input format. Please specify inputFormat explicitly.");
|
|
259
|
+
}
|
|
260
|
+
} finally {
|
|
261
|
+
reader2.releaseLock();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const buddy = await ConvertBuddy.create(actualOpts);
|
|
265
|
+
const outputs = [];
|
|
266
|
+
for (const chunk of firstChunks) {
|
|
267
|
+
const output = buddy.push(chunk);
|
|
268
|
+
if (output.length > 0) {
|
|
269
|
+
outputs.push(output);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
const reader = stream.getReader();
|
|
273
|
+
try {
|
|
274
|
+
while (true) {
|
|
275
|
+
const { done, value } = await reader.read();
|
|
276
|
+
if (done) break;
|
|
277
|
+
const output = buddy.push(value);
|
|
278
|
+
if (output.length > 0) {
|
|
279
|
+
outputs.push(output);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
const final = buddy.finish();
|
|
283
|
+
if (final.length > 0) {
|
|
284
|
+
outputs.push(final);
|
|
285
|
+
}
|
|
286
|
+
const totalLength = outputs.reduce((sum, arr) => sum + arr.length, 0);
|
|
287
|
+
const result = new Uint8Array(totalLength);
|
|
288
|
+
let offset = 0;
|
|
289
|
+
for (const output of outputs) {
|
|
290
|
+
result.set(output, offset);
|
|
291
|
+
offset += output.length;
|
|
292
|
+
}
|
|
293
|
+
if (opts.profile) {
|
|
294
|
+
const stats = buddy.stats();
|
|
295
|
+
console.log("[convert-buddy] Performance Stats:", stats);
|
|
296
|
+
}
|
|
297
|
+
return result;
|
|
298
|
+
} finally {
|
|
299
|
+
reader.releaseLock();
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Legacy create method for backward compatibility.
|
|
304
|
+
* Prefer using the constructor: new ConvertBuddy(opts)
|
|
305
|
+
*/
|
|
29
306
|
static async create(opts = {}) {
|
|
30
307
|
const debug = !!opts.debug;
|
|
31
308
|
const profile = !!opts.profile;
|
|
309
|
+
await initWasm(debug);
|
|
32
310
|
const wasmModule = await loadWasmModule();
|
|
33
|
-
if (typeof wasmModule.default === "function") {
|
|
34
|
-
await wasmModule.default();
|
|
35
|
-
}
|
|
36
|
-
wasmModule.init(debug);
|
|
37
311
|
let inputFormat = opts.inputFormat;
|
|
38
312
|
let csvConfig = opts.csvConfig;
|
|
39
313
|
if (inputFormat === "auto") {
|
|
40
314
|
inputFormat = void 0;
|
|
41
315
|
}
|
|
316
|
+
const chunkTargetBytes = opts.chunkTargetBytes || 512 * 1024;
|
|
42
317
|
let converter;
|
|
43
318
|
if (inputFormat && opts.outputFormat) {
|
|
44
319
|
const Converter = wasmModule.Converter;
|
|
@@ -46,7 +321,7 @@ class ConvertBuddy {
|
|
|
46
321
|
debug,
|
|
47
322
|
inputFormat,
|
|
48
323
|
opts.outputFormat,
|
|
49
|
-
|
|
324
|
+
chunkTargetBytes,
|
|
50
325
|
profile,
|
|
51
326
|
csvConfig || null,
|
|
52
327
|
opts.xmlConfig || null
|
|
@@ -54,8 +329,13 @@ class ConvertBuddy {
|
|
|
54
329
|
} else {
|
|
55
330
|
converter = new wasmModule.Converter(debug);
|
|
56
331
|
}
|
|
57
|
-
|
|
58
|
-
|
|
332
|
+
const simdEnabled = wasmModule.getSimdEnabled?.() ?? false;
|
|
333
|
+
if (debug) console.log("[convert-buddy-js] initialized with chunkTargetBytes:", chunkTargetBytes, "simd:", simdEnabled, opts);
|
|
334
|
+
const instance = new ConvertBuddy(opts);
|
|
335
|
+
instance.converter = converter;
|
|
336
|
+
instance.simd = simdEnabled;
|
|
337
|
+
instance.initialized = true;
|
|
338
|
+
return instance;
|
|
59
339
|
}
|
|
60
340
|
push(chunk) {
|
|
61
341
|
if (this.aborted) {
|
|
@@ -259,14 +539,61 @@ async function convertToString(input, opts = {}) {
|
|
|
259
539
|
const result = await convert(input, opts);
|
|
260
540
|
return new TextDecoder().decode(result);
|
|
261
541
|
}
|
|
542
|
+
async function convertAny(input, opts) {
|
|
543
|
+
const buddy = new ConvertBuddy();
|
|
544
|
+
return buddy.convert(input, opts);
|
|
545
|
+
}
|
|
546
|
+
async function convertAnyToString(input, opts) {
|
|
547
|
+
const result = await convertAny(input, opts);
|
|
548
|
+
return new TextDecoder().decode(result);
|
|
549
|
+
}
|
|
550
|
+
function getMimeType(format) {
|
|
551
|
+
switch (format) {
|
|
552
|
+
case "json":
|
|
553
|
+
return "application/json";
|
|
554
|
+
case "ndjson":
|
|
555
|
+
return "application/x-ndjson";
|
|
556
|
+
case "csv":
|
|
557
|
+
return "text/csv";
|
|
558
|
+
case "xml":
|
|
559
|
+
return "application/xml";
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
function getExtension(format) {
|
|
563
|
+
return format;
|
|
564
|
+
}
|
|
565
|
+
function getSuggestedFilename(originalName, outputFormat, includeTimestamp = false) {
|
|
566
|
+
const baseName = originalName.replace(/\.[^/.]+$/, "");
|
|
567
|
+
const extension = getExtension(outputFormat);
|
|
568
|
+
if (includeTimestamp) {
|
|
569
|
+
return `${baseName}_converted_${Date.now()}.${extension}`;
|
|
570
|
+
}
|
|
571
|
+
return `${baseName}.${extension}`;
|
|
572
|
+
}
|
|
573
|
+
function getFileTypeConfig(format) {
|
|
574
|
+
const mimeType = getMimeType(format);
|
|
575
|
+
const extension = `.${getExtension(format)}`;
|
|
576
|
+
return [
|
|
577
|
+
{
|
|
578
|
+
description: `${format.toUpperCase()} Files`,
|
|
579
|
+
accept: { [mimeType]: [extension] }
|
|
580
|
+
}
|
|
581
|
+
];
|
|
582
|
+
}
|
|
262
583
|
export {
|
|
263
584
|
ConvertBuddy,
|
|
264
585
|
ConvertBuddyTransformStream,
|
|
265
586
|
autoDetectConfig,
|
|
266
587
|
convert,
|
|
588
|
+
convertAny,
|
|
589
|
+
convertAnyToString,
|
|
267
590
|
convertToString,
|
|
268
591
|
detectCsvFieldsAndDelimiter,
|
|
269
592
|
detectFormat,
|
|
270
|
-
detectXmlElements
|
|
593
|
+
detectXmlElements,
|
|
594
|
+
getExtension,
|
|
595
|
+
getFileTypeConfig,
|
|
596
|
+
getMimeType,
|
|
597
|
+
getSuggestedFilename
|
|
271
598
|
};
|
|
272
599
|
//# sourceMappingURL=index.js.map
|