convert-buddy-js 0.10.5 → 0.10.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/dist/browser.js +46 -15
- package/dist/browser.js.map +1 -1
- package/dist/wasm/nodejs/convert_buddy_bg.wasm +0 -0
- package/dist/wasm/web/convert_buddy_bg.wasm +0 -0
- package/package.json +9 -2
- package/dist/index.js +0 -954
- package/dist/index.js.map +0 -1
- package/dist/node.js +0 -379
- package/dist/node.js.map +0 -1
- package/dist/nodejs-thread-pool.js +0 -229
- package/dist/nodejs-thread-pool.js.map +0 -1
- package/dist/streaming-worker.js +0 -72
- package/dist/streaming-worker.js.map +0 -1
- package/dist/tests/edge-cases/control-features.test.js +0 -87
- package/dist/tests/edge-cases/control-features.test.js.map +0 -1
- package/dist/tests/edge-cases/csv-edge-cases.test.js +0 -594
- package/dist/tests/edge-cases/csv-edge-cases.test.js.map +0 -1
- package/dist/tests/edge-cases/detection.test.js +0 -229
- package/dist/tests/edge-cases/detection.test.js.map +0 -1
- package/dist/tests/edge-cases/error-handling.test.js +0 -448
- package/dist/tests/edge-cases/error-handling.test.js.map +0 -1
- package/dist/tests/edge-cases/ndjson-edge-cases.test.js +0 -572
- package/dist/tests/edge-cases/ndjson-edge-cases.test.js.map +0 -1
- package/dist/tests/edge-cases/node-helpers.test.js +0 -147
- package/dist/tests/edge-cases/node-helpers.test.js.map +0 -1
- package/dist/tests/edge-cases/roundtrip.test.js +0 -147
- package/dist/tests/edge-cases/roundtrip.test.js.map +0 -1
- package/dist/tests/streaming/large-file-stream.test.js +0 -205
- package/dist/tests/streaming/large-file-stream.test.js.map +0 -1
- package/dist/tests/streaming/record-counting.test.js +0 -186
- package/dist/tests/streaming/record-counting.test.js.map +0 -1
- package/dist/tests/streaming/stats-object.test.js +0 -216
- package/dist/tests/streaming/stats-object.test.js.map +0 -1
- package/dist/thread-pool.js +0 -154
- package/dist/thread-pool.js.map +0 -1
package/dist/browser.js
CHANGED
|
@@ -1,8 +1,40 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __objRest = (source, exclude) => {
|
|
21
|
+
var target = {};
|
|
22
|
+
for (var prop in source)
|
|
23
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
24
|
+
target[prop] = source[prop];
|
|
25
|
+
if (source != null && __getOwnPropSymbols)
|
|
26
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
27
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
28
|
+
target[prop] = source[prop];
|
|
29
|
+
}
|
|
30
|
+
return target;
|
|
31
|
+
};
|
|
32
|
+
const import_meta = {};
|
|
1
33
|
async function streamProcessFileInWorker(file, opts = {}, onProgress) {
|
|
2
34
|
return new Promise((resolve, reject) => {
|
|
3
|
-
const worker = new Worker(new URL("./streaming-worker.js",
|
|
35
|
+
const worker = new Worker(new URL("./streaming-worker.js", import_meta.url), { type: "module" });
|
|
4
36
|
worker.onmessage = (event) => {
|
|
5
|
-
const { type,
|
|
37
|
+
const _a = event.data, { type } = _a, data = __objRest(_a, ["type"]);
|
|
6
38
|
if (type === "progress" && onProgress) {
|
|
7
39
|
onProgress(data);
|
|
8
40
|
} else if (type === "complete") {
|
|
@@ -30,7 +62,7 @@ async function convertFileToString(file, opts = {}) {
|
|
|
30
62
|
return decoder.decode(bytes);
|
|
31
63
|
}
|
|
32
64
|
async function convertFile(file, opts = {}) {
|
|
33
|
-
let actualOpts = {
|
|
65
|
+
let actualOpts = __spreadValues({}, opts);
|
|
34
66
|
if (opts.inputFormat === "auto") {
|
|
35
67
|
const sampleSize = 256 * 1024;
|
|
36
68
|
const sampleBlob = file.slice(0, sampleSize);
|
|
@@ -40,10 +72,10 @@ async function convertFile(file, opts = {}) {
|
|
|
40
72
|
if (detected.format !== "unknown") {
|
|
41
73
|
actualOpts.inputFormat = detected.format;
|
|
42
74
|
if (detected.csvConfig) {
|
|
43
|
-
actualOpts.csvConfig = opts.csvConfig ? {
|
|
75
|
+
actualOpts.csvConfig = opts.csvConfig ? __spreadValues(__spreadValues({}, detected.csvConfig), opts.csvConfig) : detected.csvConfig;
|
|
44
76
|
}
|
|
45
77
|
if (detected.xmlConfig) {
|
|
46
|
-
actualOpts.xmlConfig = opts.xmlConfig ? {
|
|
78
|
+
actualOpts.xmlConfig = opts.xmlConfig ? __spreadValues(__spreadValues({}, detected.xmlConfig), opts.xmlConfig) : detected.xmlConfig;
|
|
47
79
|
}
|
|
48
80
|
if (opts.debug) {
|
|
49
81
|
console.log("[convert-buddy] Auto-detected format:", detected.format);
|
|
@@ -120,7 +152,7 @@ async function convertFileToFile(inputFile, outputFilename, opts = {}) {
|
|
|
120
152
|
}, 100);
|
|
121
153
|
}
|
|
122
154
|
async function convertFileStream(file, opts = {}) {
|
|
123
|
-
let actualOpts = {
|
|
155
|
+
let actualOpts = __spreadValues({}, opts);
|
|
124
156
|
if (opts.inputFormat === "auto") {
|
|
125
157
|
const sampleSize = 256 * 1024;
|
|
126
158
|
const sampleBlob = file.slice(0, sampleSize);
|
|
@@ -130,10 +162,10 @@ async function convertFileStream(file, opts = {}) {
|
|
|
130
162
|
if (detected.format !== "unknown") {
|
|
131
163
|
actualOpts.inputFormat = detected.format;
|
|
132
164
|
if (detected.csvConfig) {
|
|
133
|
-
actualOpts.csvConfig = opts.csvConfig ? {
|
|
165
|
+
actualOpts.csvConfig = opts.csvConfig ? __spreadValues(__spreadValues({}, detected.csvConfig), opts.csvConfig) : detected.csvConfig;
|
|
134
166
|
}
|
|
135
167
|
if (detected.xmlConfig) {
|
|
136
|
-
actualOpts.xmlConfig = opts.xmlConfig ? {
|
|
168
|
+
actualOpts.xmlConfig = opts.xmlConfig ? __spreadValues(__spreadValues({}, detected.xmlConfig), opts.xmlConfig) : detected.xmlConfig;
|
|
137
169
|
}
|
|
138
170
|
} else {
|
|
139
171
|
throw new Error("Could not auto-detect input format.");
|
|
@@ -173,10 +205,9 @@ async function convertFileStream(file, opts = {}) {
|
|
|
173
205
|
});
|
|
174
206
|
}
|
|
175
207
|
async function autoConvertStream(file, opts) {
|
|
176
|
-
return convertFileStream(file, {
|
|
177
|
-
...opts,
|
|
208
|
+
return convertFileStream(file, __spreadProps(__spreadValues({}, opts), {
|
|
178
209
|
inputFormat: "auto"
|
|
179
|
-
});
|
|
210
|
+
}));
|
|
180
211
|
}
|
|
181
212
|
async function convertStreamToWritable(file, writable, opts = {}) {
|
|
182
213
|
const outputStream = await convertFileStream(file, opts);
|
|
@@ -202,7 +233,7 @@ async function convertAndSave(file, opts = {}) {
|
|
|
202
233
|
const writable = await fileHandle.createWritable();
|
|
203
234
|
await convertStreamToWritable(file, writable, opts);
|
|
204
235
|
} catch (error) {
|
|
205
|
-
if (error
|
|
236
|
+
if ((error == null ? void 0 : error.name) === "AbortError") {
|
|
206
237
|
return;
|
|
207
238
|
}
|
|
208
239
|
throw error;
|
|
@@ -210,7 +241,7 @@ async function convertAndSave(file, opts = {}) {
|
|
|
210
241
|
}
|
|
211
242
|
async function streamProcessFileInWorkerToWritable(file, writable, opts = {}, onProgress) {
|
|
212
243
|
return new Promise((resolve, reject) => {
|
|
213
|
-
const worker = new Worker(new URL("./streaming-worker.js",
|
|
244
|
+
const worker = new Worker(new URL("./streaming-worker.js", import_meta.url), { type: "module" });
|
|
214
245
|
let writer = null;
|
|
215
246
|
(async () => {
|
|
216
247
|
try {
|
|
@@ -230,7 +261,7 @@ async function streamProcessFileInWorkerToWritable(file, writable, opts = {}, on
|
|
|
230
261
|
await writable.write(chunk);
|
|
231
262
|
}
|
|
232
263
|
} else if (type === "progress") {
|
|
233
|
-
onProgress
|
|
264
|
+
onProgress == null ? void 0 : onProgress(event.data);
|
|
234
265
|
} else if (type === "complete") {
|
|
235
266
|
if (event.data.result) {
|
|
236
267
|
const finalChunk = new Uint8Array(event.data.result);
|
|
@@ -255,7 +286,7 @@ async function streamProcessFileInWorkerToWritable(file, writable, opts = {}, on
|
|
|
255
286
|
if (writer) {
|
|
256
287
|
try {
|
|
257
288
|
await writer.abort(err);
|
|
258
|
-
} catch {
|
|
289
|
+
} catch (e) {
|
|
259
290
|
}
|
|
260
291
|
}
|
|
261
292
|
worker.terminate();
|
package/dist/browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/browser.ts"],"sourcesContent":["/**\r\n * Stream a File/Blob conversion in a Web Worker with progress updates.\r\n *\r\n * @param file File or Blob to convert\r\n * @param opts Convert options (inputFormat, outputFormat, etc)\r\n * @param onProgress Callback for progress updates\r\n * @returns Promise<Uint8Array> with the converted result\r\n */\r\nexport async function streamProcessFileInWorker(\r\n file: File | Blob,\r\n opts: BrowserConvertOptions = {},\r\n onProgress?: (progress: { bytesRead: number; bytesWritten: number; percentComplete: number; recordsProcessed: number }) => void\r\n): Promise<Uint8Array> {\r\n return new Promise((resolve, reject) => {\r\n // Create worker\r\n const worker = new Worker(new URL('./streaming-worker.js', import.meta.url), { type: 'module' });\r\n\r\n worker.onmessage = (event) => {\r\n const { type, ...data } = event.data;\r\n if (type === 'progress' && onProgress) {\r\n onProgress(data);\r\n } else if (type === 'complete') {\r\n worker.terminate();\r\n resolve(new Uint8Array(data.result));\r\n } else if (type === 'error') {\r\n worker.terminate();\r\n reject(new Error(data.error));\r\n }\r\n };\r\n\r\n // Send file and options to worker\r\n worker.postMessage({ type: 'start', file, opts });\r\n });\r\n}\r\nimport { ConvertBuddy, type ConvertBuddyOptions, type ConvertOptions, type Format, autoDetectConfig, detectFormat, getMimeType, getFileTypeConfig, convertAny as convertAnyCore, convertAnyToString as convertAnyToStringCore } from \"./index\";\r\n\r\nexport * from \"./index\";\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 const decoder = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true });\r\n return decoder.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}\r\n\r\n/**\r\n * Stream a File/Blob conversion in a Web Worker and pipe output to a Writable.\r\n * This is useful for saving directly to disk using File System Access API.\r\n */\r\nexport async function streamProcessFileInWorkerToWritable(\r\n file: File | Blob,\r\n writable: WritableStream<Uint8Array> | FileSystemWritableFileStream,\r\n opts: BrowserConvertOptions = {},\r\n onProgress?: (progress: { bytesRead: number; bytesWritten: number; percentComplete: number; recordsProcessed: number }) => void\r\n): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n const worker = new Worker(new URL('./streaming-worker.js', import.meta.url), { type: 'module' });\r\n let writer: WritableStreamDefaultWriter<Uint8Array> | null = null;\r\n\r\n (async () => {\r\n try {\r\n if ((writable as any).getWriter) {\r\n writer = (writable as WritableStream<Uint8Array>).getWriter();\r\n } else {\r\n // FileSystemWritableFileStream supports write(Uint8Array)\r\n writer = null;\r\n }\r\n\r\n worker.onmessage = async (event) => {\r\n const { type } = event.data;\r\n if (type === 'data') {\r\n const ab: ArrayBuffer = event.data.chunk;\r\n const chunk = new Uint8Array(ab);\r\n if (writer) {\r\n await writer.write(chunk);\r\n } else if ((writable as any).write) {\r\n await (writable as any).write(chunk);\r\n }\r\n } else if (type === 'progress') {\r\n onProgress?.(event.data);\r\n } else if (type === 'complete') {\r\n // write final chunk if present\r\n if (event.data.result) {\r\n const finalChunk = new Uint8Array(event.data.result);\r\n if (writer) await writer.write(finalChunk);\r\n else if ((writable as any).write) await (writable as any).write(finalChunk);\r\n }\r\n\r\n try {\r\n // Only close if we have a writer (WritableStream with getWriter)\r\n // FileSystemWritableFileStream should NOT be closed by us - caller owns it\r\n if (writer) {\r\n await writer.close();\r\n }\r\n } catch (e) {\r\n // ignore close errors\r\n }\r\n worker.terminate();\r\n resolve();\r\n } else if (type === 'error') {\r\n worker.terminate();\r\n reject(new Error(event.data.error));\r\n }\r\n };\r\n\r\n // Start worker\r\n worker.postMessage({ type: 'start', file, opts });\r\n } catch (err) {\r\n if (writer) {\r\n try { await writer.abort(err); } catch {}\r\n }\r\n worker.terminate();\r\n reject(err);\r\n }\r\n })();\r\n });\r\n}\r\n"],"mappings":"AAQA,eAAsB,0BACpB,MACA,OAA8B,CAAC,GAC/B,YACqB;AACrB,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAEtC,UAAM,SAAS,IAAI,OAAO,IAAI,IAAI,yBAAyB,YAAY,GAAG,GAAG,EAAE,MAAM,SAAS,CAAC;AAE/F,WAAO,YAAY,CAAC,UAAU;AAC5B,YAAM,EAAE,MAAM,GAAG,KAAK,IAAI,MAAM;AAChC,UAAI,SAAS,cAAc,YAAY;AACrC,mBAAW,IAAI;AAAA,MACjB,WAAW,SAAS,YAAY;AAC9B,eAAO,UAAU;AACjB,gBAAQ,IAAI,WAAW,KAAK,MAAM,CAAC;AAAA,MACrC,WAAW,SAAS,SAAS;AAC3B,eAAO,UAAU;AACjB,eAAO,IAAI,MAAM,KAAK,KAAK,CAAC;AAAA,MAC9B;AAAA,IACF;AAGA,WAAO,YAAY,EAAE,MAAM,SAAS,MAAM,KAAK,CAAC;AAAA,EAClD,CAAC;AACH;AACA,SAAS,cAA0E,kBAA6C,mBAAmB,cAAc,gBAAgB,sBAAsB,8BAA8B;AAErO,cAAc;AAuBd,eAAsB,QACpB,OACA,MACqB;AACrB,SAAO,eAAe,OAAO,IAAI;AACnC;AASA,eAAsB,gBACpB,OACA,MACiB;AACjB,SAAO,uBAAuB,OAAO,IAAI;AAC3C;AAsBA,eAAsB,oBACpB,MACA,OAA8B,CAAC,GACd;AACjB,QAAM,QAAQ,MAAM,YAAY,MAAM,IAAI;AAC1C,QAAM,UAAU,IAAI,YAAY,SAAS,EAAE,OAAO,MAAM,WAAW,KAAK,CAAC;AACzE,SAAO,QAAQ,OAAO,KAAK;AAC7B;AAgBA,eAAsB,YACpB,MACA,OAA8B,CAAC,GACV;AAErB,MAAI,aAAa,EAAE,GAAG,KAAK;AAE3B,MAAI,KAAK,gBAAgB,QAAQ;AAE/B,UAAM,aAAa,MAAM;AACzB,UAAM,aAAa,KAAK,MAAM,GAAG,UAAU;AAC3C,UAAM,eAAe,MAAM,WAAW,YAAY;AAClD,UAAM,SAAS,IAAI,WAAW,YAA2B;AAEzD,UAAM,WAAW,MAAM,iBAAiB,QAAQ,EAAE,OAAO,KAAK,MAAM,CAAC;AAErE,QAAI,SAAS,WAAW,WAAW;AACjC,iBAAW,cAAc,SAAS;AAElC,UAAI,SAAS,WAAW;AACtB,mBAAW,YAAY,KAAK,YAAY,EAAE,GAAG,SAAS,WAAW,GAAG,KAAK,UAAU,IAAI,SAAS;AAAA,MAClG;AAEA,UAAI,SAAS,WAAW;AACtB,mBAAW,YAAY,KAAK,YAAY,EAAE,GAAG,SAAS,WAAW,GAAG,KAAK,UAAU,IAAI,SAAS;AAAA,MAClG;AAEA,UAAI,KAAK,OAAO;AACd,gBAAQ,IAAI,yCAAyC,SAAS,MAAM;AAAA,MACtE;AAAA,IACF,OAAO;AACL,YAAM,IAAI,MAAM,4EAA4E;AAAA,IAC9F;AAAA,EACF;AAIA,MAAI,CAAC,WAAW,kBAAkB;AAChC,UAAM,WAAW,KAAK;AACtB,eAAW,mBAAmB,KAAK;AAAA,MACjC,MAAM;AAAA;AAAA,MACN,KAAK;AAAA,QACH,IAAI,OAAO;AAAA;AAAA,QACX,KAAK,MAAM,WAAW,EAAE;AAAA;AAAA,MAC1B;AAAA,IACF;AACA,QAAI,KAAK,OAAO;AACd,cAAQ,IAAI,0CAA0C,QAAQ,iBAAY,WAAW,gBAAgB,cAAc;AAAA,IACrH;AAAA,EACF;AAEA,QAAM,QAAQ,MAAM,aAAa,OAAO,UAAU;AAGlD,QAAM,SAAS,KAAK,OAAO;AAC3B,QAAM,SAAS,OAAO,UAAU;AAEhC,QAAM,SAAuB,CAAC;AAE9B,MAAI;AACF,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAE1C,UAAI,KAAM;AAEV,UAAI,MAAM,UAAU,GAAG;AACrB,cAAM,IAAI,MAAM,oBAAoB;AAAA,MACtC;AAEA,YAAM,SAAS,MAAM,KAAK,KAAK;AAC/B,UAAI,OAAO,SAAS,GAAG;AACrB,eAAO,KAAK,MAAM;AAAA,MACpB;AAAA,IACF;AAEA,UAAM,QAAQ,MAAM,OAAO;AAC3B,QAAI,MAAM,SAAS,GAAG;AACpB,aAAO,KAAK,KAAK;AAAA,IACnB;AAGA,UAAM,cAAc,OAAO,OAAO,CAAC,KAAK,UAAU,MAAM,MAAM,QAAQ,CAAC;AACvE,UAAM,SAAS,IAAI,WAAW,WAAW;AACzC,QAAI,SAAS;AACb,eAAW,SAAS,QAAQ;AAC1B,aAAO,IAAI,OAAO,MAAM;AACxB,gBAAU,MAAM;AAAA,IAClB;AAEA,QAAI,KAAK,SAAS;AAChB,cAAQ,IAAI,sCAAsC,MAAM,MAAM,CAAC;AAAA,IACjE;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,WAAO,YAAY;AACnB,UAAM;AAAA,EACR;AACF;AAaA,eAAsB,kBACpB,WACA,gBACA,OAA8B,CAAC,GAChB;AACf,QAAM,SAAS,MAAM,YAAY,WAAW,IAAI;AAGhD,QAAM,OAAO,IAAI,KAAK,CAAC,IAAI,WAAW,MAAM,CAAC,GAAG,EAAE,MAAM,2BAA2B,CAAC;AACpF,QAAM,MAAM,IAAI,gBAAgB,IAAI;AAEpC,QAAM,OAAO,SAAS,cAAc,GAAG;AACvC,OAAK,OAAO;AACZ,OAAK,WAAW;AAChB,OAAK,MAAM,UAAU;AAErB,WAAS,KAAK,YAAY,IAAI;AAC9B,OAAK,MAAM;AAGX,aAAW,MAAM;AACf,aAAS,KAAK,YAAY,IAAI;AAC9B,QAAI,gBAAgB,GAAG;AAAA,EACzB,GAAG,GAAG;AACR;AAqBA,eAAsB,kBACpB,MACA,OAA8B,CAAC,GACM;AAErC,MAAI,aAAa,EAAE,GAAG,KAAK;AAE3B,MAAI,KAAK,gBAAgB,QAAQ;AAC/B,UAAM,aAAa,MAAM;AACzB,UAAM,aAAa,KAAK,MAAM,GAAG,UAAU;AAC3C,UAAM,eAAe,MAAM,WAAW,YAAY;AAClD,UAAM,SAAS,IAAI,WAAW,YAAY;AAE1C,UAAM,WAAW,MAAM,iBAAiB,QAAQ,EAAE,OAAO,KAAK,MAAM,CAAC;AAErE,QAAI,SAAS,WAAW,WAAW;AACjC,iBAAW,cAAc,SAAS;AAClC,UAAI,SAAS,WAAW;AACtB,mBAAW,YAAY,KAAK,YAAY,EAAE,GAAG,SAAS,WAAW,GAAG,KAAK,UAAU,IAAI,SAAS;AAAA,MAClG;AACA,UAAI,SAAS,WAAW;AACtB,mBAAW,YAAY,KAAK,YAAY,EAAE,GAAG,SAAS,WAAW,GAAG,KAAK,UAAU,IAAI,SAAS;AAAA,MAClG;AAAA,IACF,OAAO;AACL,YAAM,IAAI,MAAM,qCAAqC;AAAA,IACvD;AAAA,EACF;AAEA,QAAM,QAAQ,MAAM,aAAa,OAAO,UAAU;AAClD,QAAM,cAAc,KAAK,OAAO;AAEhC,SAAO,IAAI,eAA2B;AAAA,IACpC,MAAM,MAAM,YAAY;AACtB,YAAM,SAAS,YAAY,UAAU;AAErC,UAAI;AACF,eAAO,MAAM;AACX,gBAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAE1C,cAAI,MAAM;AACR,kBAAM,QAAQ,MAAM,OAAO;AAC3B,gBAAI,MAAM,SAAS,GAAG;AACpB,yBAAW,QAAQ,KAAK;AAAA,YAC1B;AACA,uBAAW,MAAM;AACjB;AAAA,UACF;AAEA,cAAI,MAAM,UAAU,GAAG;AACrB,uBAAW,MAAM,IAAI,MAAM,oBAAoB,CAAC;AAChD;AAAA,UACF;AAEA,gBAAM,SAAS,MAAM,KAAK,KAAK;AAC/B,cAAI,OAAO,SAAS,GAAG;AACrB,uBAAW,QAAQ,MAAM;AAAA,UAC3B;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,mBAAW,MAAM,KAAK;AAAA,MACxB,UAAE;AACA,eAAO,YAAY;AAAA,MACrB;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAYA,eAAsB,kBACpB,MACA,MACqC;AACrC,SAAO,kBAAkB,MAAM;AAAA,IAC7B,GAAG;AAAA,IACH,aAAa;AAAA,EACf,CAAC;AACH;AA+BA,eAAsB,wBACpB,MACA,UACA,OAA8B,CAAC,GAChB;AACf,QAAM,eAAe,MAAM,kBAAkB,MAAM,IAAI;AACvD,QAAM,aAAa,OAAO,QAAQ;AACpC;AAeO,SAAS,8BAAuC;AACrD,SACE,OAAO,WAAW,eAClB,wBAAwB,UACxB,wBAAwB;AAE5B;AAeA,eAAsB,eACpB,MACA,OAEI,CAAC,GACU;AACf,MAAI,CAAC,4BAA4B,GAAG;AAElC,UAAM,WAAW,KAAK,iBAAiB;AACvC,UAAM,kBAAkB,MAAM,UAAU,IAAI;AAC5C;AAAA,EACF;AAEA,QAAM,eAAe,KAAK,gBAAgB;AAC1C,QAAM,gBAAgB,KAAK,iBAAiB,aAAa,YAAY;AACrE,QAAM,QAAQ,kBAAkB,YAAY;AAE5C,MAAI;AACF,UAAM,aAAa,MAAO,OAAe,mBAAmB;AAAA,MAC1D;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,WAAW,MAAM,WAAW,eAAe;AACjD,UAAM,wBAAwB,MAAM,UAAU,IAAI;AAAA,EACpD,SAAS,OAAY;AAEnB,QAAI,OAAO,SAAS,cAAc;AAEhC;AAAA,IACF;AAEA,UAAM;AAAA,EACR;AACF;AAMA,eAAsB,oCACpB,MACA,UACA,OAA8B,CAAC,GAC/B,YACe;AACf,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAS,IAAI,OAAO,IAAI,IAAI,yBAAyB,YAAY,GAAG,GAAG,EAAE,MAAM,SAAS,CAAC;AAC/F,QAAI,SAAyD;AAE7D,KAAC,YAAY;AACX,UAAI;AACF,YAAK,SAAiB,WAAW;AAC/B,mBAAU,SAAwC,UAAU;AAAA,QAC9D,OAAO;AAEL,mBAAS;AAAA,QACX;AAEA,eAAO,YAAY,OAAO,UAAU;AAClC,gBAAM,EAAE,KAAK,IAAI,MAAM;AACvB,cAAI,SAAS,QAAQ;AACnB,kBAAM,KAAkB,MAAM,KAAK;AACnC,kBAAM,QAAQ,IAAI,WAAW,EAAE;AAC/B,gBAAI,QAAQ;AACV,oBAAM,OAAO,MAAM,KAAK;AAAA,YAC1B,WAAY,SAAiB,OAAO;AAClC,oBAAO,SAAiB,MAAM,KAAK;AAAA,YACrC;AAAA,UACF,WAAW,SAAS,YAAY;AAC9B,yBAAa,MAAM,IAAI;AAAA,UACzB,WAAW,SAAS,YAAY;AAE9B,gBAAI,MAAM,KAAK,QAAQ;AACrB,oBAAM,aAAa,IAAI,WAAW,MAAM,KAAK,MAAM;AACnD,kBAAI,OAAQ,OAAM,OAAO,MAAM,UAAU;AAAA,uBAC/B,SAAiB,MAAO,OAAO,SAAiB,MAAM,UAAU;AAAA,YAC5E;AAEA,gBAAI;AAGF,kBAAI,QAAQ;AACV,sBAAM,OAAO,MAAM;AAAA,cACrB;AAAA,YACF,SAAS,GAAG;AAAA,YAEZ;AACA,mBAAO,UAAU;AACjB,oBAAQ;AAAA,UACV,WAAW,SAAS,SAAS;AAC3B,mBAAO,UAAU;AACjB,mBAAO,IAAI,MAAM,MAAM,KAAK,KAAK,CAAC;AAAA,UACpC;AAAA,QACF;AAGA,eAAO,YAAY,EAAE,MAAM,SAAS,MAAM,KAAK,CAAC;AAAA,MAClD,SAAS,KAAK;AACZ,YAAI,QAAQ;AACV,cAAI;AAAE,kBAAM,OAAO,MAAM,GAAG;AAAA,UAAG,QAAQ;AAAA,UAAC;AAAA,QAC1C;AACA,eAAO,UAAU;AACjB,eAAO,GAAG;AAAA,MACZ;AAAA,IACF,GAAG;AAAA,EACL,CAAC;AACH;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/browser.ts"],"sourcesContent":["/**\r\n * Stream a File/Blob conversion in a Web Worker with progress updates.\r\n *\r\n * @param file File or Blob to convert\r\n * @param opts Convert options (inputFormat, outputFormat, etc)\r\n * @param onProgress Callback for progress updates\r\n * @returns Promise<Uint8Array> with the converted result\r\n */\r\nexport async function streamProcessFileInWorker(\r\n file: File | Blob,\r\n opts: BrowserConvertOptions = {},\r\n onProgress?: (progress: { bytesRead: number; bytesWritten: number; percentComplete: number; recordsProcessed: number }) => void\r\n): Promise<Uint8Array> {\r\n return new Promise((resolve, reject) => {\r\n // Create worker\r\n const worker = new Worker(new URL('./streaming-worker.js', import.meta.url), { type: 'module' });\r\n\r\n worker.onmessage = (event) => {\r\n const { type, ...data } = event.data;\r\n if (type === 'progress' && onProgress) {\r\n onProgress(data);\r\n } else if (type === 'complete') {\r\n worker.terminate();\r\n resolve(new Uint8Array(data.result));\r\n } else if (type === 'error') {\r\n worker.terminate();\r\n reject(new Error(data.error));\r\n }\r\n };\r\n\r\n // Send file and options to worker\r\n worker.postMessage({ type: 'start', file, opts });\r\n });\r\n}\r\nimport { ConvertBuddy, type ConvertBuddyOptions, type ConvertOptions, type Format, autoDetectConfig, detectFormat, getMimeType, getFileTypeConfig, convertAny as convertAnyCore, convertAnyToString as convertAnyToStringCore } from \"./index\";\r\n\r\nexport * from \"./index\";\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 const decoder = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true });\r\n return decoder.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}\r\n\r\n/**\r\n * Stream a File/Blob conversion in a Web Worker and pipe output to a Writable.\r\n * This is useful for saving directly to disk using File System Access API.\r\n */\r\nexport async function streamProcessFileInWorkerToWritable(\r\n file: File | Blob,\r\n writable: WritableStream<Uint8Array> | FileSystemWritableFileStream,\r\n opts: BrowserConvertOptions = {},\r\n onProgress?: (progress: { bytesRead: number; bytesWritten: number; percentComplete: number; recordsProcessed: number }) => void\r\n): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n const worker = new Worker(new URL('./streaming-worker.js', import.meta.url), { type: 'module' });\r\n let writer: WritableStreamDefaultWriter<Uint8Array> | null = null;\r\n\r\n (async () => {\r\n try {\r\n if ((writable as any).getWriter) {\r\n writer = (writable as WritableStream<Uint8Array>).getWriter();\r\n } else {\r\n // FileSystemWritableFileStream supports write(Uint8Array)\r\n writer = null;\r\n }\r\n\r\n worker.onmessage = async (event) => {\r\n const { type } = event.data;\r\n if (type === 'data') {\r\n const ab: ArrayBuffer = event.data.chunk;\r\n const chunk = new Uint8Array(ab);\r\n if (writer) {\r\n await writer.write(chunk);\r\n } else if ((writable as any).write) {\r\n await (writable as any).write(chunk);\r\n }\r\n } else if (type === 'progress') {\r\n onProgress?.(event.data);\r\n } else if (type === 'complete') {\r\n // write final chunk if present\r\n if (event.data.result) {\r\n const finalChunk = new Uint8Array(event.data.result);\r\n if (writer) await writer.write(finalChunk);\r\n else if ((writable as any).write) await (writable as any).write(finalChunk);\r\n }\r\n\r\n try {\r\n // Only close if we have a writer (WritableStream with getWriter)\r\n // FileSystemWritableFileStream should NOT be closed by us - caller owns it\r\n if (writer) {\r\n await writer.close();\r\n }\r\n } catch (e) {\r\n // ignore close errors\r\n }\r\n worker.terminate();\r\n resolve();\r\n } else if (type === 'error') {\r\n worker.terminate();\r\n reject(new Error(event.data.error));\r\n }\r\n };\r\n\r\n // Start worker\r\n worker.postMessage({ type: 'start', file, opts });\r\n } catch (err) {\r\n if (writer) {\r\n try { await writer.abort(err); } catch {}\r\n }\r\n worker.terminate();\r\n reject(err);\r\n }\r\n })();\r\n });\r\n}\r\n"],"mappings":"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","names":[]}
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "convert-buddy-js",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.6",
|
|
4
4
|
"description": "TypeScript wrapper for convert-buddy (Rust/WASM core)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
|
+
"browser": "./dist/browser.js",
|
|
8
9
|
"types": "./dist/index.d.ts",
|
|
9
10
|
"exports": {
|
|
10
11
|
".": {
|
|
11
12
|
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": {
|
|
14
|
+
"browser": "./dist/browser.js",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
},
|
|
12
17
|
"default": "./dist/index.js"
|
|
13
18
|
},
|
|
14
19
|
"./node": {
|
|
@@ -32,7 +37,9 @@
|
|
|
32
37
|
"build:wasm:node": "set CONVERT_BUDDY_WASM_TARGET=nodejs&& node ./scripts/build-wasm.mjs",
|
|
33
38
|
"build:wasm": "npm run build:wasm:web && npm run build:wasm:node",
|
|
34
39
|
"sync:wasm": "node ./scripts/sync-wasm.mjs",
|
|
35
|
-
"build": "
|
|
40
|
+
"build:js": "tsup",
|
|
41
|
+
"build:browser:compat": "tsup src/browser.ts --format esm --target es2017 --outDir dist --sourcemap",
|
|
42
|
+
"build": "npm run build:wasm && npm run build:js && npm run build:browser:compat && npm run sync:wasm",
|
|
36
43
|
"check:wasm": "node ./scripts/check-wasm.mjs",
|
|
37
44
|
"test": "npm run build && node --test ./dist/tests/edge-cases/*.test.js",
|
|
38
45
|
"bench": "npm run build && node --expose-gc ./dist/bench/runner.js",
|