jtcsv 2.2.7 → 3.0.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.
Files changed (140) hide show
  1. package/README.md +31 -1
  2. package/bin/jtcsv.js +891 -821
  3. package/bin/jtcsv.ts +2534 -0
  4. package/csv-to-json.js +168 -145
  5. package/dist/jtcsv-core.cjs.js +1407 -0
  6. package/dist/jtcsv-core.cjs.js.map +1 -0
  7. package/dist/jtcsv-core.esm.js +1379 -0
  8. package/dist/jtcsv-core.esm.js.map +1 -0
  9. package/dist/jtcsv-core.umd.js +1413 -0
  10. package/dist/jtcsv-core.umd.js.map +1 -0
  11. package/dist/jtcsv-full.cjs.js +1912 -0
  12. package/dist/jtcsv-full.cjs.js.map +1 -0
  13. package/dist/jtcsv-full.esm.js +1880 -0
  14. package/dist/jtcsv-full.esm.js.map +1 -0
  15. package/dist/jtcsv-full.umd.js +1918 -0
  16. package/dist/jtcsv-full.umd.js.map +1 -0
  17. package/dist/jtcsv-workers.esm.js +759 -0
  18. package/dist/jtcsv-workers.esm.js.map +1 -0
  19. package/dist/jtcsv-workers.umd.js +773 -0
  20. package/dist/jtcsv-workers.umd.js.map +1 -0
  21. package/dist/jtcsv.cjs.js +61 -19
  22. package/dist/jtcsv.cjs.js.map +1 -1
  23. package/dist/jtcsv.esm.js +61 -19
  24. package/dist/jtcsv.esm.js.map +1 -1
  25. package/dist/jtcsv.umd.js +61 -19
  26. package/dist/jtcsv.umd.js.map +1 -1
  27. package/errors.js +188 -2
  28. package/examples/advanced/conditional-transformations.js +446 -0
  29. package/examples/advanced/conditional-transformations.ts +446 -0
  30. package/examples/advanced/csv-parser.worker.js +89 -0
  31. package/examples/advanced/csv-parser.worker.ts +89 -0
  32. package/examples/advanced/nested-objects-example.js +306 -0
  33. package/examples/advanced/nested-objects-example.ts +306 -0
  34. package/examples/advanced/performance-optimization.js +504 -0
  35. package/examples/advanced/performance-optimization.ts +504 -0
  36. package/examples/advanced/run-demo-server.js +116 -0
  37. package/examples/advanced/run-demo-server.ts +116 -0
  38. package/examples/advanced/web-worker-usage.html +874 -0
  39. package/examples/async-multithreaded-example.ts +335 -0
  40. package/examples/cli-advanced-usage.md +288 -0
  41. package/examples/cli-batch-processing.ts +38 -0
  42. package/examples/cli-tool.js +0 -3
  43. package/examples/cli-tool.ts +183 -0
  44. package/examples/error-handling.js +21 -7
  45. package/examples/error-handling.ts +356 -0
  46. package/examples/express-api.js +0 -3
  47. package/examples/express-api.ts +164 -0
  48. package/examples/large-dataset-example.js +0 -3
  49. package/examples/large-dataset-example.ts +204 -0
  50. package/examples/ndjson-processing.js +1 -1
  51. package/examples/ndjson-processing.ts +456 -0
  52. package/examples/plugin-excel-exporter.js +3 -4
  53. package/examples/plugin-excel-exporter.ts +406 -0
  54. package/examples/react-integration.tsx +637 -0
  55. package/examples/schema-validation.ts +640 -0
  56. package/examples/simple-usage.js +254 -254
  57. package/examples/simple-usage.ts +194 -0
  58. package/examples/streaming-example.js +4 -5
  59. package/examples/streaming-example.ts +419 -0
  60. package/examples/web-workers-advanced.ts +28 -0
  61. package/index.d.ts +1 -3
  62. package/index.js +15 -1
  63. package/json-save.js +9 -3
  64. package/json-to-csv.js +168 -21
  65. package/package.json +69 -10
  66. package/plugins/express-middleware/README.md +21 -2
  67. package/plugins/express-middleware/example.js +3 -4
  68. package/plugins/express-middleware/example.ts +135 -0
  69. package/plugins/express-middleware/index.d.ts +1 -1
  70. package/plugins/express-middleware/index.js +270 -118
  71. package/plugins/express-middleware/index.ts +557 -0
  72. package/plugins/fastify-plugin/index.js +2 -4
  73. package/plugins/fastify-plugin/index.ts +443 -0
  74. package/plugins/hono/index.ts +226 -0
  75. package/plugins/nestjs/index.ts +201 -0
  76. package/plugins/nextjs-api/examples/ConverterComponent.tsx +386 -0
  77. package/plugins/nextjs-api/examples/api-convert.js +0 -2
  78. package/plugins/nextjs-api/examples/api-convert.ts +67 -0
  79. package/plugins/nextjs-api/index.tsx +339 -0
  80. package/plugins/nextjs-api/route.js +2 -3
  81. package/plugins/nextjs-api/route.ts +370 -0
  82. package/plugins/nuxt/index.ts +94 -0
  83. package/plugins/nuxt/runtime/composables/useJtcsv.ts +100 -0
  84. package/plugins/nuxt/runtime/plugin.ts +71 -0
  85. package/plugins/remix/index.js +1 -1
  86. package/plugins/remix/index.ts +260 -0
  87. package/plugins/sveltekit/index.js +1 -1
  88. package/plugins/sveltekit/index.ts +301 -0
  89. package/plugins/trpc/index.ts +267 -0
  90. package/src/browser/browser-functions.ts +402 -0
  91. package/src/browser/core.js +92 -0
  92. package/src/browser/core.ts +152 -0
  93. package/src/browser/csv-to-json-browser.d.ts +3 -0
  94. package/src/browser/csv-to-json-browser.js +36 -14
  95. package/src/browser/csv-to-json-browser.ts +264 -0
  96. package/src/browser/errors-browser.ts +303 -0
  97. package/src/browser/extensions/plugins.js +92 -0
  98. package/src/browser/extensions/plugins.ts +93 -0
  99. package/src/browser/extensions/workers.js +39 -0
  100. package/src/browser/extensions/workers.ts +39 -0
  101. package/src/browser/globals.d.ts +5 -0
  102. package/src/browser/index.ts +192 -0
  103. package/src/browser/json-to-csv-browser.d.ts +3 -0
  104. package/src/browser/json-to-csv-browser.js +13 -3
  105. package/src/browser/json-to-csv-browser.ts +262 -0
  106. package/src/browser/streams.js +12 -2
  107. package/src/browser/streams.ts +336 -0
  108. package/src/browser/workers/csv-parser.worker.ts +377 -0
  109. package/src/browser/workers/worker-pool.ts +548 -0
  110. package/src/core/delimiter-cache.js +22 -8
  111. package/src/core/delimiter-cache.ts +310 -0
  112. package/src/core/node-optimizations.ts +449 -0
  113. package/src/core/plugin-system.js +29 -11
  114. package/src/core/plugin-system.ts +400 -0
  115. package/src/core/transform-hooks.ts +558 -0
  116. package/src/engines/fast-path-engine-new.ts +347 -0
  117. package/src/engines/fast-path-engine.ts +854 -0
  118. package/src/errors.ts +72 -0
  119. package/src/formats/ndjson-parser.ts +469 -0
  120. package/src/formats/tsv-parser.ts +334 -0
  121. package/src/index-with-plugins.js +16 -9
  122. package/src/index-with-plugins.ts +395 -0
  123. package/src/types/index.ts +255 -0
  124. package/src/utils/bom-utils.js +259 -0
  125. package/src/utils/bom-utils.ts +373 -0
  126. package/src/utils/encoding-support.js +124 -0
  127. package/src/utils/encoding-support.ts +155 -0
  128. package/src/utils/schema-validator.js +19 -19
  129. package/src/utils/schema-validator.ts +819 -0
  130. package/src/utils/transform-loader.js +1 -1
  131. package/src/utils/transform-loader.ts +389 -0
  132. package/src/utils/zod-adapter.js +170 -0
  133. package/src/utils/zod-adapter.ts +280 -0
  134. package/src/web-server/index.js +10 -10
  135. package/src/web-server/index.ts +683 -0
  136. package/src/workers/csv-multithreaded.ts +310 -0
  137. package/src/workers/csv-parser.worker.ts +227 -0
  138. package/src/workers/worker-pool.ts +409 -0
  139. package/stream-csv-to-json.js +26 -8
  140. package/stream-json-to-csv.js +1 -0
