jtcsv 2.2.8 → 3.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.
Files changed (246) hide show
  1. package/README.md +204 -115
  2. package/bin/jtcsv.ts +2612 -0
  3. package/browser.d.ts +142 -0
  4. package/dist/benchmark.js +446 -0
  5. package/dist/benchmark.js.map +1 -0
  6. package/dist/bin/jtcsv.js +1940 -0
  7. package/dist/bin/jtcsv.js.map +1 -0
  8. package/dist/csv-to-json.js +1262 -0
  9. package/dist/csv-to-json.js.map +1 -0
  10. package/dist/errors.js +291 -0
  11. package/dist/errors.js.map +1 -0
  12. package/dist/eslint.config.js +147 -0
  13. package/dist/eslint.config.js.map +1 -0
  14. package/dist/index-core.js +95 -0
  15. package/dist/index-core.js.map +1 -0
  16. package/dist/index.js +93 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/json-save.js +229 -0
  19. package/dist/json-save.js.map +1 -0
  20. package/dist/json-to-csv.js +576 -0
  21. package/dist/json-to-csv.js.map +1 -0
  22. package/dist/jtcsv-core.cjs.js +1736 -0
  23. package/dist/jtcsv-core.cjs.js.map +1 -0
  24. package/dist/jtcsv-core.esm.js +1708 -0
  25. package/dist/jtcsv-core.esm.js.map +1 -0
  26. package/dist/jtcsv-core.umd.js +1742 -0
  27. package/dist/jtcsv-core.umd.js.map +1 -0
  28. package/dist/jtcsv-full.cjs.js +2241 -0
  29. package/dist/jtcsv-full.cjs.js.map +1 -0
  30. package/dist/jtcsv-full.esm.js +2209 -0
  31. package/dist/jtcsv-full.esm.js.map +1 -0
  32. package/dist/jtcsv-full.umd.js +2247 -0
  33. package/dist/jtcsv-full.umd.js.map +1 -0
  34. package/dist/jtcsv-workers.esm.js +768 -0
  35. package/dist/jtcsv-workers.esm.js.map +1 -0
  36. package/dist/jtcsv-workers.umd.js +782 -0
  37. package/dist/jtcsv-workers.umd.js.map +1 -0
  38. package/dist/jtcsv.cjs.js +1996 -2048
  39. package/dist/jtcsv.cjs.js.map +1 -1
  40. package/dist/jtcsv.esm.js +1992 -2048
  41. package/dist/jtcsv.esm.js.map +1 -1
  42. package/dist/jtcsv.umd.js +2157 -2209
  43. package/dist/jtcsv.umd.js.map +1 -1
  44. package/dist/plugins/express-middleware/index.js +350 -0
  45. package/dist/plugins/express-middleware/index.js.map +1 -0
  46. package/dist/plugins/fastify-plugin/index.js +315 -0
  47. package/dist/plugins/fastify-plugin/index.js.map +1 -0
  48. package/dist/plugins/hono/index.js +111 -0
  49. package/dist/plugins/hono/index.js.map +1 -0
  50. package/dist/plugins/nestjs/index.js +112 -0
  51. package/dist/plugins/nestjs/index.js.map +1 -0
  52. package/dist/plugins/nuxt/index.js +53 -0
  53. package/dist/plugins/nuxt/index.js.map +1 -0
  54. package/dist/plugins/remix/index.js +133 -0
  55. package/dist/plugins/remix/index.js.map +1 -0
  56. package/dist/plugins/sveltekit/index.js +155 -0
  57. package/dist/plugins/sveltekit/index.js.map +1 -0
  58. package/dist/plugins/trpc/index.js +136 -0
  59. package/dist/plugins/trpc/index.js.map +1 -0
  60. package/dist/run-demo.js +49 -0
  61. package/dist/run-demo.js.map +1 -0
  62. package/dist/src/browser/browser-functions.js +193 -0
  63. package/dist/src/browser/browser-functions.js.map +1 -0
  64. package/dist/src/browser/core.js +123 -0
  65. package/dist/src/browser/core.js.map +1 -0
  66. package/dist/src/browser/csv-to-json-browser.js +353 -0
  67. package/dist/src/browser/csv-to-json-browser.js.map +1 -0
  68. package/dist/src/browser/errors-browser.js +219 -0
  69. package/dist/src/browser/errors-browser.js.map +1 -0
  70. package/dist/src/browser/extensions/plugins.js +106 -0
  71. package/dist/src/browser/extensions/plugins.js.map +1 -0
  72. package/dist/src/browser/extensions/workers.js +66 -0
  73. package/dist/src/browser/extensions/workers.js.map +1 -0
  74. package/dist/src/browser/index.js +140 -0
  75. package/dist/src/browser/index.js.map +1 -0
  76. package/dist/src/browser/json-to-csv-browser.js +225 -0
  77. package/dist/src/browser/json-to-csv-browser.js.map +1 -0
  78. package/dist/src/browser/streams.js +340 -0
  79. package/dist/src/browser/streams.js.map +1 -0
  80. package/dist/src/browser/workers/csv-parser.worker.js +264 -0
  81. package/dist/src/browser/workers/csv-parser.worker.js.map +1 -0
  82. package/dist/src/browser/workers/worker-pool.js +338 -0
  83. package/dist/src/browser/workers/worker-pool.js.map +1 -0
  84. package/dist/src/core/delimiter-cache.js +196 -0
  85. package/dist/src/core/delimiter-cache.js.map +1 -0
  86. package/dist/src/core/node-optimizations.js +279 -0
  87. package/dist/src/core/node-optimizations.js.map +1 -0
  88. package/dist/src/core/plugin-system.js +399 -0
  89. package/dist/src/core/plugin-system.js.map +1 -0
  90. package/dist/src/core/transform-hooks.js +348 -0
  91. package/dist/src/core/transform-hooks.js.map +1 -0
  92. package/dist/src/engines/fast-path-engine-new.js +262 -0
  93. package/dist/src/engines/fast-path-engine-new.js.map +1 -0
  94. package/dist/src/engines/fast-path-engine.js +671 -0
  95. package/dist/src/engines/fast-path-engine.js.map +1 -0
  96. package/dist/src/errors.js +18 -0
  97. package/dist/src/errors.js.map +1 -0
  98. package/dist/src/formats/ndjson-parser.js +332 -0
  99. package/dist/src/formats/ndjson-parser.js.map +1 -0
  100. package/dist/src/formats/tsv-parser.js +230 -0
  101. package/dist/src/formats/tsv-parser.js.map +1 -0
  102. package/dist/src/index-with-plugins.js +259 -0
  103. package/dist/src/index-with-plugins.js.map +1 -0
  104. package/dist/src/types/index.js +3 -0
  105. package/dist/src/types/index.js.map +1 -0
  106. package/dist/src/utils/bom-utils.js +267 -0
  107. package/dist/src/utils/bom-utils.js.map +1 -0
  108. package/dist/src/utils/encoding-support.js +77 -0
  109. package/dist/src/utils/encoding-support.js.map +1 -0
  110. package/dist/src/utils/schema-validator.js +609 -0
  111. package/dist/src/utils/schema-validator.js.map +1 -0
  112. package/dist/src/utils/transform-loader.js +281 -0
  113. package/dist/src/utils/transform-loader.js.map +1 -0
  114. package/dist/src/utils/validators.js +40 -0
  115. package/dist/src/utils/validators.js.map +1 -0
  116. package/dist/src/utils/zod-adapter.js +144 -0
  117. package/dist/src/utils/zod-adapter.js.map +1 -0
  118. package/dist/src/web-server/index.js +648 -0
  119. package/dist/src/web-server/index.js.map +1 -0
  120. package/dist/src/workers/csv-multithreaded.js +211 -0
  121. package/dist/src/workers/csv-multithreaded.js.map +1 -0
  122. package/dist/src/workers/csv-parser.worker.js +179 -0
  123. package/dist/src/workers/csv-parser.worker.js.map +1 -0
  124. package/dist/src/workers/worker-pool.js +228 -0
  125. package/dist/src/workers/worker-pool.js.map +1 -0
  126. package/dist/stream-csv-to-json.js +665 -0
  127. package/dist/stream-csv-to-json.js.map +1 -0
  128. package/dist/stream-json-to-csv.js +389 -0
  129. package/dist/stream-json-to-csv.js.map +1 -0
  130. package/examples/advanced/conditional-transformations.ts +446 -0
  131. package/examples/advanced/csv-parser.worker.ts +89 -0
  132. package/examples/advanced/nested-objects-example.ts +306 -0
  133. package/examples/advanced/performance-optimization.ts +504 -0
  134. package/examples/advanced/run-demo-server.ts +116 -0
  135. package/examples/advanced/web-worker-usage.html +874 -0
  136. package/examples/async-multithreaded-example.ts +335 -0
  137. package/examples/cli-advanced-usage.md +290 -0
  138. package/examples/{cli-batch-processing.js → cli-batch-processing.ts} +38 -38
  139. package/examples/{cli-tool.js → cli-tool.ts} +5 -8
  140. package/examples/{error-handling.js → error-handling.ts} +356 -324
  141. package/examples/{express-api.js → express-api.ts} +161 -164
  142. package/examples/{large-dataset-example.js → large-dataset-example.ts} +201 -182
  143. package/examples/{ndjson-processing.js → ndjson-processing.ts} +456 -434
  144. package/examples/{plugin-excel-exporter.js → plugin-excel-exporter.ts} +6 -7
  145. package/examples/react-integration.tsx +637 -0
  146. package/examples/{schema-validation.js → schema-validation.ts} +2 -2
  147. package/examples/simple-usage.ts +194 -0
  148. package/examples/{streaming-example.js → streaming-example.ts} +12 -12
  149. package/index.d.ts +187 -18
  150. package/package.json +75 -81
  151. package/plugins.d.ts +37 -0
  152. package/schema.d.ts +103 -0
  153. package/src/browser/browser-functions.ts +402 -0
  154. package/src/browser/core.ts +152 -0
  155. package/src/browser/csv-to-json-browser.d.ts +3 -0
  156. package/src/browser/csv-to-json-browser.ts +494 -0
  157. package/src/browser/{errors-browser.js → errors-browser.ts} +305 -197
  158. package/src/browser/extensions/plugins.ts +93 -0
  159. package/src/browser/extensions/workers.ts +39 -0
  160. package/src/browser/globals.d.ts +5 -0
  161. package/src/browser/index.ts +192 -0
  162. package/src/browser/json-to-csv-browser.d.ts +3 -0
  163. package/src/browser/json-to-csv-browser.ts +338 -0
  164. package/src/browser/streams.ts +403 -0
  165. package/src/browser/workers/{csv-parser.worker.js → csv-parser.worker.ts} +3 -3
  166. package/src/browser/workers/{worker-pool.js → worker-pool.ts} +51 -30
  167. package/src/core/delimiter-cache.ts +320 -0
  168. package/src/core/{node-optimizations.js → node-optimizations.ts} +448 -407
  169. package/src/core/plugin-system.ts +588 -0
  170. package/src/core/transform-hooks.ts +566 -0
  171. package/src/engines/{fast-path-engine-new.js → fast-path-engine-new.ts} +11 -2
  172. package/src/engines/{fast-path-engine.js → fast-path-engine.ts} +79 -53
  173. package/src/errors.ts +1 -0
  174. package/src/formats/{ndjson-parser.js → ndjson-parser.ts} +24 -16
  175. package/src/formats/{tsv-parser.js → tsv-parser.ts} +18 -17
  176. package/src/{index-with-plugins.js → index-with-plugins.ts} +381 -357
  177. package/src/types/index.ts +275 -0
  178. package/src/utils/bom-utils.ts +373 -0
  179. package/src/utils/encoding-support.ts +155 -0
  180. package/src/utils/{schema-validator.js → schema-validator.ts} +814 -589
  181. package/src/utils/transform-loader.ts +389 -0
  182. package/src/utils/validators.ts +35 -0
  183. package/src/utils/zod-adapter.ts +280 -0
  184. package/src/web-server/{index.js → index.ts} +19 -19
  185. package/src/workers/csv-multithreaded.ts +310 -0
  186. package/src/workers/csv-parser.worker.ts +227 -0
  187. package/src/workers/worker-pool.ts +409 -0
  188. package/bin/jtcsv.js +0 -2462
  189. package/csv-to-json.js +0 -688
  190. package/errors.js +0 -208
  191. package/examples/simple-usage.js +0 -282
  192. package/index.js +0 -68
  193. package/json-save.js +0 -254
  194. package/json-to-csv.js +0 -526
  195. package/plugins/README.md +0 -91
  196. package/plugins/express-middleware/README.md +0 -64
  197. package/plugins/express-middleware/example.js +0 -136
  198. package/plugins/express-middleware/index.d.ts +0 -114
  199. package/plugins/express-middleware/index.js +0 -360
  200. package/plugins/express-middleware/package.json +0 -52
  201. package/plugins/fastify-plugin/index.js +0 -406
  202. package/plugins/fastify-plugin/package.json +0 -55
  203. package/plugins/hono/README.md +0 -28
  204. package/plugins/hono/index.d.ts +0 -12
  205. package/plugins/hono/index.js +0 -36
  206. package/plugins/hono/package.json +0 -35
  207. package/plugins/nestjs/README.md +0 -35
  208. package/plugins/nestjs/index.d.ts +0 -25
  209. package/plugins/nestjs/index.js +0 -77
  210. package/plugins/nestjs/package.json +0 -37
  211. package/plugins/nextjs-api/README.md +0 -57
  212. package/plugins/nextjs-api/examples/ConverterComponent.jsx +0 -386
  213. package/plugins/nextjs-api/examples/api-convert.js +0 -69
  214. package/plugins/nextjs-api/index.js +0 -387
  215. package/plugins/nextjs-api/package.json +0 -63
  216. package/plugins/nextjs-api/route.js +0 -371
  217. package/plugins/nuxt/README.md +0 -24
  218. package/plugins/nuxt/index.js +0 -21
  219. package/plugins/nuxt/package.json +0 -35
  220. package/plugins/nuxt/runtime/composables/useJtcsv.js +0 -6
  221. package/plugins/nuxt/runtime/plugin.js +0 -6
  222. package/plugins/remix/README.md +0 -26
  223. package/plugins/remix/index.d.ts +0 -16
  224. package/plugins/remix/index.js +0 -62
  225. package/plugins/remix/package.json +0 -35
  226. package/plugins/sveltekit/README.md +0 -28
  227. package/plugins/sveltekit/index.d.ts +0 -17
  228. package/plugins/sveltekit/index.js +0 -54
  229. package/plugins/sveltekit/package.json +0 -33
  230. package/plugins/trpc/README.md +0 -25
  231. package/plugins/trpc/index.d.ts +0 -7
  232. package/plugins/trpc/index.js +0 -32
  233. package/plugins/trpc/package.json +0 -34
  234. package/src/browser/browser-functions.js +0 -219
  235. package/src/browser/csv-to-json-browser.js +0 -700
  236. package/src/browser/index.js +0 -113
  237. package/src/browser/json-to-csv-browser.js +0 -309
  238. package/src/browser/streams.js +0 -393
  239. package/src/core/delimiter-cache.js +0 -186
  240. package/src/core/plugin-system.js +0 -476
  241. package/src/core/transform-hooks.js +0 -350
  242. package/src/errors.js +0 -26
  243. package/src/utils/transform-loader.js +0 -205
  244. package/stream-csv-to-json.js +0 -542
  245. package/stream-json-to-csv.js +0 -464
  246. /package/examples/{web-workers-advanced.js → web-workers-advanced.ts} +0 -0
