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.
- package/README.md +204 -115
- package/bin/jtcsv.ts +2612 -0
- package/browser.d.ts +142 -0
- package/dist/benchmark.js +446 -0
- package/dist/benchmark.js.map +1 -0
- package/dist/bin/jtcsv.js +1940 -0
- package/dist/bin/jtcsv.js.map +1 -0
- package/dist/csv-to-json.js +1262 -0
- package/dist/csv-to-json.js.map +1 -0
- package/dist/errors.js +291 -0
- package/dist/errors.js.map +1 -0
- package/dist/eslint.config.js +147 -0
- package/dist/eslint.config.js.map +1 -0
- package/dist/index-core.js +95 -0
- package/dist/index-core.js.map +1 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/dist/json-save.js +229 -0
- package/dist/json-save.js.map +1 -0
- package/dist/json-to-csv.js +576 -0
- package/dist/json-to-csv.js.map +1 -0
- package/dist/jtcsv-core.cjs.js +1736 -0
- package/dist/jtcsv-core.cjs.js.map +1 -0
- package/dist/jtcsv-core.esm.js +1708 -0
- package/dist/jtcsv-core.esm.js.map +1 -0
- package/dist/jtcsv-core.umd.js +1742 -0
- package/dist/jtcsv-core.umd.js.map +1 -0
- package/dist/jtcsv-full.cjs.js +2241 -0
- package/dist/jtcsv-full.cjs.js.map +1 -0
- package/dist/jtcsv-full.esm.js +2209 -0
- package/dist/jtcsv-full.esm.js.map +1 -0
- package/dist/jtcsv-full.umd.js +2247 -0
- package/dist/jtcsv-full.umd.js.map +1 -0
- package/dist/jtcsv-workers.esm.js +768 -0
- package/dist/jtcsv-workers.esm.js.map +1 -0
- package/dist/jtcsv-workers.umd.js +782 -0
- package/dist/jtcsv-workers.umd.js.map +1 -0
- package/dist/jtcsv.cjs.js +1996 -2048
- package/dist/jtcsv.cjs.js.map +1 -1
- package/dist/jtcsv.esm.js +1992 -2048
- package/dist/jtcsv.esm.js.map +1 -1
- package/dist/jtcsv.umd.js +2157 -2209
- package/dist/jtcsv.umd.js.map +1 -1
- package/dist/plugins/express-middleware/index.js +350 -0
- package/dist/plugins/express-middleware/index.js.map +1 -0
- package/dist/plugins/fastify-plugin/index.js +315 -0
- package/dist/plugins/fastify-plugin/index.js.map +1 -0
- package/dist/plugins/hono/index.js +111 -0
- package/dist/plugins/hono/index.js.map +1 -0
- package/dist/plugins/nestjs/index.js +112 -0
- package/dist/plugins/nestjs/index.js.map +1 -0
- package/dist/plugins/nuxt/index.js +53 -0
- package/dist/plugins/nuxt/index.js.map +1 -0
- package/dist/plugins/remix/index.js +133 -0
- package/dist/plugins/remix/index.js.map +1 -0
- package/dist/plugins/sveltekit/index.js +155 -0
- package/dist/plugins/sveltekit/index.js.map +1 -0
- package/dist/plugins/trpc/index.js +136 -0
- package/dist/plugins/trpc/index.js.map +1 -0
- package/dist/run-demo.js +49 -0
- package/dist/run-demo.js.map +1 -0
- package/dist/src/browser/browser-functions.js +193 -0
- package/dist/src/browser/browser-functions.js.map +1 -0
- package/dist/src/browser/core.js +123 -0
- package/dist/src/browser/core.js.map +1 -0
- package/dist/src/browser/csv-to-json-browser.js +353 -0
- package/dist/src/browser/csv-to-json-browser.js.map +1 -0
- package/dist/src/browser/errors-browser.js +219 -0
- package/dist/src/browser/errors-browser.js.map +1 -0
- package/dist/src/browser/extensions/plugins.js +106 -0
- package/dist/src/browser/extensions/plugins.js.map +1 -0
- package/dist/src/browser/extensions/workers.js +66 -0
- package/dist/src/browser/extensions/workers.js.map +1 -0
- package/dist/src/browser/index.js +140 -0
- package/dist/src/browser/index.js.map +1 -0
- package/dist/src/browser/json-to-csv-browser.js +225 -0
- package/dist/src/browser/json-to-csv-browser.js.map +1 -0
- package/dist/src/browser/streams.js +340 -0
- package/dist/src/browser/streams.js.map +1 -0
- package/dist/src/browser/workers/csv-parser.worker.js +264 -0
- package/dist/src/browser/workers/csv-parser.worker.js.map +1 -0
- package/dist/src/browser/workers/worker-pool.js +338 -0
- package/dist/src/browser/workers/worker-pool.js.map +1 -0
- package/dist/src/core/delimiter-cache.js +196 -0
- package/dist/src/core/delimiter-cache.js.map +1 -0
- package/dist/src/core/node-optimizations.js +279 -0
- package/dist/src/core/node-optimizations.js.map +1 -0
- package/dist/src/core/plugin-system.js +399 -0
- package/dist/src/core/plugin-system.js.map +1 -0
- package/dist/src/core/transform-hooks.js +348 -0
- package/dist/src/core/transform-hooks.js.map +1 -0
- package/dist/src/engines/fast-path-engine-new.js +262 -0
- package/dist/src/engines/fast-path-engine-new.js.map +1 -0
- package/dist/src/engines/fast-path-engine.js +671 -0
- package/dist/src/engines/fast-path-engine.js.map +1 -0
- package/dist/src/errors.js +18 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/formats/ndjson-parser.js +332 -0
- package/dist/src/formats/ndjson-parser.js.map +1 -0
- package/dist/src/formats/tsv-parser.js +230 -0
- package/dist/src/formats/tsv-parser.js.map +1 -0
- package/dist/src/index-with-plugins.js +259 -0
- package/dist/src/index-with-plugins.js.map +1 -0
- package/dist/src/types/index.js +3 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/utils/bom-utils.js +267 -0
- package/dist/src/utils/bom-utils.js.map +1 -0
- package/dist/src/utils/encoding-support.js +77 -0
- package/dist/src/utils/encoding-support.js.map +1 -0
- package/dist/src/utils/schema-validator.js +609 -0
- package/dist/src/utils/schema-validator.js.map +1 -0
- package/dist/src/utils/transform-loader.js +281 -0
- package/dist/src/utils/transform-loader.js.map +1 -0
- package/dist/src/utils/validators.js +40 -0
- package/dist/src/utils/validators.js.map +1 -0
- package/dist/src/utils/zod-adapter.js +144 -0
- package/dist/src/utils/zod-adapter.js.map +1 -0
- package/dist/src/web-server/index.js +648 -0
- package/dist/src/web-server/index.js.map +1 -0
- package/dist/src/workers/csv-multithreaded.js +211 -0
- package/dist/src/workers/csv-multithreaded.js.map +1 -0
- package/dist/src/workers/csv-parser.worker.js +179 -0
- package/dist/src/workers/csv-parser.worker.js.map +1 -0
- package/dist/src/workers/worker-pool.js +228 -0
- package/dist/src/workers/worker-pool.js.map +1 -0
- package/dist/stream-csv-to-json.js +665 -0
- package/dist/stream-csv-to-json.js.map +1 -0
- package/dist/stream-json-to-csv.js +389 -0
- package/dist/stream-json-to-csv.js.map +1 -0
- package/examples/advanced/conditional-transformations.ts +446 -0
- package/examples/advanced/csv-parser.worker.ts +89 -0
- package/examples/advanced/nested-objects-example.ts +306 -0
- package/examples/advanced/performance-optimization.ts +504 -0
- package/examples/advanced/run-demo-server.ts +116 -0
- package/examples/advanced/web-worker-usage.html +874 -0
- package/examples/async-multithreaded-example.ts +335 -0
- package/examples/cli-advanced-usage.md +290 -0
- package/examples/{cli-batch-processing.js ā cli-batch-processing.ts} +38 -38
- package/examples/{cli-tool.js ā cli-tool.ts} +5 -8
- package/examples/{error-handling.js ā error-handling.ts} +356 -324
- package/examples/{express-api.js ā express-api.ts} +161 -164
- package/examples/{large-dataset-example.js ā large-dataset-example.ts} +201 -182
- package/examples/{ndjson-processing.js ā ndjson-processing.ts} +456 -434
- package/examples/{plugin-excel-exporter.js ā plugin-excel-exporter.ts} +6 -7
- package/examples/react-integration.tsx +637 -0
- package/examples/{schema-validation.js ā schema-validation.ts} +2 -2
- package/examples/simple-usage.ts +194 -0
- package/examples/{streaming-example.js ā streaming-example.ts} +12 -12
- package/index.d.ts +187 -18
- package/package.json +75 -81
- package/plugins.d.ts +37 -0
- package/schema.d.ts +103 -0
- package/src/browser/browser-functions.ts +402 -0
- package/src/browser/core.ts +152 -0
- package/src/browser/csv-to-json-browser.d.ts +3 -0
- package/src/browser/csv-to-json-browser.ts +494 -0
- package/src/browser/{errors-browser.js ā errors-browser.ts} +305 -197
- package/src/browser/extensions/plugins.ts +93 -0
- package/src/browser/extensions/workers.ts +39 -0
- package/src/browser/globals.d.ts +5 -0
- package/src/browser/index.ts +192 -0
- package/src/browser/json-to-csv-browser.d.ts +3 -0
- package/src/browser/json-to-csv-browser.ts +338 -0
- package/src/browser/streams.ts +403 -0
- package/src/browser/workers/{csv-parser.worker.js ā csv-parser.worker.ts} +3 -3
- package/src/browser/workers/{worker-pool.js ā worker-pool.ts} +51 -30
- package/src/core/delimiter-cache.ts +320 -0
- package/src/core/{node-optimizations.js ā node-optimizations.ts} +448 -407
- package/src/core/plugin-system.ts +588 -0
- package/src/core/transform-hooks.ts +566 -0
- package/src/engines/{fast-path-engine-new.js ā fast-path-engine-new.ts} +11 -2
- package/src/engines/{fast-path-engine.js ā fast-path-engine.ts} +79 -53
- package/src/errors.ts +1 -0
- package/src/formats/{ndjson-parser.js ā ndjson-parser.ts} +24 -16
- package/src/formats/{tsv-parser.js ā tsv-parser.ts} +18 -17
- package/src/{index-with-plugins.js ā index-with-plugins.ts} +381 -357
- package/src/types/index.ts +275 -0
- package/src/utils/bom-utils.ts +373 -0
- package/src/utils/encoding-support.ts +155 -0
- package/src/utils/{schema-validator.js ā schema-validator.ts} +814 -589
- package/src/utils/transform-loader.ts +389 -0
- package/src/utils/validators.ts +35 -0
- package/src/utils/zod-adapter.ts +280 -0
- package/src/web-server/{index.js ā index.ts} +19 -19
- package/src/workers/csv-multithreaded.ts +310 -0
- package/src/workers/csv-parser.worker.ts +227 -0
- package/src/workers/worker-pool.ts +409 -0
- package/bin/jtcsv.js +0 -2462
- package/csv-to-json.js +0 -688
- package/errors.js +0 -208
- package/examples/simple-usage.js +0 -282
- package/index.js +0 -68
- package/json-save.js +0 -254
- package/json-to-csv.js +0 -526
- package/plugins/README.md +0 -91
- package/plugins/express-middleware/README.md +0 -64
- package/plugins/express-middleware/example.js +0 -136
- package/plugins/express-middleware/index.d.ts +0 -114
- package/plugins/express-middleware/index.js +0 -360
- package/plugins/express-middleware/package.json +0 -52
- package/plugins/fastify-plugin/index.js +0 -406
- package/plugins/fastify-plugin/package.json +0 -55
- package/plugins/hono/README.md +0 -28
- package/plugins/hono/index.d.ts +0 -12
- package/plugins/hono/index.js +0 -36
- package/plugins/hono/package.json +0 -35
- package/plugins/nestjs/README.md +0 -35
- package/plugins/nestjs/index.d.ts +0 -25
- package/plugins/nestjs/index.js +0 -77
- package/plugins/nestjs/package.json +0 -37
- package/plugins/nextjs-api/README.md +0 -57
- package/plugins/nextjs-api/examples/ConverterComponent.jsx +0 -386
- package/plugins/nextjs-api/examples/api-convert.js +0 -69
- package/plugins/nextjs-api/index.js +0 -387
- package/plugins/nextjs-api/package.json +0 -63
- package/plugins/nextjs-api/route.js +0 -371
- package/plugins/nuxt/README.md +0 -24
- package/plugins/nuxt/index.js +0 -21
- package/plugins/nuxt/package.json +0 -35
- package/plugins/nuxt/runtime/composables/useJtcsv.js +0 -6
- package/plugins/nuxt/runtime/plugin.js +0 -6
- package/plugins/remix/README.md +0 -26
- package/plugins/remix/index.d.ts +0 -16
- package/plugins/remix/index.js +0 -62
- package/plugins/remix/package.json +0 -35
- package/plugins/sveltekit/README.md +0 -28
- package/plugins/sveltekit/index.d.ts +0 -17
- package/plugins/sveltekit/index.js +0 -54
- package/plugins/sveltekit/package.json +0 -33
- package/plugins/trpc/README.md +0 -25
- package/plugins/trpc/index.d.ts +0 -7
- package/plugins/trpc/index.js +0 -32
- package/plugins/trpc/package.json +0 -34
- package/src/browser/browser-functions.js +0 -219
- package/src/browser/csv-to-json-browser.js +0 -700
- package/src/browser/index.js +0 -113
- package/src/browser/json-to-csv-browser.js +0 -309
- package/src/browser/streams.js +0 -393
- package/src/core/delimiter-cache.js +0 -186
- package/src/core/plugin-system.js +0 -476
- package/src/core/transform-hooks.js +0 -350
- package/src/errors.js +0 -26
- package/src/utils/transform-loader.js +0 -205
- package/stream-csv-to-json.js +0 -542
- package/stream-json-to-csv.js +0 -464
- /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
|
+
};
|