convert-buddy-js 0.12.4 → 0.12.5

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 CHANGED
@@ -8,6 +8,33 @@ A **high-performance, streaming-first** parser and converter for **CSV, XML, NDJ
8
8
 
9
9
  ---
10
10
 
11
+ ## Table of Contents
12
+
13
+ - [Install](#install)
14
+ - [Quick Start](#quick-start)
15
+ - [API Overview](#api-overview)
16
+ - [Simple API](#1-simple-api-for-small-files)
17
+ - [Streaming API](#2-streaming-api-for-large-files--real-time-processing)
18
+ - [Instance-based API](#3-instance-based-api)
19
+ - [Low-level API](#4-low-level-api-for-advanced-use-cases)
20
+ - [Stats & Monitoring](#stats--monitoring)
21
+ - [Format Detection & Structure Analysis](#format-detection--structure-analysis)
22
+ - [Real-World Examples](#real-world-examples)
23
+ - [Formats & Configuration](#formats--configuration)
24
+ - [Transformations & Field Mapping](#transformations--field-mapping)
25
+ - [Transform Basics](#transform-basics)
26
+ - [Transform Modes](#transform-modes)
27
+ - [Field Mapping](#field-mapping)
28
+ - [Compute Functions](#compute-functions)
29
+ - [Type Coercion](#type-coercion)
30
+ - [Error Handling](#transform-error-handling)
31
+ - [Transform Examples](#transform-examples)
32
+ - [How it Works](#how-it-works)
33
+ - [Benchmarks](#benchmarks-repository)
34
+ - [License](#license)
35
+
36
+ ---
37
+
11
38
  ## Status & Quality
12
39
 
13
40
  [![Known Vulnerabilities](https://snyk.io/test/github/brunohanss/convert-buddy/badge.svg)](https://snyk.io/test/github/brunohanss/convert-buddy)
@@ -678,16 +705,26 @@ Supported
678
705
 
679
706
  ## Transformations & Field Mapping
680
707
 
681
- Convert Buddy supports field-level transformations during conversion via the `transform` option. Example:
708
+ Convert Buddy includes a **powerful Rust-based transform engine** that enables field-level transformations, computed fields, type coercion, and data reshaping during conversion all executed in WASM for maximum performance with zero JavaScript overhead.
709
+
710
+ ### Transform Basics
711
+
712
+ Apply transforms using the `transform` option in any conversion:
682
713
 
683
714
  ```ts
684
- const out = await buddy.convert(csvString, {
715
+ import { ConvertBuddy } from "convert-buddy-js";
716
+
717
+ const buddy = new ConvertBuddy();
718
+
719
+ const result = await buddy.convert(csvData, {
685
720
  outputFormat: "json",
686
721
  transform: {
687
- mode: "augment",
722
+ mode: "replace",
688
723
  fields: [
724
+ { targetFieldName: "id", required: true },
689
725
  { targetFieldName: "full_name", compute: "concat(first, ' ', last)" },
690
726
  { targetFieldName: "age", coerce: { type: "i64" }, defaultValue: 0 },
727
+ { targetFieldName: "email", compute: "lower(trim(email))" },
691
728
  ],
692
729
  onMissingField: "null",
693
730
  onCoerceError: "null",
@@ -695,7 +732,511 @@ const out = await buddy.convert(csvString, {
695
732
  });
696
733
  ```
697
734
 
698
- Runtime compute helpers depend on the Rust/WASM core build. For complex transforms consider pre/post-processing in JS.
735
+ **Key Features:**
736
+ - 🚀 **WASM performance** — all transforms execute in Rust/WASM
737
+ - 🔄 **Streaming** — transforms work on line-by-line records without buffering
738
+ - 🧮 **30+ compute functions** — string manipulation, math, logic, type conversions
739
+ - 🎯 **Type coercion** — convert strings to numbers, booleans, timestamps
740
+ - ⚡ **Zero memory overhead** — no intermediate objects or copies in JS
741
+ - 🛡️ **Error policies** — control behavior for missing fields and coercion failures
742
+
743
+ ### Transform Modes
744
+
745
+ **`mode: "replace"`** (default)
746
+ Outputs only the fields you explicitly map. Original fields are discarded.
747
+
748
+ ```ts
749
+ // Input: { "first": "Alice", "last": "Smith", "age": 30, "city": "NYC" }
750
+ // Output: { "full_name": "Alice Smith", "age": 30 }
751
+
752
+ transform: {
753
+ mode: "replace",
754
+ fields: [
755
+ { targetFieldName: "full_name", compute: "concat(first, ' ', last)" },
756
+ { targetFieldName: "age" },
757
+ ],
758
+ }
759
+ ```
760
+
761
+ **`mode: "augment"`**
762
+ Preserves all original fields and adds/overwrites mapped fields.
763
+
764
+ ```ts
765
+ // Input: { "name": "Alice", "age": 30 }
766
+ // Output: { "name": "Alice", "age": 30, "name_upper": "ALICE", "is_adult": true }
767
+
768
+ transform: {
769
+ mode: "augment",
770
+ fields: [
771
+ { targetFieldName: "name_upper", compute: "upper(name)" },
772
+ { targetFieldName: "is_adult", compute: "gte(age, 18)" },
773
+ ],
774
+ }
775
+ ```
776
+
777
+ ### Field Mapping
778
+
779
+ Each field in the `fields` array defines a mapping:
780
+
781
+ ```ts
782
+ type FieldMap = {
783
+ targetFieldName: string; // Output field name
784
+ originFieldName?: string; // Input field name (defaults to targetFieldName)
785
+ required?: boolean; // Fail if missing
786
+ defaultValue?: any; // Fallback value
787
+ coerce?: Coerce; // Type conversion
788
+ compute?: string; // Expression to compute value
789
+ };
790
+ ```
791
+
792
+ **Basic field pass-through:**
793
+ ```ts
794
+ { targetFieldName: "name" } // Maps input "name" to output "name"
795
+ ```
796
+
797
+ **Rename fields:**
798
+ ```ts
799
+ { targetFieldName: "fullName", originFieldName: "full_name" } // Rename full_name → fullName
800
+ ```
801
+
802
+ **Required fields:**
803
+ ```ts
804
+ { targetFieldName: "id", required: true } // Fail conversion if "id" is missing
805
+ ```
806
+
807
+ **Default values:**
808
+ ```ts
809
+ { targetFieldName: "status", defaultValue: "active" } // Use "active" if field is missing or null
810
+ ```
811
+
812
+ **Computed fields:**
813
+ ```ts
814
+ { targetFieldName: "display", compute: "concat(first, ' ', last)" }
815
+ ```
816
+
817
+ **Type coercion:**
818
+ ```ts
819
+ { targetFieldName: "age", coerce: { type: "i64" } } // Convert string "30" → number 30
820
+ ```
821
+
822
+ **Combined:**
823
+ ```ts
824
+ {
825
+ targetFieldName: "age_years",
826
+ originFieldName: "age",
827
+ coerce: { type: "i64" },
828
+ defaultValue: 0,
829
+ required: false,
830
+ }
831
+ ```
832
+
833
+ ### Compute Functions
834
+
835
+ Transform expressions support **30+ built-in functions** for data manipulation:
836
+
837
+ #### String Functions
838
+
839
+ | Function | Description | Example |
840
+ |----------|-------------|---------|
841
+ | `concat(...)` | Join strings | `concat(first, " ", last)` → `"Alice Smith"` |
842
+ | `lower(s)` | Lowercase | `lower("HELLO")` → `"hello"` |
843
+ | `upper(s)` | Uppercase | `upper("hello")` → `"HELLO"` |
844
+ | `trim(s)` | Remove whitespace | `trim(" text ")` → `"text"` |
845
+ | `trim_start(s)` | Remove leading whitespace | `trim_start(" text")` → `"text"` |
846
+ | `trim_end(s)` | Remove trailing whitespace | `trim_end("text ")` → `"text"` |
847
+ | `substring(s, start, end)` | Extract substring | `substring("hello", 0, 3)` → `"hel"` |
848
+ | `replace(s, old, new)` | Replace text | `replace("foo bar", "foo", "baz")` → `"baz bar"` |
849
+ | `len(s)` | String length | `len("hello")` → `5` |
850
+ | `starts_with(s, prefix)` | Check prefix | `starts_with("https://...", "https")` → `true` |
851
+ | `ends_with(s, suffix)` | Check suffix | `ends_with("file.pdf", ".pdf")` → `true` |
852
+ | `contains(s, substr)` | Check substring | `contains("hello world", "world")` → `true` |
853
+ | `pad_start(s, len, char)` | Left-pad | `pad_start("42", 5, "0")` → `"00042"` |
854
+ | `pad_end(s, len, char)` | Right-pad | `pad_end("x", 3, "_")` → `"x__"` |
855
+ | `repeat(s, n)` | Repeat string | `repeat("ab", 3)` → `"ababab"` |
856
+ | `reverse(s)` | Reverse string | `reverse("hello")` → `"olleh"` |
857
+ | `split(s, delim)` | Split to array | `split("a,b,c", ",")` → `["a","b","c"]` |
858
+ | `join(arr, delim)` | Join array | `join(["a","b"], ",")` → `"a,b"` |
859
+
860
+ #### Math Functions
861
+
862
+ | Function | Description | Example |
863
+ |----------|-------------|---------|
864
+ | `+`, `-`, `*`, `/` | Arithmetic operators | `price * 1.1` |
865
+ | `round(n)` | Round to nearest integer | `round(3.7)` → `4` |
866
+ | `floor(n)` | Round down | `floor(3.9)` → `3` |
867
+ | `ceil(n)` | Round up | `ceil(3.1)` → `4` |
868
+ | `abs(n)` | Absolute value | `abs(-5)` → `5` |
869
+ | `min(...)` | Minimum value | `min(a, b, c)` → smallest |
870
+ | `max(...)` | Maximum value | `max(a, b, c)` → largest |
871
+
872
+ #### Logic & Comparison
873
+
874
+ | Function | Description | Example |
875
+ |----------|-------------|---------|
876
+ | `if(cond, true_val, false_val)` | Conditional | `if(age >= 18, "adult", "minor")` |
877
+ | `not(bool)` | Boolean NOT | `not(active)` → opposite |
878
+ | `eq(a, b)` | Equals | `eq(status, "active")` → `true/false` |
879
+ | `ne(a, b)` | Not equals | `ne(a, b)` |
880
+ | `gt(a, b)` | Greater than | `gt(age, 18)` |
881
+ | `gte(a, b)` | Greater than or equal | `gte(age, 18)` |
882
+ | `lt(a, b)` | Less than | `lt(price, 100)` |
883
+ | `lte(a, b)` | Less than or equal | `lte(score, 50)` |
884
+
885
+ #### Type Checking
886
+
887
+ | Function | Description | Example |
888
+ |----------|-------------|---------|
889
+ | `is_null(val)` | Check if null | `is_null(optional_field)` → `true/false` |
890
+ | `is_number(val)` | Check if number | `is_number(val)` → `true/false` |
891
+ | `is_string(val)` | Check if string | `is_string(val)` → `true/false` |
892
+ | `is_bool(val)` | Check if boolean | `is_bool(val)` → `true/false` |
893
+
894
+ #### Type Conversion
895
+
896
+ | Function | Description | Example |
897
+ |----------|-------------|---------|
898
+ | `to_string(val)` | Convert to string | `to_string(42)` → `"42"` |
899
+ | `parse_int(s)` | Parse string to integer | `parse_int("123")` → `123` |
900
+ | `parse_float(s)` | Parse string to float | `parse_float("3.14")` → `3.14` |
901
+
902
+ #### Utility Functions
903
+
904
+ | Function | Description | Example |
905
+ |----------|-------------|---------|
906
+ | `coalesce(...)` | First non-null value | `coalesce(alt1, alt2, "default")` |
907
+ | `default(val, fallback)` | Fallback for null | `default(optional, "N/A")` |
908
+
909
+ **Nested expressions:**
910
+ ```ts
911
+ compute: "upper(trim(concat(first, ' ', last)))"
912
+ // Input: { first: " alice ", last: " smith " }
913
+ // Output: "ALICE SMITH"
914
+ ```
915
+
916
+ **Complex logic:**
917
+ ```ts
918
+ compute: "if(gte(age, 18), 'adult', if(gte(age, 13), 'teen', 'child'))"
919
+ ```
920
+
921
+ ### Type Coercion
922
+
923
+ Convert field types automatically:
924
+
925
+ ```ts
926
+ type Coerce =
927
+ | { type: "string" }
928
+ | { type: "i64" } // 64-bit integer
929
+ | { type: "f64" } // 64-bit float
930
+ | { type: "bool" }
931
+ | { type: "timestamp_ms"; format?: "iso8601" | "unix_ms" | "unix_s" };
932
+ ```
933
+
934
+ **String coercion:**
935
+ ```ts
936
+ // Number → String: 42 → "42"
937
+ // Boolean → String: true → "true"
938
+ // Null → String: null → ""
939
+ { targetFieldName: "age_str", originFieldName: "age", coerce: { type: "string" } }
940
+ ```
941
+
942
+ **Integer coercion (`i64`):**
943
+ ```ts
944
+ // String → Integer: "42" → 42
945
+ // Float → Integer: 3.7 → 3 (truncates)
946
+ // Boolean → Integer: true → 1, false → 0
947
+ { targetFieldName: "count", coerce: { type: "i64" } }
948
+ ```
949
+
950
+ **Float coercion (`f64`):**
951
+ ```ts
952
+ // String → Float: "3.14" → 3.14
953
+ // Integer → Float: 42 → 42.0
954
+ { targetFieldName: "price", coerce: { type: "f64" } }
955
+ ```
956
+
957
+ **Boolean coercion:**
958
+ ```ts
959
+ // String → Boolean: "true"/"false" → true/false, "1"/"0" → true/false
960
+ // Number → Boolean: 0 → false, non-zero → true
961
+ { targetFieldName: "active", coerce: { type: "bool" } }
962
+ ```
963
+
964
+ **Timestamp coercion:**
965
+ ```ts
966
+ // ISO8601 string → Unix timestamp (ms)
967
+ {
968
+ targetFieldName: "created_ts",
969
+ originFieldName: "created_at",
970
+ coerce: { type: "timestamp_ms", format: "iso8601" }
971
+ }
972
+ // "2024-01-15T10:30:00Z" → 1705315800000
973
+
974
+ // Unix seconds → milliseconds
975
+ {
976
+ targetFieldName: "updated_ts",
977
+ coerce: { type: "timestamp_ms", format: "unix_s" }
978
+ }
979
+ // 1705315800 → 1705315800000
980
+ ```
981
+
982
+ ### Transform Error Handling
983
+
984
+ Control behavior when fields are missing or coercion fails:
985
+
986
+ **`onMissingField`** — What to do when a field is missing:
987
+ - `"error"` — Fail the entire conversion
988
+ - `"null"` — Insert `null` for missing fields
989
+ - `"drop"` — Omit the field from output
990
+
991
+ ```ts
992
+ transform: {
993
+ fields: [{ targetFieldName: "optional_field" }],
994
+ onMissingField: "null", // Missing fields become null
995
+ }
996
+ ```
997
+
998
+ **`onMissingRequired`** — What to do when a required field is missing:
999
+ - `"error"` — Fail the conversion (default)
1000
+ - `"abort"` — Stop processing this record
1001
+
1002
+ ```ts
1003
+ transform: {
1004
+ fields: [{ targetFieldName: "id", required: true }],
1005
+ onMissingRequired: "error", // Fail if "id" is missing
1006
+ }
1007
+ ```
1008
+
1009
+ **`onCoerceError`** — What to do when type coercion fails:
1010
+ - `"error"` — Fail the entire conversion
1011
+ - `"null"` — Set field to `null` on coercion failure
1012
+ - `"dropRecord"` — Silently skip records that fail coercion
1013
+
1014
+ ```ts
1015
+ transform: {
1016
+ fields: [{ targetFieldName: "age", coerce: { type: "i64" } }],
1017
+ onCoerceError: "null", // "invalid" → null instead of throwing
1018
+ }
1019
+ ```
1020
+
1021
+ **Skip invalid records:**
1022
+ ```ts
1023
+ // Drop records where age cannot be parsed as integer
1024
+ transform: {
1025
+ fields: [
1026
+ { targetFieldName: "name" },
1027
+ { targetFieldName: "age", coerce: { type: "i64" } },
1028
+ ],
1029
+ onCoerceError: "dropRecord", // Skip bad records silently
1030
+ }
1031
+ ```
1032
+
1033
+ ### Transform Examples
1034
+
1035
+ **Example 1: Clean and normalize user data**
1036
+
1037
+ ```ts
1038
+ const controller = buddy.stream("users.csv", {
1039
+ outputFormat: "json",
1040
+ transform: {
1041
+ mode: "replace",
1042
+ fields: [
1043
+ // Required ID
1044
+ { targetFieldName: "id", required: true },
1045
+
1046
+ // Normalize name
1047
+ {
1048
+ targetFieldName: "full_name",
1049
+ compute: "trim(concat(first_name, ' ', last_name))"
1050
+ },
1051
+
1052
+ // Lowercase email
1053
+ { targetFieldName: "email", compute: "lower(trim(email))" },
1054
+
1055
+ // Parse age as integer with default
1056
+ {
1057
+ targetFieldName: "age",
1058
+ coerce: { type: "i64" },
1059
+ defaultValue: 0
1060
+ },
1061
+
1062
+ // Active status as boolean
1063
+ { targetFieldName: "active", coerce: { type: "bool" } },
1064
+ ],
1065
+ onMissingField: "null",
1066
+ onCoerceError: "null",
1067
+ },
1068
+ onRecords: async (ctrl, records) => {
1069
+ await db.users.insertMany(records);
1070
+ },
1071
+ });
1072
+ ```
1073
+
1074
+ **Example 2: Calculate derived fields**
1075
+
1076
+ ```ts
1077
+ // Add computed fields to existing data
1078
+ transform: {
1079
+ mode: "augment", // Keep all original fields
1080
+ fields: [
1081
+ // Calculate total with tax
1082
+ {
1083
+ targetFieldName: "total_with_tax",
1084
+ compute: "round(price * (1 + tax_rate))"
1085
+ },
1086
+
1087
+ // Discount percentage
1088
+ {
1089
+ targetFieldName: "discount_pct",
1090
+ compute: "round((original_price - price) / original_price * 100)"
1091
+ },
1092
+
1093
+ // Is on sale?
1094
+ {
1095
+ targetFieldName: "on_sale",
1096
+ compute: "lt(price, original_price)"
1097
+ },
1098
+ ],
1099
+ }
1100
+ ```
1101
+
1102
+ **Example 3: Data validation and filtering**
1103
+
1104
+ ```ts
1105
+ // Only keep records with valid email and age >= 18
1106
+ const validRecords = [];
1107
+
1108
+ const controller = buddy.stream(csvData, {
1109
+ outputFormat: "ndjson",
1110
+ transform: {
1111
+ mode: "replace",
1112
+ fields: [
1113
+ { targetFieldName: "email", required: true },
1114
+ { targetFieldName: "age", coerce: { type: "i64" }, required: true },
1115
+ {
1116
+ targetFieldName: "is_adult",
1117
+ compute: "gte(age, 18)"
1118
+ },
1119
+ ],
1120
+ onMissingRequired: "error",
1121
+ onCoerceError: "dropRecord", // Skip records with invalid age
1122
+ },
1123
+ onRecords: (ctrl, records) => {
1124
+ // Filter for adults only
1125
+ const adults = records.filter(r => r.is_adult);
1126
+ validRecords.push(...adults);
1127
+ },
1128
+ });
1129
+ ```
1130
+
1131
+ **Example 4: Format conversion with field mapping**
1132
+
1133
+ ```ts
1134
+ // Convert XML to CSV with field restructuring
1135
+ const controller = buddy.stream("data.xml", {
1136
+ inputFormat: "xml",
1137
+ outputFormat: "csv",
1138
+ xmlConfig: { recordElement: "user" },
1139
+ transform: {
1140
+ mode: "replace",
1141
+ fields: [
1142
+ { targetFieldName: "user_id", originFieldName: "id" },
1143
+ { targetFieldName: "name", compute: "concat(firstName, ' ', lastName)" },
1144
+ { targetFieldName: "email_domain", compute: "split(email, '@')[1]" },
1145
+ {
1146
+ targetFieldName: "created_date",
1147
+ originFieldName: "createdAt",
1148
+ coerce: { type: "timestamp_ms", format: "iso8601" }
1149
+ },
1150
+ ],
1151
+ },
1152
+ onData: (chunk) => {
1153
+ fs.appendFileSync("output.csv", chunk);
1154
+ },
1155
+ });
1156
+ ```
1157
+
1158
+ **Example 5: Streaming with real-time transforms**
1159
+
1160
+ ```ts
1161
+ // Process large file with transforms in streaming mode
1162
+ let processedCount = 0;
1163
+
1164
+ const controller = buddy.stream("massive-dataset.csv", {
1165
+ outputFormat: "ndjson",
1166
+ recordBatchSize: 1000,
1167
+ transform: {
1168
+ mode: "replace",
1169
+ fields: [
1170
+ { targetFieldName: "id" },
1171
+ { targetFieldName: "name_upper", compute: "upper(name)" },
1172
+ { targetFieldName: "price", coerce: { type: "f64" } },
1173
+ {
1174
+ targetFieldName: "price_category",
1175
+ compute: "if(gt(price, 100), 'premium', if(gt(price, 50), 'mid', 'budget'))"
1176
+ },
1177
+ ],
1178
+ onMissingField: "drop",
1179
+ },
1180
+ onRecords: async (ctrl, records, stats) => {
1181
+ processedCount += records.length;
1182
+ console.log(`Transformed ${processedCount} records at ${stats.throughputMbPerSec.toFixed(2)} MB/s`);
1183
+
1184
+ // Stream directly to database
1185
+ await db.products.insertMany(records);
1186
+ },
1187
+ });
1188
+
1189
+ await controller.done;
1190
+ ```
1191
+
1192
+ **Example 6: Complex field transformations**
1193
+
1194
+ ```ts
1195
+ transform: {
1196
+ mode: "replace",
1197
+ fields: [
1198
+ // Combine multiple fields with formatting
1199
+ {
1200
+ targetFieldName: "address",
1201
+ compute: "concat(street, ', ', city, ', ', state, ' ', zip)"
1202
+ },
1203
+
1204
+ // Conditional logic
1205
+ {
1206
+ targetFieldName: "shipping_fee",
1207
+ compute: "if(eq(country, 'US'), 5.00, if(eq(country, 'CA'), 7.50, 12.00))"
1208
+ },
1209
+
1210
+ // Nested string operations
1211
+ {
1212
+ targetFieldName: "username",
1213
+ compute: "lower(trim(replace(email, '@', '_at_')))"
1214
+ },
1215
+
1216
+ // Math with multiple fields
1217
+ {
1218
+ targetFieldName: "bmi",
1219
+ compute: "round(weight / ((height / 100) * (height / 100)))"
1220
+ },
1221
+
1222
+ // String manipulation chain
1223
+ {
1224
+ targetFieldName: "display_name",
1225
+ compute: "concat(upper(substring(first, 0, 1)), '. ', last)"
1226
+ },
1227
+ ],
1228
+ }
1229
+ ```
1230
+
1231
+ ### Performance Notes
1232
+
1233
+ - ✅ **Zero JS overhead** — transforms execute entirely in Rust/WASM
1234
+ - ✅ **Streaming** — processes line-by-line, no buffering of entire dataset
1235
+ - ✅ **Type safety** — expression parser validates syntax at compile time
1236
+ - ✅ **Memory efficient** — uses WASM linear memory, no JS objects created
1237
+ - ⚡ **Throughput** — typically adds <10% overhead vs. raw conversion
1238
+
1239
+ For extremely complex transformations (e.g., API lookups, database joins), consider using `onRecords` callback for post-processing in JavaScript.
699
1240
 
700
1241
  ---
701
1242
 
package/dist/browser.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ConvertOptions, Format } from './index.js';
2
- export { BuddyController, BuddyInput, BuddyStats, BuddyStreamOptions, Coerce, ConvertBuddy, ConvertBuddyOptions, ConvertBuddyTransformStream, ConvertBuddy as Converter, CsvConfig, CsvDetection, DetectInput, DetectOptions, FieldMap, JsonDetection, NdjsonDetection, ProgressCallback, Stats, StreamController, StreamInput, StreamOptions, StreamResult, StructureDetection, TransformConfig, TransformMode, XmlConfig, XmlDetection, autoDetectConfig, convertAny, convertAnyToString, createStreamController, detectCsvFieldsAndDelimiter, detectFormat, detectStructure, detectXmlElements, getExtension, getMimeType, getOptimalThreadCount, getSuggestedFilename, getThreadingInfo, isWasmThreadingSupported, processStream, stream, streamRecords } from './index.js';
2
+ export { BuddyController, BuddyStats, BuddyStreamOptions, Coerce, ConvertBuddy, ConvertBuddyOptions, ConvertBuddyTransformStream, ConvertBuddy as Converter, CsvConfig, CsvDetection, DetectInput, DetectOptions, FieldMap, JsonDetection, NdjsonDetection, ProgressCallback, Stats, StructureDetection, TransformConfig, TransformMode, XmlConfig, XmlDetection, autoDetectConfig, convertAny, convertAnyToString, detectCsvFieldsAndDelimiter, detectFormat, detectStructure, detectXmlElements, getExtension, getMimeType, getOptimalThreadCount, getSuggestedFilename, getThreadingInfo, isWasmThreadingSupported, stream } from './index.js';
3
3
 
4
4
  /**
5
5
  * Browser entry point for convert-buddy-js