@@ -1,185 +1,204 @@
1
- // Large dataset example for jtcsv
2
- // Demonstrates handling of large datasets and memory efficiency
3
-
4
- const { jsonToCsv } = require('../index.js');
5
- const fs = require('fs');
6
- const path = require('path');
7
-
8
- // Generate large dataset
9
- function generateLargeDataset(rows) {
10
- console.log(`Generating ${rows.toLocaleString()} records...`);
11
-
12
- const dataset = [];
13
- const batchSize = 10000;
14
- const batches = Math.ceil(rows / batchSize);
15
-
16
- for (let batch = 0; batch < batches; batch++) {
17
- const start = batch * batchSize;
18
- const end = Math.min(start + batchSize, rows);
19
-
20
- for (let i = start; i < end; i++) {
21
- dataset.push({
22
- id: i + 1,
23
- timestamp: new Date(Date.now() - Math.random() * 31536000000).toISOString(),
24
- userId: `user_${Math.floor(Math.random() * 10000)}`,
25
- action: ['login', 'purchase', 'view', 'click', 'logout'][Math.floor(Math.random() * 5)],
26
- amount: Math.random() * 1000,
27
- success: Math.random() > 0.1,
28
- metadata: {
29
- ip: `${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`,
30
- userAgent: `Browser/${Math.floor(Math.random() * 100)}`,
31
- sessionId: `session_${Math.random().toString(36).substr(2, 9)}`
32
- },
33
- tags: Array.from({ length: Math.floor(Math.random() * 5) + 1 },
34
- () => ['tag' + Math.floor(Math.random() * 20), 'cat' + Math.floor(Math.random() * 10)]
35
- ).flat()
36
- });
37
- }
38
-
39
- if ((batch + 1) % 10 === 0 || batch === batches - 1) {
40
- console.log(` Generated ${Math.min((batch + 1) * batchSize, rows).toLocaleString()} records`);
41
- }
42
- }
43
-
44
- return dataset;
45
- }
46
-
47
- // Memory usage helper
48
- function getMemoryUsage() {
49
- const used = process.memoryUsage();
50
- return {
51
- rss: Math.round(used.rss / 1024 / 1024),
52
- heapTotal: Math.round(used.heapTotal / 1024 / 1024),
53
- heapUsed: Math.round(used.heapUsed / 1024 / 1024),
54
- external: Math.round(used.external / 1024 / 1024)
55
- };
56
- }
57
-
58
- // Benchmark conversion
59
- async function benchmarkConversion(dataset, name) {
60
- console.log(`\n${name}:`);
61
- console.log(` Records: ${dataset.length.toLocaleString()}`);
62
-
63
- const memBefore = getMemoryUsage();
64
- console.log(` Memory before: ${memBefore.heapUsed}MB heap`);
65
-
66
- const startTime = performance.now();
67
-
68
- try {
69
- const csv = jsonToCsv(dataset, {
70
- delimiter: ','
71
- });
72
-
73
- const endTime = performance.now();
74
- const memAfter = getMemoryUsage();
75
-
76
- console.log(` Conversion time: ${(endTime - startTime).toFixed(2)}ms`);
77
- console.log(` Memory after: ${memAfter.heapUsed}MB heap`);
78
- console.log(` Memory delta: ${(memAfter.heapUsed - memBefore.heapUsed)}MB`);
79
- console.log(` CSV size: ${(csv.length / 1024 / 1024).toFixed(2)}MB`);
80
- console.log(` Rows/second: ${Math.round((dataset.length / (endTime - startTime)) * 1000).toLocaleString()}`);
81
-
82
- return csv;
83
- } catch (error) {
84
- console.error(` Error: ${error.message}`);
85
- return null;
86
- }
87
- }
88
-
89
- // Save CSV in chunks (for very large files)
90
- function saveCsvInChunks(csv, filename, chunkSize = 10 * 1024 * 1024) { // 10MB chunks
91
- console.log(`\nSaving CSV in chunks to ${filename}...`);
92
-
93
- const totalChunks = Math.ceil(csv.length / chunkSize);
94
- const writeStream = fs.createWriteStream(filename);
95
-
96
- return new Promise((resolve, reject) => {
97
- writeStream.on('error', reject);
98
- writeStream.on('finish', resolve);
99
-
100
- for (let i = 0; i < totalChunks; i++) {
101
- const start = i * chunkSize;
102
- const end = Math.min(start + chunkSize, csv.length);
103
- const chunk = csv.substring(start, end);
104
-
105
- if (!writeStream.write(chunk)) {
106
- // Wait for drain if buffer is full
107
- writeStream.once('drain', () => {
108
- if (i % 10 === 0 || i === totalChunks - 1) {
109
- console.log(` Written chunk ${i + 1}/${totalChunks} (${Math.round((i + 1) / totalChunks * 100)}%)`);
110
- }
111
- });
112
- } else {
113
- if (i % 10 === 0 || i === totalChunks - 1) {
114
- console.log(` Written chunk ${i + 1}/${totalChunks} (${Math.round((i + 1) / totalChunks * 100)}%)`);
115
- }
116
- }
117
- }
118
-
119
- writeStream.end();
120
- });
121
- }
122
-
123
- // Main function
124
- async function main() {
125
- console.log('šŸ“Š jtcsv Large Dataset Demo');
126
- console.log('=' .repeat(50));
127
-
128
- // Test with different dataset sizes
129
- const testSizes = [1000, 10000, 50000];
130
-
131
- for (const size of testSizes) {
132
- const dataset = generateLargeDataset(size);
133
- const csv = await benchmarkConversion(dataset, `Dataset: ${size.toLocaleString()} records`);
134
-
135
- if (csv && size === 50000) {
136
- // Save the largest dataset as example
137
- const filename = `large-dataset-${size}-records.csv`;
138
- await saveCsvInChunks(csv, filename);
139
-
140
- const stats = fs.statSync(filename);
141
- console.log(`\nāœ… Saved to ${filename}`);
142
- console.log(` File size: ${(stats.size / 1024 / 1024).toFixed(2)}MB`);
143
-
144
- // Show first few lines
145
- const sample = csv.split('\n').slice(0, 3).join('\n');
146
- console.log('\nSample output (first 3 lines):');
147
- console.log(sample);
148
- console.log('...');
149
- }
150
-
151
- // Force garbage collection if available
152
- if (global.gc) {
153
- global.gc();
154
- }
155
- }
156
-
157
- console.log('\nšŸŽÆ Performance Summary:');
158
- console.log('| Records | Approx. Time | Memory Usage | CSV Size |');
159
- console.log('|---------|--------------|--------------|----------|');
160
- console.log('| 1,000 | ~5ms | ~2MB | ~0.5MB |');
161
- console.log('| 10,000 | ~50ms | ~10MB | ~5MB |');
162
- console.log('| 50,000 | ~250ms | ~40MB | ~25MB |');
163
- console.log('| 100,000 | ~500ms* | ~80MB* | ~50MB* |');
164
- console.log('\n* Estimated values');
165
-
166
- console.log('\nšŸ’” Tips for very large datasets:');
167
- console.log('1. Use the maxRecords option optionally to limit processing');
168
- console.log('2. Process data in batches if memory is limited');
169
- console.log('3. Use saveAsCsv() for secure file writing');
170
- console.log('4. Monitor memory usage with process.memoryUsage()');
171
- }
172
-
173
- // Run if called directly
174
- if (require.main === module) {
175
- main().catch(console.error);
176
- }
177
-
178
- module.exports = {
179
- generateLargeDataset,
180
- benchmarkConversion,
181
- saveCsvInChunks
182
- };
1
+ // Large dataset example for jtcsv
2
+ // Demonstrates handling of large datasets and memory efficiency
183
3
 
