convert-buddy-js 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/dist/chunk-C3RSVYQF.js +63 -0
- package/dist/{chunk-27H3T556.js → chunk-WBKHAQCT.js} +76 -53
- package/dist/src/index.d.ts +13 -4
- package/dist/src/index.js +5 -3
- package/dist/src/node.d.ts +7 -0
- package/dist/src/node.js +21 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -146,11 +146,22 @@ if (csvInfo) {
|
|
|
146
146
|
## How it works
|
|
147
147
|
|
|
148
148
|
- **Rust core** (`crates/convert-buddy`) implements streaming parsers and stats tracking.
|
|
149
|
-
- **WASM bindings** are generated via `wasm-bindgen` and bundled into this package.
|
|
149
|
+
- **WASM bindings** are generated via `wasm-bindgen` and bundled into this package as prebuilt binaries.
|
|
150
150
|
- **TypeScript wrapper** (`src/index.ts`) exposes the `ConvertBuddy` class and stream adapters.
|
|
151
151
|
|
|
152
|
+
## Package contents (what ships)
|
|
153
|
+
|
|
154
|
+
The published npm package includes only the runtime artifacts needed to use Convert Buddy:
|
|
155
|
+
|
|
156
|
+
- Prebuilt WASM binaries (in `wasm/` plus `wasm-node.cjs` for Node.js).
|
|
157
|
+
- Compiled TypeScript output (in `dist/`).
|
|
158
|
+
|
|
159
|
+
The monorepo demo app, Rust sources, and build/benchmark tooling live in this repository but are **not** published with the npm package.
|
|
160
|
+
|
|
152
161
|
### Build (repository)
|
|
153
162
|
|
|
163
|
+
These steps are **only** for contributors working in this monorepo. If you install `convert-buddy-js` from npm, you do **not** need to run them.
|
|
164
|
+
|
|
154
165
|
```bash
|
|
155
166
|
npm install
|
|
156
167
|
npm -w convert-buddy-js run build
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConvertBuddy
|
|
3
|
+
} from "./chunk-WBKHAQCT.js";
|
|
4
|
+
|
|
5
|
+
// src/node.ts
|
|
6
|
+
async function loadNodeTransform() {
|
|
7
|
+
const isNode = typeof process !== "undefined" && !!process.versions?.node;
|
|
8
|
+
if (!isNode) {
|
|
9
|
+
throw new Error("createNodeTransform is only available in Node.js runtimes.");
|
|
10
|
+
}
|
|
11
|
+
const streamModule = await import("stream");
|
|
12
|
+
return streamModule.Transform;
|
|
13
|
+
}
|
|
14
|
+
async function createNodeTransform(opts = {}) {
|
|
15
|
+
let buddy = null;
|
|
16
|
+
let initPromise = null;
|
|
17
|
+
const Transform = await loadNodeTransform();
|
|
18
|
+
const transform = new Transform({
|
|
19
|
+
async transform(chunk, encoding, callback) {
|
|
20
|
+
try {
|
|
21
|
+
if (!buddy) {
|
|
22
|
+
if (!initPromise) {
|
|
23
|
+
initPromise = ConvertBuddy.create(opts).then((b) => {
|
|
24
|
+
buddy = b;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
await initPromise;
|
|
28
|
+
}
|
|
29
|
+
const input = new Uint8Array(chunk);
|
|
30
|
+
const output = buddy.push(input);
|
|
31
|
+
if (output.length > 0) {
|
|
32
|
+
this.push(Buffer.from(output));
|
|
33
|
+
}
|
|
34
|
+
callback();
|
|
35
|
+
} catch (err) {
|
|
36
|
+
callback(err);
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
async flush(callback) {
|
|
40
|
+
try {
|
|
41
|
+
if (buddy) {
|
|
42
|
+
const output = buddy.finish();
|
|
43
|
+
if (output.length > 0) {
|
|
44
|
+
this.push(Buffer.from(output));
|
|
45
|
+
}
|
|
46
|
+
if (opts.profile) {
|
|
47
|
+
const stats = buddy.stats();
|
|
48
|
+
console.log("[convert-buddy] Performance Stats:", stats);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
callback();
|
|
52
|
+
} catch (err) {
|
|
53
|
+
callback(err);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return transform;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export {
|
|
61
|
+
createNodeTransform
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=chunk-C3RSVYQF.js.map
|
|
@@ -35,7 +35,9 @@ var ConvertBuddy = class _ConvertBuddy {
|
|
|
35
35
|
opts.inputFormat,
|
|
36
36
|
opts.outputFormat,
|
|
37
37
|
opts.chunkTargetBytes || 1024 * 1024,
|
|
38
|
-
profile
|
|
38
|
+
profile,
|
|
39
|
+
opts.csvConfig,
|
|
40
|
+
opts.xmlConfig
|
|
39
41
|
);
|
|
40
42
|
} else {
|
|
41
43
|
converter = new wasmModule.Converter(debug);
|
|
@@ -55,58 +57,78 @@ var ConvertBuddy = class _ConvertBuddy {
|
|
|
55
57
|
return this.converter.getStats();
|
|
56
58
|
}
|
|
57
59
|
};
|
|
58
|
-
async function
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
async function readSample(input, maxBytes = 256 * 1024) {
|
|
61
|
+
if (typeof input === "string") {
|
|
62
|
+
const encoded = new TextEncoder().encode(input);
|
|
63
|
+
return encoded.length > maxBytes ? encoded.slice(0, maxBytes) : encoded;
|
|
62
64
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (output.length > 0) {
|
|
84
|
-
this.push(Buffer.from(output));
|
|
85
|
-
}
|
|
86
|
-
callback();
|
|
87
|
-
} catch (err) {
|
|
88
|
-
callback(err);
|
|
89
|
-
}
|
|
90
|
-
},
|
|
91
|
-
async flush(callback) {
|
|
92
|
-
try {
|
|
93
|
-
if (buddy) {
|
|
94
|
-
const output = buddy.finish();
|
|
95
|
-
if (output.length > 0) {
|
|
96
|
-
this.push(Buffer.from(output));
|
|
97
|
-
}
|
|
98
|
-
if (opts.profile) {
|
|
99
|
-
const stats = buddy.stats();
|
|
100
|
-
console.log("[convert-buddy] Performance Stats:", stats);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
callback();
|
|
104
|
-
} catch (err) {
|
|
105
|
-
callback(err);
|
|
106
|
-
}
|
|
65
|
+
if (input instanceof Uint8Array) {
|
|
66
|
+
return input.length > maxBytes ? input.slice(0, maxBytes) : input;
|
|
67
|
+
}
|
|
68
|
+
if (input instanceof ArrayBuffer) {
|
|
69
|
+
const bytes = new Uint8Array(input);
|
|
70
|
+
return bytes.length > maxBytes ? bytes.slice(0, maxBytes) : bytes;
|
|
71
|
+
}
|
|
72
|
+
if (isReadableStream(input)) {
|
|
73
|
+
const reader = input.getReader();
|
|
74
|
+
const chunks2 = [];
|
|
75
|
+
let total2 = 0;
|
|
76
|
+
while (total2 < maxBytes) {
|
|
77
|
+
const { value, done } = await reader.read();
|
|
78
|
+
if (done || !value) break;
|
|
79
|
+
const slice = total2 + value.length > maxBytes ? value.slice(0, maxBytes - total2) : value;
|
|
80
|
+
chunks2.push(slice);
|
|
81
|
+
total2 += slice.length;
|
|
82
|
+
}
|
|
83
|
+
if (total2 >= maxBytes) {
|
|
84
|
+
await reader.cancel();
|
|
107
85
|
}
|
|
108
|
-
|
|
109
|
-
|
|
86
|
+
return concatChunks(chunks2, total2);
|
|
87
|
+
}
|
|
88
|
+
const chunks = [];
|
|
89
|
+
let total = 0;
|
|
90
|
+
for await (const chunk of input) {
|
|
91
|
+
if (total >= maxBytes) {
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
const data = chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk);
|
|
95
|
+
const slice = total + data.length > maxBytes ? data.slice(0, maxBytes - total) : data;
|
|
96
|
+
chunks.push(slice);
|
|
97
|
+
total += slice.length;
|
|
98
|
+
}
|
|
99
|
+
return concatChunks(chunks, total);
|
|
100
|
+
}
|
|
101
|
+
function concatChunks(chunks, total) {
|
|
102
|
+
const result = new Uint8Array(total);
|
|
103
|
+
let offset = 0;
|
|
104
|
+
for (const chunk of chunks) {
|
|
105
|
+
result.set(chunk, offset);
|
|
106
|
+
offset += chunk.length;
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
function isReadableStream(input) {
|
|
111
|
+
return typeof input?.getReader === "function";
|
|
112
|
+
}
|
|
113
|
+
async function loadDetectionWasm(debug) {
|
|
114
|
+
const wasmModule = await loadWasmModule();
|
|
115
|
+
if (typeof wasmModule.default === "function") {
|
|
116
|
+
await wasmModule.default();
|
|
117
|
+
}
|
|
118
|
+
wasmModule.init(debug);
|
|
119
|
+
return wasmModule;
|
|
120
|
+
}
|
|
121
|
+
async function detectFormat(input, opts = {}) {
|
|
122
|
+
const wasmModule = await loadDetectionWasm(!!opts.debug);
|
|
123
|
+
const sample = await readSample(input, opts.maxBytes);
|
|
124
|
+
const format = wasmModule.detectFormat?.(sample);
|
|
125
|
+
return format ?? "unknown";
|
|
126
|
+
}
|
|
127
|
+
async function detectCsvFieldsAndDelimiter(input, opts = {}) {
|
|
128
|
+
const wasmModule = await loadDetectionWasm(!!opts.debug);
|
|
129
|
+
const sample = await readSample(input, opts.maxBytes);
|
|
130
|
+
const result = wasmModule.detectCsvFields?.(sample);
|
|
131
|
+
return result ?? null;
|
|
110
132
|
}
|
|
111
133
|
var ConvertBuddyTransformStream = class extends TransformStream {
|
|
112
134
|
constructor(opts = {}) {
|
|
@@ -161,9 +183,10 @@ async function convertToString(input, opts = {}) {
|
|
|
161
183
|
|
|
162
184
|
export {
|
|
163
185
|
ConvertBuddy,
|
|
164
|
-
|
|
186
|
+
detectFormat,
|
|
187
|
+
detectCsvFieldsAndDelimiter,
|
|
165
188
|
ConvertBuddyTransformStream,
|
|
166
189
|
convert,
|
|
167
190
|
convertToString
|
|
168
191
|
};
|
|
169
|
-
//# sourceMappingURL=chunk-
|
|
192
|
+
//# sourceMappingURL=chunk-WBKHAQCT.js.map
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import { Transform } from 'node:stream';
|
|
2
|
-
|
|
3
1
|
type Format = "csv" | "ndjson" | "json" | "xml";
|
|
2
|
+
type DetectInput = Uint8Array | ArrayBuffer | string | ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>;
|
|
3
|
+
type CsvDetection = {
|
|
4
|
+
delimiter: string;
|
|
5
|
+
fields: string[];
|
|
6
|
+
};
|
|
7
|
+
type DetectOptions = {
|
|
8
|
+
maxBytes?: number;
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
};
|
|
4
11
|
type ConvertBuddyOptions = {
|
|
5
12
|
debug?: boolean;
|
|
6
13
|
profile?: boolean;
|
|
@@ -21,6 +28,7 @@ type XmlConfig = {
|
|
|
21
28
|
recordElement?: string;
|
|
22
29
|
trimText?: boolean;
|
|
23
30
|
includeAttributes?: boolean;
|
|
31
|
+
expandEntities?: boolean;
|
|
24
32
|
};
|
|
25
33
|
type Stats = {
|
|
26
34
|
bytesIn: number;
|
|
@@ -44,11 +52,12 @@ declare class ConvertBuddy {
|
|
|
44
52
|
finish(): Uint8Array;
|
|
45
53
|
stats(): Stats;
|
|
46
54
|
}
|
|
47
|
-
declare function
|
|
55
|
+
declare function detectFormat(input: DetectInput, opts?: DetectOptions): Promise<Format | "unknown">;
|
|
56
|
+
declare function detectCsvFieldsAndDelimiter(input: DetectInput, opts?: DetectOptions): Promise<CsvDetection | null>;
|
|
48
57
|
declare class ConvertBuddyTransformStream extends TransformStream<Uint8Array, Uint8Array> {
|
|
49
58
|
constructor(opts?: ConvertBuddyOptions);
|
|
50
59
|
}
|
|
51
60
|
declare function convert(input: Uint8Array | string, opts?: ConvertBuddyOptions): Promise<Uint8Array>;
|
|
52
61
|
declare function convertToString(input: Uint8Array | string, opts?: ConvertBuddyOptions): Promise<string>;
|
|
53
62
|
|
|
54
|
-
export { ConvertBuddy, type ConvertBuddyOptions, ConvertBuddyTransformStream, type CsvConfig, type Format, type Stats, type XmlConfig, convert, convertToString,
|
|
63
|
+
export { ConvertBuddy, type ConvertBuddyOptions, ConvertBuddyTransformStream, type CsvConfig, type CsvDetection, type DetectInput, type DetectOptions, type Format, type Stats, type XmlConfig, convert, convertToString, detectCsvFieldsAndDelimiter, detectFormat };
|
package/dist/src/index.js
CHANGED
|
@@ -3,13 +3,15 @@ import {
|
|
|
3
3
|
ConvertBuddyTransformStream,
|
|
4
4
|
convert,
|
|
5
5
|
convertToString,
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
detectCsvFieldsAndDelimiter,
|
|
7
|
+
detectFormat
|
|
8
|
+
} from "../chunk-WBKHAQCT.js";
|
|
8
9
|
export {
|
|
9
10
|
ConvertBuddy,
|
|
10
11
|
ConvertBuddyTransformStream,
|
|
11
12
|
convert,
|
|
12
13
|
convertToString,
|
|
13
|
-
|
|
14
|
+
detectCsvFieldsAndDelimiter,
|
|
15
|
+
detectFormat
|
|
14
16
|
};
|
|
15
17
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Transform } from 'node:stream';
|
|
2
|
+
import { ConvertBuddyOptions } from './index.js';
|
|
3
|
+
export { ConvertBuddy, ConvertBuddyTransformStream, CsvConfig, CsvDetection, DetectInput, DetectOptions, Format, Stats, XmlConfig, convert, convertToString, detectCsvFieldsAndDelimiter, detectFormat } from './index.js';
|
|
4
|
+
|
|
5
|
+
declare function createNodeTransform(opts?: ConvertBuddyOptions): Promise<Transform>;
|
|
6
|
+
|
|
7
|
+
export { ConvertBuddyOptions, createNodeTransform };
|
package/dist/src/node.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createNodeTransform
|
|
3
|
+
} from "../chunk-C3RSVYQF.js";
|
|
4
|
+
import {
|
|
5
|
+
ConvertBuddy,
|
|
6
|
+
ConvertBuddyTransformStream,
|
|
7
|
+
convert,
|
|
8
|
+
convertToString,
|
|
9
|
+
detectCsvFieldsAndDelimiter,
|
|
10
|
+
detectFormat
|
|
11
|
+
} from "../chunk-WBKHAQCT.js";
|
|
12
|
+
export {
|
|
13
|
+
ConvertBuddy,
|
|
14
|
+
ConvertBuddyTransformStream,
|
|
15
|
+
convert,
|
|
16
|
+
convertToString,
|
|
17
|
+
createNodeTransform,
|
|
18
|
+
detectCsvFieldsAndDelimiter,
|
|
19
|
+
detectFormat
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=node.js.map
|