convert-csv-to-json 3.28.0 → 4.1.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/docs/ASYNC.md ADDED
@@ -0,0 +1,485 @@
1
+ # Asynchronous API Documentation
2
+
3
+ Promise-based async/await API for modern Node.js applications. Perfect for handling large files, concurrent operations, and integration with async workflows.
4
+
5
+ ## Table of Contents
6
+ - [Basic Usage](#basic-usage)
7
+ - [File Operations](#file-operations)
8
+ - [Working with Raw CSV Data](#working-with-raw-csv-data)
9
+ - [Processing Large Files](#processing-large-files)
10
+ - [Batch Processing](#batch-processing)
11
+ - [Error Handling](#error-handling)
12
+ - [Method Chaining](#method-chaining)
13
+ - [Row Mapping and Transformation](#row-mapping-and-transformation)
14
+ - [TypeScript Support](#typescript-support)
15
+
16
+ ## Basic Usage
17
+
18
+ ```js
19
+ const csvToJson = require('convert-csv-to-json');
20
+
21
+ // Using async/await
22
+ async function parseCSV() {
23
+ const json = await csvToJson.getJsonFromCsvAsync('input.csv');
24
+ console.log(json);
25
+ }
26
+ parseCSV();
27
+
28
+ // Using Promises
29
+ csvToJson.getJsonFromCsvAsync('input.csv')
30
+ .then(json => console.log(json))
31
+ .catch(err => console.error('Error:', err));
32
+ ```
33
+
34
+ ## File Operations
35
+
36
+ ### Read CSV File
37
+
38
+ ```js
39
+ const csvToJson = require('convert-csv-to-json');
40
+
41
+ async function readCSV() {
42
+ try {
43
+ const json = await csvToJson.getJsonFromCsvAsync('input.csv');
44
+ console.log(`Parsed ${json.length} records`);
45
+ return json;
46
+ } catch (error) {
47
+ console.error('Error reading CSV:', error);
48
+ }
49
+ }
50
+ ```
51
+
52
+ ### Generate JSON File from CSV
53
+
54
+ ```js
55
+ async function convertAndSave() {
56
+ await csvToJson
57
+ .fieldDelimiter(',')
58
+ .formatValueByType()
59
+ .generateJsonFileFromCsvAsync('input.csv', 'output.json');
60
+
61
+ console.log('JSON file created successfully');
62
+ }
63
+ ```
64
+
65
+ ### Parse CSV String
66
+
67
+ ```js
68
+ const csv = 'name,age\nAlice,30\nBob,25';
69
+
70
+ // Parse to array
71
+ const json = await csvToJson.csvStringToJsonAsync(csv);
72
+
73
+ // Parse to JSON string (validated)
74
+ const jsonString = await csvToJson.csvStringToJsonStringifiedAsync(csv);
75
+ ```
76
+
77
+ ## Working with Raw CSV Data
78
+
79
+ ### Parse API Response
80
+
81
+ ```js
82
+ async function parseRemoteCSV(url) {
83
+ const response = await fetch(url);
84
+ const csvText = await response.text();
85
+
86
+ const json = await csvToJson
87
+ .formatValueByType()
88
+ .getJsonFromCsvAsync(csvText, { raw: true });
89
+
90
+ return json;
91
+ }
92
+ ```
93
+
94
+ ### Parse from Buffer
95
+
96
+ ```js
97
+ async function parseBuffer(buffer) {
98
+ const csvString = buffer.toString('utf8');
99
+ return csvToJson.getJsonFromCsvAsync(csvString, { raw: true });
100
+ }
101
+ ```
102
+
103
+ ## Processing Large Files
104
+
105
+ ### Stream Processing
106
+
107
+ ```js
108
+ const { createReadStream } = require('fs');
109
+ const { createInterface } = require('readline');
110
+
111
+ async function* processLargeFile(filePath) {
112
+ const fileStream = createReadStream(filePath);
113
+ const lines = createInterface({
114
+ input: fileStream,
115
+ crlfDelay: Infinity
116
+ });
117
+
118
+ const headers = (await lines[Symbol.asyncIterator]().next()).value;
119
+
120
+ for await (const line of lines) {
121
+ const fullCSV = headers + '\n' + line;
122
+ const record = await csvToJson.getJsonFromCsvAsync(fullCSV, { raw: true });
123
+ yield record[0];
124
+ }
125
+ }
126
+
127
+ // Usage
128
+ async function process() {
129
+ for await (const record of processLargeFile('large.csv')) {
130
+ console.log(record);
131
+ // Process one record at a time
132
+ }
133
+ }
134
+ ```
135
+
136
+ ### Chunked Processing
137
+
138
+ ```js
139
+ const fs = require('fs');
140
+
141
+ async function processInChunks(filePath, chunkSize = 1000) {
142
+ const content = fs.readFileSync(filePath, 'utf8');
143
+ const lines = content.split('\n');
144
+ const headers = lines[0];
145
+
146
+ for (let i = 1; i < lines.length; i += chunkSize) {
147
+ const chunk = lines.slice(i, i + chunkSize);
148
+ const csvChunk = headers + '\n' + chunk.join('\n');
149
+
150
+ const json = await csvToJson.getJsonFromCsvAsync(csvChunk, { raw: true });
151
+ await processChunk(json);
152
+ }
153
+ }
154
+
155
+ async function processChunk(records) {
156
+ // Your processing logic here
157
+ console.log(`Processing ${records.length} records`);
158
+ }
159
+ ```
160
+
161
+ ## Batch Processing
162
+
163
+ ### Sequential Processing
164
+
165
+ ```js
166
+ async function processFilesSequentially(files) {
167
+ const results = [];
168
+
169
+ for (const file of files) {
170
+ const json = await csvToJson.getJsonFromCsvAsync(file);
171
+ results.push({ file, data: json });
172
+ }
173
+
174
+ return results;
175
+ }
176
+
177
+ // Usage
178
+ const files = ['data1.csv', 'data2.csv', 'data3.csv'];
179
+ const results = await processFilesSequentially(files);
180
+ ```
181
+
182
+ ### Parallel Processing
183
+
184
+ ```js
185
+ async function processFilesParallel(files, concurrency = 3) {
186
+ const results = new Map();
187
+
188
+ // Process in chunks of concurrent operations
189
+ for (let i = 0; i < files.length; i += concurrency) {
190
+ const batch = files.slice(i, i + concurrency);
191
+
192
+ const promises = batch.map(async file => {
193
+ const json = await csvToJson.getJsonFromCsvAsync(file);
194
+ return [file, json];
195
+ });
196
+
197
+ const batchResults = await Promise.all(promises);
198
+ batchResults.forEach(([file, json]) => results.set(file, json));
199
+ }
200
+
201
+ return results;
202
+ }
203
+
204
+ // Usage
205
+ const results = await processFilesParallel(['file1.csv', 'file2.csv', 'file3.csv'], 2);
206
+ ```
207
+
208
+ ## Error Handling
209
+
210
+ ### Basic Try-Catch
211
+
212
+ ```js
213
+ async function safeRead(filePath) {
214
+ try {
215
+ const json = await csvToJson.getJsonFromCsvAsync(filePath);
216
+ return json;
217
+ } catch (error) {
218
+ console.error(`Failed to read ${filePath}:`, error.message);
219
+ throw error;
220
+ }
221
+ }
222
+ ```
223
+
224
+ ### Retry Logic
225
+
226
+ ```js
227
+ async function readWithRetry(filePath, maxRetries = 3) {
228
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
229
+ try {
230
+ return await csvToJson.getJsonFromCsvAsync(filePath);
231
+ } catch (error) {
232
+ if (attempt === maxRetries) throw error;
233
+
234
+ // Exponential backoff
235
+ const delay = Math.pow(2, attempt - 1) * 1000;
236
+ console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
237
+ await new Promise(resolve => setTimeout(resolve, delay));
238
+ }
239
+ }
240
+ }
241
+ ```
242
+
243
+ ### Error Recovery
244
+
245
+ ```js
246
+ async function processWithFallback(primaryFile, fallbackFile) {
247
+ try {
248
+ return await csvToJson.getJsonFromCsvAsync(primaryFile);
249
+ } catch (error) {
250
+ console.warn(`Failed to read ${primaryFile}, using fallback...`);
251
+ return csvToJson.getJsonFromCsvAsync(fallbackFile);
252
+ }
253
+ }
254
+ ```
255
+
256
+ ## Method Chaining
257
+
258
+ Combine configuration options with async operations:
259
+
260
+ ```js
261
+ const json = await csvToJson
262
+ .fieldDelimiter(';')
263
+ .formatValueByType()
264
+ .supportQuotedField(true)
265
+ .trimHeaderFieldWhiteSpace(true)
266
+ .getJsonFromCsvAsync('file.csv');
267
+
268
+ // Or use async file generation
269
+ await csvToJson
270
+ .fieldDelimiter(',')
271
+ .formatValueByType()
272
+ .generateJsonFileFromCsvAsync('input.csv', 'output.json');
273
+ ```
274
+
275
+ All configuration methods from the [Sync API](SYNC.md) are available with async operations.
276
+
277
+ ## Row Mapping and Transformation
278
+
279
+ The `mapRows()` method allows you to transform, filter, or enrich each row after parsing. The mapping function is applied within the async operation, making it perfect for data transformation pipelines.
280
+
281
+ ### Basic Row Transformation
282
+
283
+ ```js
284
+ async function transformRows() {
285
+ const json = await csvToJson
286
+ .fieldDelimiter(',')
287
+ .mapRows((row, index) => {
288
+ // Add computed fields
289
+ row.id = index + 1;
290
+ row.email = row.email.toLowerCase();
291
+ return row;
292
+ })
293
+ .csvStringToJsonAsync('firstName,lastName,email\nJohn,Doe,John.Doe@example.com');
294
+
295
+ console.log(json);
296
+ // Output: [{ id: 1, firstName: 'John', lastName: 'Doe', email: 'john.doe@example.com' }]
297
+ }
298
+ ```
299
+
300
+ ### Filtering Rows
301
+
302
+ ```js
303
+ async function filterRows() {
304
+ const json = await csvToJson
305
+ .fieldDelimiter(',')
306
+ .mapRows((row) => {
307
+ // Only keep rows where status is 'active'
308
+ if (row.status === 'active') {
309
+ return row;
310
+ }
311
+ return null; // Filter out inactive rows
312
+ })
313
+ .getJsonFromCsvAsync('data.csv');
314
+
315
+ return json; // Contains only active records
316
+ }
317
+ ```
318
+
319
+ ### Data Enrichment
320
+
321
+ ```js
322
+ async function enrichData() {
323
+ const json = await csvToJson
324
+ .fieldDelimiter(';')
325
+ .mapRows((row, index) => {
326
+ // Add metadata and computed properties
327
+ const age = parseInt(row.age);
328
+ return {
329
+ ...row,
330
+ rowId: index,
331
+ ageGroup: age < 18 ? 'minor' : age < 65 ? 'adult' : 'senior',
332
+ processed: new Date().toISOString()
333
+ };
334
+ })
335
+ .getJsonFromCsvAsync('people.csv');
336
+
337
+ return json;
338
+ }
339
+ ```
340
+
341
+ ### Complex Transformations
342
+
343
+ ```js
344
+ async function complexTransformation() {
345
+ const sales = await csvToJson
346
+ .fieldDelimiter(',')
347
+ .formatValueByType()
348
+ .mapRows((row, index) => {
349
+ const amount = typeof row.amount === 'number' ? row.amount : parseFloat(row.amount);
350
+ const quantity = typeof row.quantity === 'number' ? row.quantity : parseInt(row.quantity);
351
+
352
+ return {
353
+ transactionId: `TXN-${String(index + 1).padStart(6, '0')}`,
354
+ customer: row.customer_name,
355
+ product: row.product_id,
356
+ quantity: quantity,
357
+ unitPrice: amount / quantity,
358
+ totalAmount: amount,
359
+ taxable: amount > 100,
360
+ timestamp: new Date().toISOString()
361
+ };
362
+ })
363
+ .getJsonFromCsvAsync('sales.csv');
364
+
365
+ return sales;
366
+ }
367
+ ```
368
+
369
+ ### Validation and Filtering Pipeline
370
+
371
+ ```js
372
+ async function validateAndFilter() {
373
+ const json = await csvToJson
374
+ .fieldDelimiter(',')
375
+ .mapRows((row) => {
376
+ // Validate email format
377
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
378
+ if (!emailRegex.test(row.email)) {
379
+ return null; // Skip invalid rows
380
+ }
381
+
382
+ // Trim whitespace
383
+ row.name = row.name.trim();
384
+ row.email = row.email.trim();
385
+
386
+ return row;
387
+ })
388
+ .getJsonFromCsvAsync('contacts.csv');
389
+
390
+ return json;
391
+ }
392
+ ```
393
+
394
+ ## TypeScript Support
395
+
396
+ ```ts
397
+ import csvToJson from 'convert-csv-to-json';
398
+
399
+ interface Product {
400
+ id: number;
401
+ name: string;
402
+ price: number;
403
+ inStock: boolean;
404
+ }
405
+
406
+ // Read with type assertion
407
+ async function loadProducts(file: string): Promise<Product[]> {
408
+ return csvToJson
409
+ .formatValueByType()
410
+ .getJsonFromCsvAsync(file) as Promise<Product[]>;
411
+ }
412
+
413
+ // Parse string with types
414
+ async function parseCSV(csv: string): Promise<Product[]> {
415
+ return csvToJson
416
+ .csvStringToJsonAsync(csv) as Promise<Product[]>;
417
+ }
418
+
419
+ // Error handling
420
+ async function safeLoad(file: string): Promise<Product[] | null> {
421
+ try {
422
+ return await loadProducts(file);
423
+ } catch (error) {
424
+ console.error('Failed to load products:', error);
425
+ return null;
426
+ }
427
+ }
428
+ ```
429
+
430
+ ## Common Patterns
431
+
432
+ ### Transform Data Pipeline
433
+
434
+ ```js
435
+ async function processAndTransform(csvFile) {
436
+ // 1. Parse CSV
437
+ const raw = await csvToJson
438
+ .formatValueByType()
439
+ .getJsonFromCsvAsync(csvFile);
440
+
441
+ // 2. Filter and transform
442
+ const processed = raw
443
+ .filter(record => record.active)
444
+ .map(record => ({
445
+ id: record.id,
446
+ name: record.name.toUpperCase(),
447
+ displayPrice: `$${record.price.toFixed(2)}`
448
+ }));
449
+
450
+ return processed;
451
+ }
452
+ ```
453
+
454
+ ### Concurrent File Processing with Logging
455
+
456
+ ```js
457
+ async function processMultipleWithLogging(files) {
458
+ const results = [];
459
+
460
+ const promises = files.map(async (file, index) => {
461
+ console.log(`[${index + 1}/${files.length}] Processing ${file}...`);
462
+ const startTime = Date.now();
463
+
464
+ try {
465
+ const json = await csvToJson.getJsonFromCsvAsync(file);
466
+ const duration = Date.now() - startTime;
467
+
468
+ console.log(`[✓] ${file} completed in ${duration}ms (${json.length} records)`);
469
+ return { file, json, success: true };
470
+ } catch (error) {
471
+ console.error(`[✗] ${file} failed:`, error.message);
472
+ return { file, error: error.message, success: false };
473
+ }
474
+ });
475
+
476
+ return Promise.all(promises);
477
+ }
478
+ ```
479
+
480
+ ## See Also
481
+
482
+ - [Main README](../README.md) - Overview and installation
483
+ - [Sync API](SYNC.md) - Synchronous operations
484
+ - [Browser API](BROWSER.md) - Client-side CSV parsing
485
+ - [MIGRATION.md](../migration/MIGRATION_TO_ASYNC.md) - Guide for migrating from Sync to Async