4
+ import { jsonToCsv } from 'jtcsv';
5
+ import fs from 'fs';
6
+ import path from 'path';
184
7
 
8
+ interface DatasetRecord {
9
+ id: number;
10
+ timestamp: string;
11
+ userId: string;
12
+ action: string;
13
+ amount: number;
14
+ success: boolean;
15
+ metadata: {
16
+ ip: string;
17
+ userAgent: string;
18
+ sessionId: string;
19
+ };
20
+ tags: string[];
21
+ }
185
22
 
23
+ interface MemoryUsage {
24
+ rss: number;
25
+ heapTotal: number;
26
+ heapUsed: number;
27
+ external: number;
28
+ }
29
+
30
+ // Generate large dataset
31
+ export function generateLargeDataset(rows: number): DatasetRecord[] {
32
+ console.log(`Generating ${rows.toLocaleString()} records...`);
33
+
34
+ const dataset: DatasetRecord[] = [];
35
+ const batchSize = 10000;
36
+ const batches = Math.ceil(rows / batchSize);
37
+
38
+ for (let batch = 0; batch < batches; batch++) {
39
+ const start = batch * batchSize;
40
+ const end = Math.min(start + batchSize, rows);
41
+
42
+ for (let i = start; i < end; i++) {
43
+ dataset.push({
44
+ id: i + 1,
45
+ timestamp: new Date(Date.now() - Math.random() * 31536000000).toISOString(),
46
+ userId: `user_${Math.floor(Math.random() * 10000)}`,
47
+ action: ['login', 'purchase', 'view', 'click', 'logout'][Math.floor(Math.random() * 5)],
48
+ amount: Math.random() * 1000,
49
+ success: Math.random() > 0.1,
50
+ metadata: {
51
+ ip: `${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`,
52
+ userAgent: `Browser/${Math.floor(Math.random() * 100)}`,
53
+ sessionId: `session_${Math.random().toString(36).substr(2, 9)}`
54
+ },
55
+ tags: Array.from({ length: Math.floor(Math.random() * 5) + 1 },
56
+ () => ['tag' + Math.floor(Math.random() * 20), 'cat' + Math.floor(Math.random() * 10)]
57
+ ).flat()
58
+ });
59
+ }
60
+
61
+ if ((batch + 1) % 10 === 0 || batch === batches - 1) {
62
+ console.log(` Generated ${Math.min((batch + 1) * batchSize, rows).toLocaleString()} records`);
63
+ }
64
+ }
65
+
66
+ return dataset;
67
+ }
68
+
69
+ // Memory usage helper
70
+ export function getMemoryUsage(): MemoryUsage {
71
+ const used = process.memoryUsage();
72
+ return {
73
+ rss: Math.round(used.rss / 1024 / 1024),
74
+ heapTotal: Math.round(used.heapTotal / 1024 / 1024),
75
+ heapUsed: Math.round(used.heapUsed / 1024 / 1024),
76
+ external: Math.round(used.external / 1024 / 1024)
77
+ };
78
+ }
79
+
80
+ // Benchmark conversion
81
+ export async function benchmarkConversion(dataset: DatasetRecord[], name: string): Promise<string | null> {
82
+ console.log(`\n${name}:`);
83
+ console.log(` Records: ${dataset.length.toLocaleString()}`);
84
+
85
+ const memBefore = getMemoryUsage();
86
+ console.log(` Memory before: ${memBefore.heapUsed}MB heap`);
87
+
88
+ const startTime = performance.now();
89
+
90
+ try {
91
+ const csv = jsonToCsv(dataset, {
92
+ delimiter: ','
93
+ });
94
+
95
+ const endTime = performance.now();
96
+ const memAfter = getMemoryUsage();
97
+
98
+ console.log(` Conversion time: ${(endTime - startTime).toFixed(2)}ms`);
99
+ console.log(` Memory after: ${memAfter.heapUsed}MB heap`);
100
+ console.log(` Memory delta: ${(memAfter.heapUsed - memBefore.heapUsed)}MB`);
101
+ console.log(` CSV size: ${(csv.length / 1024 / 1024).toFixed(2)}MB`);
102
+ console.log(` Rows/second: ${Math.round((dataset.length / (endTime - startTime)) * 1000).toLocaleString()}`);
103
+
104
+ return csv;
105
+ } catch (error: unknown) {
106
+ console.error(` Error: ${(error as Error).message}`);
107
+ return null;
108
+ }
109
+ }
110
+
111
+ // Save CSV in chunks (for very large files)
112
+ export function saveCsvInChunks(csv: string, filename: string, chunkSize = 10 * 1024 * 1024): Promise<void> { // 10MB chunks
113
+ console.log(`\nSaving CSV in chunks to ${filename}...`);
114
+
115
+ const totalChunks = Math.ceil(csv.length / chunkSize);
116
+ const writeStream = fs.createWriteStream(filename);
117
+
118
+ return new Promise((resolve, reject) => {
119
+ writeStream.on('error', reject);
120
+ writeStream.on('finish', resolve);
121
+
122
+ for (let i = 0; i < totalChunks; i++) {
123
+ const start = i * chunkSize;
124
+ const end = Math.min(start + chunkSize, csv.length);
125
+ const chunk = csv.substring(start, end);
126
+
127
+ if (!writeStream.write(chunk)) {
128
+ // Wait for drain if buffer is full
129
+ writeStream.once('drain', () => {
130
+ if (i % 10 === 0 || i === totalChunks - 1) {
131
+ console.log(` Written chunk ${i + 1}/${totalChunks} (${Math.round((i + 1) / totalChunks * 100)}%)`);
132
+ }
133
+ });
134
+ } else {
135
+ if (i % 10 === 0 || i === totalChunks - 1) {
136
+ console.log(` Written chunk ${i + 1}/${totalChunks} (${Math.round((i + 1) / totalChunks * 100)}%)`);
137
+ }
138
+ }
139
+ }
140
+
141
+ writeStream.end();
142
+ });
143
+ }
144
+
145
+ // Main function
146
+ export async function main(): Promise<void> {
147
+ console.log('šŸ“Š jtcsv Large Dataset Demo');
148
+ console.log('=' .repeat(50));
149
+
150
+ // Test with different dataset sizes
151
+ const testSizes = [1000, 10000, 50000];
152
+
153
+ for (const size of testSizes) {
154
+ const dataset = generateLargeDataset(size);
155
+ const csv = await benchmarkConversion(dataset, `Dataset: ${size.toLocaleString()} records`);
156
+
157
+ if (csv && size === 50000) {
158
+ // Save the largest dataset as example
159
+ const filename = `large-dataset-${size}-records.csv`;
160
+ await saveCsvInChunks(csv, filename);
161
+
162
+ const stats = fs.statSync(filename);
163
+ console.log(`\nāœ… Saved to ${filename}`);
164
+ console.log(` File size: ${(stats.size / 1024 / 1024).toFixed(2)}MB`);
165
+
166
+ // Show first few lines
167
+ const sample = csv.split('\n').slice(0, 3).join('\n');
168
+ console.log('\nSample output (first 3 lines):');
169
+ console.log(sample);
170
+ console.log('...');
171
+ }
172
+
173
+ // Force garbage collection if available
174
+ if (global.gc) {
175
+ (global.gc as () => void)();
176
+ }
177
+ }
178
+
179
+ console.log('\nšŸŽÆ Performance Summary:');
180
+ console.log('| Records | Approx. Time | Memory Usage | CSV Size |');
181
+ console.log('|---------|--------------|--------------|----------|');
182
+ console.log('| 1,000 | ~5ms | ~2MB | ~0.5MB |');
183
+ console.log('| 10,000 | ~50ms | ~10MB | ~5MB |');
184
+ console.log('| 50,000 | ~250ms | ~40MB | ~25MB |');
185
+ console.log('| 100,000 | ~500ms* | ~80MB* | ~50MB* |');
186
+ console.log('\n* Estimated values');
187
+
188
+ console.log('\nšŸ’” Tips for very large datasets:');
189
+ console.log('1. Use the maxRecords option optionally to limit processing');
190
+ console.log('2. Process data in batches if memory is limited');
191
+ console.log('3. Use saveAsCsv() for secure file writing');
192
+ console.log('4. Monitor memory usage with process.memoryUsage()');
193
+ }
194
+
195
+ // Run if called directly
196
+ if (require.main === module) {
197
+ main().catch(console.error);
198
+ }
199
+
200
+ export default {
201
+ generateLargeDataset,
202
+ benchmarkConversion,
203
+ saveCsvInChunks
204
+ };