@@ -0,0 +1,504 @@
1
+ /**
2
+ * Advanced Example: Performance Optimization Patterns
3
+ *
4
+ * Demonstrates various performance optimization techniques with jtcsv
5
+ * including caching, streaming, batch processing, and memory management.
6
+ */
7
+
8
+ const { csvToJson, jsonToCsv, createCsvToJsonStream, createJsonToCsvStream } = require('../../index.js');
9
+ const fs = require('fs');
10
+ const { pipeline } = require('stream/promises');
11
+ const { performance, PerformanceObserver } = require('perf_hooks');
12
+
13
+ /**
14
+ * Example 1: Delimiter Caching for Repeated Operations
15
+ *
16
+ * Scenario: Processing multiple CSV files with similar structure
17
+ */
18
+ async function exampleDelimiterCaching() {
19
+ console.log('=== Example 1: Delimiter Caching ===\n');
20
+
21
+ // Create multiple CSV files with different delimiters
22
+ const testFiles = [
23
+ { name: 'semicolon.csv', content: 'id;name;age\n1;Alice;30\n2;Bob;25\n3;Charlie;35', delimiter: ';' },
24
+ { name: 'comma.csv', content: 'id,name,age\n1,Alice,30\n2,Bob,25\n3,Charlie,35', delimiter: ',' },
25
+ { name: 'pipe.csv', content: 'id|name|age\n1|Alice|30\n2|Bob|25\n3|Charlie|35', delimiter: '|' },
26
+ { name: 'tab.csv', content: 'id\tname\tage\n1\tAlice\t30\n2\tBob\t25\n3\tCharlie\t35', delimiter: '\t' }
27
+ ];
28
+
29
+ console.log('Processing without caching:');
30
+ const timesWithoutCache = [];
31
+
32
+ for (const file of testFiles) {
33
+ const start = performance.now();
34
+
35
+ // Process without cache (auto-detection each time)
36
+ const data = csvToJson(file.content, {
37
+ autoDetect: true,
38
+ useCache: false, // Explicitly disable cache
39
+ parseNumbers: true
40
+ });
41
+
42
+ const end = performance.now();
43
+ timesWithoutCache.push(end - start);
44
+
45
+ console.log(` ${file.name}: ${(end - start).toFixed(2)}ms (detected: ${data.length} rows)`);
46
+ }
47
+
48
+ console.log('\nProcessing with caching:');
49
+ const timesWithCache = [];
50
+
51
+ for (const file of testFiles) {
52
+ const start = performance.now();
53
+
54
+ // Process with cache (reuses delimiter detection)
55
+ const data = csvToJson(file.content, {
56
+ autoDetect: true,
57
+ useCache: true, // Enable caching
58
+ parseNumbers: true
59
+ });
60
+
61
+ const end = performance.now();
62
+ timesWithCache.push(end - start);
63
+
64
+ console.log(` ${file.name}: ${(end - start).toFixed(2)}ms (detected: ${data.length} rows)`);
65
+ }
66
+
67
+ const avgWithoutCache = timesWithoutCache.reduce((a, b) => a + b, 0) / timesWithoutCache.length;
68
+ const avgWithCache = timesWithCache.reduce((a, b) => a + b, 0) / timesWithCache.length;
69
+ const improvement = ((avgWithoutCache - avgWithCache) / avgWithoutCache * 100).toFixed(1);
70
+
71
+ console.log(`\nPerformance Improvement: ${improvement}% faster with caching`);
72
+ console.log(`Average time without cache: ${avgWithoutCache.toFixed(2)}ms`);
73
+ console.log(`Average time with cache: ${avgWithCache.toFixed(2)}ms`);
74
+ }
75
+
76
+ /**
77
+ * Example 2: Memory-Efficient Streaming with Backpressure Control
78
+ *
79
+ * Scenario: Processing very large files with controlled memory usage
80
+ */
81
+ async function exampleMemoryEfficientStreaming() {
82
+ console.log('\n\n=== Example 2: Memory-Efficient Streaming ===\n');
83
+
84
+ // Create a large CSV file (in memory for demonstration)
85
+ const rowCount = 100000;
86
+ const headers = Array.from({ length: 20 }, (_, i) => `column${i + 1}`);
87
+ const largeCsv = headers.join(',') + '\n' +
88
+ Array.from({ length: rowCount }, (_, rowIndex) =>
89
+ headers.map((_, colIndex) => `value${rowIndex}_${colIndex}`).join(',')
90
+ ).join('\n');
91
+
92
+ console.log(`Generated ${rowCount.toLocaleString()} rows with ${headers.length} columns`);
93
+ console.log('Approximate size:', Math.round(largeCsv.length / 1024 / 1024 * 100) / 100, 'MB');
94
+
95
+ // Method 1: In-memory processing (high memory usage)
96
+ console.log('\nMethod 1: In-memory processing');
97
+ const memoryStart = performance.now();
98
+ const memoryUsageBefore = process.memoryUsage();
99
+
100
+ try {
101
+ const allData = csvToJson(largeCsv, {
102
+ hasHeaders: true,
103
+ maxRows: 10000 // Limit for demonstration
104
+ });
105
+
106
+ const memoryUsageAfter = process.memoryUsage();
107
+ const memoryEnd = performance.now();
108
+
109
+ console.log(` Time: ${(memoryEnd - memoryStart).toFixed(2)}ms`);
110
+ console.log(` Memory increase: ${Math.round((memoryUsageAfter.heapUsed - memoryUsageBefore.heapUsed) / 1024 / 1024)} MB`);
111
+ console.log(` Rows processed: ${allData.length}`);
112
+ } catch (error) {
113
+ console.log(` Error: ${error.message} (likely out of memory)`);
114
+ }
115
+
116
+ // Method 2: Streaming with backpressure control
117
+ console.log('\nMethod 2: Streaming with backpressure control');
118
+ const streamStart = performance.now();
119
+ const streamMemoryBefore = process.memoryUsage();
120
+
121
+ let streamRowCount = 0;
122
+ let batchCount = 0;
123
+ const batchSize = 1000;
124
+
125
+ const { Readable, Transform, Writable } = require('stream');
126
+
127
+ // Create readable stream from CSV string
128
+ const readable = new Readable({
129
+ read() {
130
+ this.push(largeCsv);
131
+ this.push(null); // End stream
132
+ }
133
+ });
134
+
135
+ // Create CSV parser stream with controlled batch processing
136
+ const csvStream = createCsvToJsonStream({
137
+ hasHeaders: true
138
+ });
139
+
140
+ // Custom transform to control backpressure
141
+ const batchProcessor = new Transform({
142
+ objectMode: true,
143
+ highWaterMark: 100, // Control memory by limiting buffer size
144
+
145
+ transform(row, encoding, callback) {
146
+ streamRowCount++;
147
+
148
+ // Process in batches
149
+ if (streamRowCount % batchSize === 0) {
150
+ batchCount++;
151
+
152
+ // Simulate batch processing (e.g., database insert)
153
+ // In real scenario, this could be async database operation
154
+
155
+ // Control backpressure: pause if processing is slow
156
+ if (batchCount % 10 === 0) {
157
+ setTimeout(() => {
158
+ callback(null, row);
159
+ }, 10); // Simulate slow processing
160
+ } else {
161
+ callback(null, row);
162
+ }
163
+ } else {
164
+ callback(null, row);
165
+ }
166
+ }
167
+ });
168
+
169
+ // Monitor memory during streaming
170
+ const memorySamples = [];
171
+ const memoryMonitor = setInterval(() => {
172
+ memorySamples.push(process.memoryUsage().heapUsed);
173
+ }, 100);
174
+
175
+ // Collector that does nothing (just counts)
176
+ const collector = new Writable({
177
+ objectMode: true,
178
+ write(row, encoding, callback) {
179
+ callback();
180
+ }
181
+ });
182
+
183
+ try {
184
+ await pipeline(readable, csvStream, batchProcessor, collector);
185
+
186
+ clearInterval(memoryMonitor);
187
+ const streamEnd = performance.now();
188
+ const streamMemoryAfter = process.memoryUsage();
189
+
190
+ const peakMemory = Math.max(...memorySamples);
191
+ const avgMemory = memorySamples.reduce((a, b) => a + b, 0) / memorySamples.length;
192
+
193
+ console.log(` Time: ${(streamEnd - streamStart).toFixed(2)}ms`);
194
+ console.log(` Peak memory: ${Math.round(peakMemory / 1024 / 1024)} MB`);
195
+ console.log(` Average memory: ${Math.round(avgMemory / 1024 / 1024)} MB`);
196
+ console.log(` Final memory: ${Math.round(streamMemoryAfter.heapUsed / 1024 / 1024)} MB`);
197
+ console.log(` Memory increase: ${Math.round((streamMemoryAfter.heapUsed - streamMemoryBefore.heapUsed) / 1024 / 1024)} MB`);
198
+ console.log(` Rows processed: ${streamRowCount.toLocaleString()}`);
199
+ console.log(` Batches: ${batchCount}`);
200
+
201
+ } catch (error) {
202
+ clearInterval(memoryMonitor);
203
+ console.log(` Error: ${error.message}`);
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Example 3: Parallel Processing with Worker Threads
209
+ *
210
+ * Scenario: CPU-intensive transformations on large datasets
211
+ */
212
+ async function exampleParallelProcessing() {
213
+ console.log('\n\n=== Example 3: Parallel Processing ===\n');
214
+
215
+ // Generate sample data
216
+ const rowCount = 50000;
217
+ const data = Array.from({ length: rowCount }, (_, i) => ({
218
+ id: i + 1,
219
+ value: Math.random() * 1000,
220
+ category: `CAT${Math.floor(Math.random() * 10) + 1}`,
221
+ timestamp: new Date(Date.now() - Math.random() * 10000000000).toISOString()
222
+ }));
223
+
224
+ console.log(`Generated ${rowCount.toLocaleString()} rows for processing`);
225
+
226
+ // CPU-intensive transformation function
227
+ function complexTransformation(row) {
228
+ // Simulate CPU-intensive operations
229
+ const result = { ...row };
230
+
231
+ // Multiple mathematical operations
232
+ for (let i = 0; i < 100; i++) {
233
+ result.value = Math.sin(result.value) * Math.cos(result.value) * Math.tan(result.value);
234
+ result.value = Math.sqrt(Math.abs(result.value)) * Math.log(Math.abs(result.value) + 1);
235
+ }
236
+
237
+ // String manipulations
238
+ result.category_code = result.category.split('').map(c => c.charCodeAt(0)).join('-');
239
+ result.hash = require('crypto').createHash('md5').update(JSON.stringify(result)).digest('hex').substring(0, 8);
240
+
241
+ // Date calculations
242
+ const date = new Date(result.timestamp);
243
+ result.year = date.getFullYear();
244
+ result.quarter = Math.floor(date.getMonth() / 3) + 1;
245
+ result.day_of_week = date.getDay();
246
+
247
+ return result;
248
+ }
249
+
250
+ // Method 1: Sequential processing
251
+ console.log('Method 1: Sequential processing');
252
+ const sequentialStart = performance.now();
253
+
254
+ const sequentialResults = data.map(row => complexTransformation(row));
255
+
256
+ const sequentialEnd = performance.now();
257
+ console.log(` Time: ${(sequentialEnd - sequentialStart).toFixed(2)}ms`);
258
+ console.log(` Rate: ${(rowCount / ((sequentialEnd - sequentialStart) / 1000)).toFixed(0)} rows/second`);
259
+
260
+ // Method 2: Batch processing with setImmediate (cooperative multitasking)
261
+ console.log('\nMethod 2: Batch processing with cooperative multitasking');
262
+ const batchStart = performance.now();
263
+
264
+ const batchResults = [];
265
+ const batchSize = 1000;
266
+ let batchIndex = 0;
267
+
268
+ function processBatch() {
269
+ const startIdx = batchIndex * batchSize;
270
+ const endIdx = Math.min(startIdx + batchSize, data.length);
271
+
272
+ for (let i = startIdx; i < endIdx; i++) {
273
+ batchResults.push(complexTransformation(data[i]));
274
+ }
275
+
276
+ batchIndex++;
277
+
278
+ if (batchIndex * batchSize < data.length) {
279
+ // Yield to event loop between batches
280
+ setImmediate(processBatch);
281
+ } else {
282
+ const batchEnd = performance.now();
283
+ console.log(` Time: ${(batchEnd - batchStart).toFixed(2)}ms`);
284
+ console.log(` Rate: ${(rowCount / ((batchEnd - batchStart) / 1000)).toFixed(0)} rows/second`);
285
+ console.log(` Batches: ${batchIndex}`);
286
+ }
287
+ }
288
+
289
+ // Start batch processing
290
+ await new Promise(resolve => {
291
+ processBatch();
292
+ // Simple check for completion (in real scenario, use proper signaling)
293
+ const checkInterval = setInterval(() => {
294
+ if (batchResults.length === data.length) {
295
+ clearInterval(checkInterval);
296
+ resolve();
297
+ }
298
+ }, 10);
299
+ });
300
+
301
+ // Method 3: Using jtcsv with transform hooks for parallel-like processing
302
+ console.log('\nMethod 3: jtcsv with optimized transform hooks');
303
+
304
+ // Convert data to CSV for processing
305
+ const csvData = jsonToCsv(data);
306
+
307
+ const transformStart = performance.now();
308
+
309
+ const transformedData = csvToJson(csvData, {
310
+ hasHeaders: true,
311
+ parseNumbers: true,
312
+ hooks: {
313
+ perRow: (row, index) => {
314
+ // Process every 10th row with intensive transformation
315
+ if (index % 10 === 0) {
316
+ return complexTransformation(row);
317
+ }
318
+ // Simple transformation for other rows
319
+ return {
320
+ ...row,
321
+ processed: true,
322
+ index
323
+ };
324
+ }
325
+ }
326
+ });
327
+
328
+ const transformEnd = performance.now();
329
+ console.log(` Time: ${(transformEnd - transformStart).toFixed(2)}ms`);
330
+ console.log(` Rate: ${(rowCount / ((transformEnd - transformStart) / 1000)).toFixed(0)} rows/second`);
331
+ console.log(` Rows processed: ${transformedData.length}`);
332
+ }
333
+
334
+ /**
335
+ * Example 4: Optimized File I/O Patterns
336
+ *
337
+ * Scenario: Efficient reading/writing of large CSV files
338
+ */
339
+ async function exampleOptimizedFileIO() {
340
+ console.log('\n\n=== Example 4: Optimized File I/O Patterns ===\n');
341
+
342
+ const tempDir = './temp_benchmark';
343
+ if (!fs.existsSync(tempDir)) {
344
+ fs.mkdirSync(tempDir, { recursive: true });
345
+ }
346
+
347
+ // Create a test file
348
+ const testFile = `${tempDir}/test_data.csv`;
349
+ const rowCount = 100000;
350
+ const columnCount = 15;
351
+
352
+ console.log(`Creating test file with ${rowCount.toLocaleString()} rows...`);
353
+
354
+ const headers = Array.from({ length: columnCount }, (_, i) => `col${i + 1}`);
355
+ const writeStream = fs.createWriteStream(testFile, { encoding: 'utf8' });
356
+
357
+ writeStream.write(headers.join(',') + '\n');
358
+
359
+ for (let i = 0; i < rowCount; i++) {
360
+ const row = headers.map((_, j) => `value${i}_${j}_${Math.random().toString(36).substring(7)}`);
361
+ if (!writeStream.write(row.join(',') + '\n')) {
362
+ await new Promise(resolve => writeStream.once('drain', resolve));
363
+ }
364
+
365
+ if (i % 10000 === 0 && i > 0) {
366
+ console.log(` Written ${i.toLocaleString()} rows...`);
367
+ }
368
+ }
369
+
370
+ writeStream.end();
371
+ await new Promise(resolve => writeStream.once('close', resolve));
372
+
373
+ const fileSize = fs.statSync(testFile).size;
374
+ console.log(`File created: ${Math.round(fileSize / 1024 / 1024 * 100) / 100} MB`);
375
+
376
+ // Pattern 1: Read entire file into memory
377
+ console.log('\nPattern 1: Read entire file into memory');
378
+ const pattern1Start = performance.now();
379
+ const memoryBefore1 = process.memoryUsage();
380
+
381
+ const fileContent = fs.readFileSync(testFile, 'utf8');
382
+ const data1 = csvToJson(fileContent, { hasHeaders: true });
383
+
384
+ const pattern1End = performance.now();
385
+ const memoryAfter1 = process.memoryUsage();
386
+
387
+ console.log(` Read time: ${(pattern1End - pattern1Start).toFixed(2)}ms`);
388
+ console.log(` Memory used: ${Math.round((memoryAfter1.heapUsed - memoryBefore1.heapUsed) / 1024 / 1024)} MB`);
389
+ console.log(` Rows: ${data1.length}`);
390
+
391
+ // Pattern 2: Streaming with file handle
392
+ console.log('\nPattern 2: Streaming with file handle');
393
+ const pattern2Start = performance.now();
394
+ const memoryBefore2 = process.memoryUsage();
395
+
396
+ const readStream = fs.createReadStream(testFile, {
397
+ encoding: 'utf8',
398
+ highWaterMark: 64 * 1024 // 64KB chunks for optimal disk I/O
399
+ });
400
+
401
+ const csvStream = createCsvToJsonStream({ hasHeaders: true });
402
+ const rowCounts2 = { count: 0 };
403
+
404
+ const countingStream = new (require('stream').Writable)({
405
+ objectMode: true,
406
+ write(row, encoding, callback) {
407
+ rowCounts2.count++;
408
+ callback();
409
+ }
410
+ });
411
+
412
+ await pipeline(readStream, csvStream, countingStream);
413
+
414
+ const pattern2End = performance.now();
415
+ const memoryAfter2 = process.memoryUsage();
416
+
417
+ console.log(` Read time: ${(pattern2End - pattern2Start).toFixed(2)}ms`);
418
+ console.log(` Memory used: ${Math.round((memoryAfter2.heapUsed - memoryBefore2.heapUsed) / 1024 / 1024)} MB`);
419
+ console.log(` Rows: ${rowCounts2.count.toLocaleString()}`);
420
+
421
+ // Pattern 3: Memory-mapped reading (simulated with buffers)
422
+ console.log('\nPattern 3: Memory-mapped reading (simulated)');
423
+ const pattern3Start = performance.now();
424
+ const memoryBefore3 = process.memoryUsage();
425
+
426
+ // Read file in chunks and process incrementally
427
+ const chunkSize = 1024 * 1024; // 1MB chunks
428
+ const fd = fs.openSync(testFile, 'r');
429
+ let position = 0;
430
+ const buffer = Buffer.alloc(chunkSize);
431
+ let leftover = '';
432
+ let rowCount3 = 0;
433
+
434
+ while (true) {
435
+ const bytesRead = fs.readSync(fd, buffer, 0, chunkSize, position);
436
+ if (bytesRead === 0) {
437
+ break;
438
+ }
439
+
440
+ const chunk = leftover + buffer.toString('utf8', 0, bytesRead);
441
+ const lines = chunk.split('\n');
442
+
443
+ // Last line might be incomplete
444
+ leftover = lines.pop() || '';
445
+
446
+ // Count complete lines (excluding header)
447
+ rowCount3 += lines.length > 0 ? lines.length - 1 : 0;
448
+
449
+ position += bytesRead;
450
+ }
451
+
452
+ fs.closeSync(fd);
453
+
454
+ const pattern3End = performance.now();
455
+ const memoryAfter3 = process.memoryUsage();
456
+
457
+ console.log(` Read time: ${(pattern3End - pattern3Start).toFixed(2)}ms`);
458
+ console.log(` Memory used: ${Math.round((memoryAfter3.heapUsed - memoryBefore3.heapUsed) / 1024 / 1024)} MB`);
459
+ console.log(` Rows: ${rowCount3.toLocaleString()}`);
460
+
461
+ // Cleanup
462
+ fs.unlinkSync(testFile);
463
+ fs.rmdirSync(tempDir);
464
+
465
+ console.log('\nSummary:');
466
+ console.log(' Pattern 1 (in-memory): Fastest but highest memory usage');
467
+ console.log(' Pattern 2 (streaming): Good balance of speed and memory');
468
+ console.log(' Pattern 3 (chunked): Lowest memory but more complex');
469
+ }
470
+
471
+ /**
472
+ * Main function to run all examples
473
+ */
474
+ async function main() {
475
+ console.log('='.repeat(80));
476
+ console.log('PERFORMANCE OPTIMIZATION PATTERNS');
477
+ console.log('='.repeat(80));
478
+
479
+ try {
480
+ await exampleDelimiterCaching();
481
+ await exampleMemoryEfficientStreaming();
482
+ await exampleParallelProcessing();
483
+ await exampleOptimizedFileIO();
484
+
485
+ console.log('\n' + '='.repeat(80));
486
+ console.log('ALL OPTIMIZATION EXAMPLES COMPLETED');
487
+ console.log('='.repeat(80));
488
+ } catch (error) {
489
+ console.error('\nError running examples:', error);
490
+ process.exit(1);
491
+ }
492
+ }
493
+
494
+ // Run examples if this file is executed directly
495
+ if (require.main === module) {
496
+ main();
497
+ }
498
+
499
+ module.exports = {
500
+ exampleDelimiterCaching,
501
+ exampleMemoryEfficientStreaming,
502
+ exampleParallelProcessing,
503
+ exampleOptimizedFileIO
504
+ };