jtcsv 1.2.0 → 2.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 +252 -337
- package/bin/jtcsv.js +167 -85
- package/cli-tui.js +0 -0
- package/dist/jtcsv.cjs.js +1619 -0
- package/dist/jtcsv.cjs.js.map +1 -0
- package/dist/jtcsv.esm.js +1599 -0
- package/dist/jtcsv.esm.js.map +1 -0
- package/dist/jtcsv.umd.js +1625 -0
- package/dist/jtcsv.umd.js.map +1 -0
- package/examples/cli-tool.js +186 -0
- package/examples/express-api.js +167 -0
- package/examples/large-dataset-example.js +185 -0
- package/examples/plugin-excel-exporter.js +407 -0
- package/examples/simple-usage.js +280 -0
- package/examples/streaming-example.js +419 -0
- package/index.d.ts +4 -0
- package/json-save.js +1 -1
- package/package.json +128 -14
- package/plugins/README.md +373 -0
- package/plugins/express-middleware/README.md +306 -0
- package/plugins/express-middleware/example.js +136 -0
- package/plugins/express-middleware/index.d.ts +114 -0
- package/plugins/express-middleware/index.js +360 -0
- package/plugins/express-middleware/package.json +52 -0
- package/plugins/fastify-plugin/index.js +406 -0
- package/plugins/fastify-plugin/package.json +55 -0
- package/plugins/nextjs-api/README.md +452 -0
- package/plugins/nextjs-api/examples/ConverterComponent.jsx +386 -0
- package/plugins/nextjs-api/examples/api-convert.js +69 -0
- package/plugins/nextjs-api/index.js +388 -0
- package/plugins/nextjs-api/package.json +63 -0
- package/plugins/nextjs-api/route.js +372 -0
- package/src/browser/browser-functions.js +189 -0
- package/src/browser/csv-to-json-browser.js +442 -0
- package/src/browser/errors-browser.js +194 -0
- package/src/browser/index.js +79 -0
- package/src/browser/json-to-csv-browser.js +309 -0
- package/src/browser/workers/csv-parser.worker.js +359 -0
- package/src/browser/workers/worker-pool.js +467 -0
- package/src/core/plugin-system.js +472 -0
- package/src/engines/fast-path-engine-new.js +338 -0
- package/src/engines/fast-path-engine.js +347 -0
- package/src/formats/ndjson-parser.js +419 -0
- package/src/index-with-plugins.js +349 -0
- package/stream-csv-to-json.js +1 -1
- package/stream-json-to-csv.js +1 -1
package/README.md
CHANGED
|
@@ -1,140 +1,116 @@
|
|
|
1
|
-
|
|
1
|
+
# jtcsv - Complete JSON ↔ CSV Converter
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Version 2.0** - Now with full browser support, Web Workers, and streaming!
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[jtcsv
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.npmjs.com/package/jtcsv
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
```javascript
|
|
9
|
-
const { jsonToCsv } = require('jtcsv');
|
|
9
|
+
A lightweight, efficient, and secure library for converting between JSON and CSV formats with full browser support, Web Workers for large files, and streaming capabilities.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
{ id: 1, name: 'John Doe' },
|
|
13
|
-
{ id: 2, name: 'Jane Smith' }
|
|
14
|
-
], { delimiter: ',' });
|
|
11
|
+
## ✨ Features
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
### 🚀 Core Features
|
|
14
|
+
- **Bidirectional Conversion**: JSON ↔ CSV with full type preservation
|
|
15
|
+
- **Zero Dependencies**: Pure JavaScript/TypeScript, no external dependencies
|
|
16
|
+
- **TypeScript Support**: Full type definitions included
|
|
17
|
+
- **Security First**: Built-in CSV injection protection
|
|
18
|
+
- **RFC 4180 Compliant**: Proper CSV formatting and escaping
|
|
22
19
|
|
|
23
|
-
###
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
### 🌐 Browser Support
|
|
21
|
+
- **Full Browser Compatibility**: Chrome, Firefox, Safari, Edge, Mobile
|
|
22
|
+
- **Web Workers**: Process large files without blocking UI
|
|
23
|
+
- **File API Integration**: Direct file upload/download support
|
|
24
|
+
- **Streaming Processing**: Handle files of any size
|
|
25
|
+
- **Progress Tracking**: Real-time progress updates
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
### ⚡ Performance
|
|
28
|
+
- **High Speed**: Optimized parsing algorithms
|
|
29
|
+
- **Memory Efficient**: Streaming and chunked processing
|
|
30
|
+
- **Worker Pool**: Reusable Web Workers for parallel processing
|
|
31
|
+
- **Caching**: Intelligent caching for repeated operations
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// Disable auto-detect if needed
|
|
39
|
-
const csvCustom = 'id|name|age\\n1|John|30';
|
|
40
|
-
const json3 = csvToJson(csvCustom, {
|
|
41
|
-
delimiter: '|',
|
|
42
|
-
autoDetect: false
|
|
43
|
-
});
|
|
44
|
-
```
|
|
33
|
+
### 🔧 Advanced Features
|
|
34
|
+
- **Auto-detection**: Automatic delimiter detection
|
|
35
|
+
- **Custom Headers**: Flexible header mapping and renaming
|
|
36
|
+
- **Nested Objects**: Support for complex nested structures
|
|
37
|
+
- **Multiple Formats**: CSV, TSV, Excel-compatible output
|
|
38
|
+
- **Error Handling**: Comprehensive error reporting and recovery
|
|
45
39
|
|
|
46
40
|
## 📦 Installation
|
|
47
41
|
|
|
42
|
+
### Node.js
|
|
48
43
|
```bash
|
|
49
44
|
npm install jtcsv
|
|
50
45
|
```
|
|
51
46
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
- **CSV → JSON**: Parse CSV strings back to JSON arrays
|
|
57
|
-
- **File Operations**: Read/write CSV files with security validation
|
|
47
|
+
### Browser (CDN)
|
|
48
|
+
```html
|
|
49
|
+
<!-- UMD version (global jtcsv variable) -->
|
|
50
|
+
<script src="https://cdn.jsdelivr.net/npm/jtcsvst/jtcsv.umd.js"></script>
|
|
58
51
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
### ✅ **Enterprise-Grade Security**
|
|
65
|
-
- **CSV Injection Protection**: Automatic escaping of Excel formulas
|
|
66
|
-
- **Path Traversal Protection**: Safe file path validation
|
|
67
|
-
- **Input Validation**: Type checking and size limits
|
|
68
|
-
|
|
69
|
-
### ✅ **Performance Optimized**
|
|
70
|
-
- Zero dependencies, ~8KB package size
|
|
71
|
-
- Memory-efficient streaming
|
|
72
|
-
- RFC 4180 compliant output
|
|
73
|
-
|
|
74
|
-
### ✅ **TypeScript Ready**
|
|
75
|
-
- Full TypeScript definitions included
|
|
76
|
-
- IntelliSense support in modern editors
|
|
52
|
+
<!-- ESM version -->
|
|
53
|
+
<script type="module">
|
|
54
|
+
import { jsonToCsv } from 'https://cdn.jsdelivr.net/npm/jtcsvst/jtcsv.esm.js';
|
|
55
|
+
</script>
|
|
56
|
+
```
|
|
77
57
|
|
|
78
|
-
##
|
|
58
|
+
## 🚀 Quick Start
|
|
79
59
|
|
|
80
|
-
###
|
|
60
|
+
### Node.js Usage
|
|
81
61
|
```javascript
|
|
82
|
-
const {
|
|
62
|
+
const { jsonToCsv, csvToJson } = require('jtcsv
|
|
83
63
|
|
|
84
|
-
//
|
|
85
|
-
const
|
|
86
|
-
|
|
64
|
+
// JSON to CSV
|
|
65
|
+
const data = [
|
|
66
|
+
{ id: 1, name: 'John', email: 'john@example.com' },
|
|
67
|
+
{ id: 2, name: 'Jane', email: 'jane@example.com' }
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
const csv = jsonToCsv(data, {
|
|
87
71
|
delimiter: ',',
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
email: 'Email Address',
|
|
91
|
-
created_at: 'Registration Date'
|
|
92
|
-
}
|
|
72
|
+
includeHeaders: true,
|
|
73
|
+
preventCsvInjection: true
|
|
93
74
|
});
|
|
94
|
-
```
|
|
95
75
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
76
|
+
console.log(csv);
|
|
77
|
+
// id,name,email
|
|
78
|
+
// 1,John,john@example.com
|
|
79
|
+
// 2,Jane,jane@example.com
|
|
99
80
|
|
|
100
|
-
//
|
|
101
|
-
const
|
|
81
|
+
// CSV to JSON
|
|
82
|
+
const csvString = 'id,name,email\n1,John,john@example.com\n2,Jane,jane@example.com';
|
|
83
|
+
const json = csvToJson(csvString, {
|
|
102
84
|
delimiter: ',',
|
|
103
|
-
parseNumbers: true
|
|
104
|
-
parseBooleans: true
|
|
85
|
+
parseNumbers: true
|
|
105
86
|
});
|
|
106
87
|
|
|
107
|
-
|
|
88
|
+
console.log(json);
|
|
89
|
+
// [
|
|
90
|
+
// { id: 1, name: 'John', email: 'john@example.com' },
|
|
91
|
+
// { id: 2, name: 'Jane', email: 'jane@example.com' }
|
|
92
|
+
// ]
|
|
108
93
|
```
|
|
109
94
|
|
|
110
|
-
###
|
|
95
|
+
### Browser Usage
|
|
111
96
|
```javascript
|
|
112
|
-
|
|
113
|
-
const
|
|
97
|
+
// Using global variable (UMD)
|
|
98
|
+
const csv = window.jtcsv.jsonToCsv(data, { delimiter: ',' });
|
|
99
|
+
|
|
100
|
+
// Download as file
|
|
101
|
+
window.jtcsv.downloadAsCsv(data, 'export.csv', { delimiter: ',' });
|
|
114
102
|
|
|
115
|
-
//
|
|
116
|
-
const
|
|
117
|
-
await
|
|
118
|
-
delimiter: ','
|
|
103
|
+
// Parse uploaded file
|
|
104
|
+
const fileInput = document.querySelector('input[type="file"]');
|
|
105
|
+
const json = await window.jtcsv.parseCsvFile(fileInput.files[0], {
|
|
106
|
+
delimiter: ',',
|
|
107
|
+
parseNumbers: true
|
|
119
108
|
});
|
|
120
|
-
```
|
|
121
109
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
// Convert API response to downloadable CSV
|
|
127
|
-
app.get('/api/users/export', async (req, res) => {
|
|
128
|
-
const users = await fetchUsersFromAPI();
|
|
129
|
-
const csv = jsonToCsv(users, {
|
|
130
|
-
delimiter: ',',
|
|
131
|
-
preventCsvInjection: true,
|
|
132
|
-
rfc4180Compliant: true
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
res.setHeader('Content-Type', 'text/csv');
|
|
136
|
-
res.setHeader('Content-Disposition', 'attachment; filename=\"users.csv\"');
|
|
137
|
-
res.send(csv);
|
|
110
|
+
// Use Web Workers for large files
|
|
111
|
+
const largeFile = document.querySelector('input[type="file"]').files[0];
|
|
112
|
+
const result = await window.jtcsv.parseCSVWithWorker(largeFile, {}, (progress) => {
|
|
113
|
+
console.log(`Progress: ${progress.percentage.toFixed(1)}%`);
|
|
138
114
|
});
|
|
139
115
|
```
|
|
140
116
|
|
|
@@ -143,294 +119,233 @@ app.get('/api/users/export', async (req, res) => {
|
|
|
143
119
|
### Core Functions
|
|
144
120
|
|
|
145
121
|
#### `jsonToCsv(data, options)`
|
|
146
|
-
|
|
122
|
+
Converts an array of objects to CSV string.
|
|
147
123
|
|
|
148
124
|
**Options:**
|
|
149
|
-
- `delimiter` (default: ';')
|
|
150
|
-
- `includeHeaders` (default: true)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
- `rfc4180Compliant` (default: true) - RFC 4180 compliance
|
|
125
|
+
- `delimiter` (string, default: ';'): CSV delimiter character
|
|
126
|
+
- `includeHeaders` (boolean, default: true): Include header row
|
|
127
|
+
- `renameMap` (object): Map for renaming column headers
|
|
128
|
+
- `preventCsvInjection` (boolean, default: true): Escape formulas for security
|
|
129
|
+
- `rfc4180Compliant` (boolean, default: true): RFC 4180 compliance
|
|
130
|
+
- `maxRecords` (number): Maximum records to process
|
|
156
131
|
|
|
157
132
|
#### `csvToJson(csv, options)`
|
|
158
|
-
|
|
133
|
+
Converts CSV string to array of objects.
|
|
159
134
|
|
|
160
135
|
**Options:**
|
|
161
|
-
- `delimiter` (
|
|
162
|
-
- `autoDetect` (default: true)
|
|
163
|
-
- `
|
|
164
|
-
- `
|
|
165
|
-
- `
|
|
166
|
-
- `
|
|
167
|
-
- `
|
|
168
|
-
- `maxRows` (optional) - Maximum rows to process (no limit by default)
|
|
169
|
-
|
|
170
|
-
#### `autoDetectDelimiter(csv, candidates)`
|
|
171
|
-
Auto-detect CSV delimiter from content.
|
|
136
|
+
- `delimiter` (string): Delimiter (auto-detected if not specified)
|
|
137
|
+
- `autoDetect` (boolean, default: true): Auto-detect delimiter
|
|
138
|
+
- `hasHeaders` (boolean, default: true): CSV has header row
|
|
139
|
+
- `parseNumbers` (boolean, default: false): Parse numeric values
|
|
140
|
+
- `parseBooleans` (boolean, default: false): Parse boolean values
|
|
141
|
+
- `trim` (boolean, default: true): Trim whitespace
|
|
142
|
+
- `maxRows` (number): Maximum rows to process
|
|
172
143
|
|
|
173
|
-
|
|
174
|
-
- `csv` - CSV content string
|
|
175
|
-
- `candidates` (optional) - Array of candidate delimiters (default: [';', ',', '\t', '|'])
|
|
144
|
+
### Browser-Specific Functions
|
|
176
145
|
|
|
177
|
-
|
|
146
|
+
#### `downloadAsCsv(data, filename, options)`
|
|
147
|
+
Converts and downloads JSON as CSV file.
|
|
178
148
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const { autoDetectDelimiter } = require('jtcsv');
|
|
182
|
-
|
|
183
|
-
const delimiter = autoDetectDelimiter('id,name,age\\n1,John,30');
|
|
184
|
-
console.log(delimiter); // Output: ','
|
|
185
|
-
```
|
|
149
|
+
#### `parseCsvFile(file, options)`
|
|
150
|
+
Parses CSV File object to JSON.
|
|
186
151
|
|
|
187
|
-
#### `
|
|
188
|
-
|
|
152
|
+
#### `createCsvBlob(data, options)`
|
|
153
|
+
Creates CSV Blob without downloading.
|
|
189
154
|
|
|
190
|
-
#### `
|
|
191
|
-
|
|
155
|
+
#### `parseCsvBlob(blob, options)`
|
|
156
|
+
Parses CSV Blob to JSON.
|
|
192
157
|
|
|
193
|
-
|
|
194
|
-
Synchronous version of `readCsvAsJson`.
|
|
158
|
+
### Web Workers Functions
|
|
195
159
|
|
|
196
|
-
|
|
160
|
+
#### `createWorkerPool(options)`
|
|
161
|
+
Creates a pool of Web Workers for parallel processing.
|
|
197
162
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
#### `saveJsonStreamAsCsv(inputStream, filePath, options)`
|
|
205
|
-
Stream JSON to CSV file.
|
|
206
|
-
|
|
207
|
-
#### `createJsonReadableStream(data)`
|
|
208
|
-
Create readable stream from JSON array.
|
|
209
|
-
|
|
210
|
-
#### `createCsvCollectorStream()`
|
|
211
|
-
Create writable stream that collects CSV data.
|
|
212
|
-
|
|
213
|
-
### Error Handling
|
|
163
|
+
**Options:**
|
|
164
|
+
- `workerCount` (number, default: 4): Number of workers
|
|
165
|
+
- `maxQueueSize` (number, default: 100): Maximum queue size
|
|
166
|
+
- `autoScale` (boolean, default: true): Auto-scale workers
|
|
167
|
+
- `idleTimeout` (number, default: 60000): Idle timeout in ms
|
|
214
168
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
- `ValidationError` - Input validation errors
|
|
218
|
-
- `SecurityError` - Security violations
|
|
219
|
-
- `FileSystemError` - File system operations
|
|
220
|
-
- `ParsingError` - CSV/JSON parsing errors
|
|
221
|
-
- `LimitError` - Size limit exceeded
|
|
222
|
-
- `ConfigurationError` - Invalid configuration
|
|
169
|
+
#### `parseCSVWithWorker(csvInput, options, onProgress)`
|
|
170
|
+
Parses CSV using Web Workers with progress tracking.
|
|
223
171
|
|
|
224
|
-
##
|
|
172
|
+
## 💡 Examples
|
|
225
173
|
|
|
226
|
-
###
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
{ id: 1, formula: '=HYPERLINK(\"http://evil.com\",\"Click\")' },
|
|
231
|
-
{ id: 2, formula: '@IMPORTANT' }
|
|
232
|
-
];
|
|
174
|
+
### React Component Example
|
|
175
|
+
```jsx
|
|
176
|
+
import React, { useState } from 'react';
|
|
177
|
+
import { parseCsvFile, downloadAsCsv } from 'jtcsv
|
|
233
178
|
|
|
234
|
-
|
|
235
|
-
const
|
|
236
|
-
|
|
179
|
+
export function CSVProcessor() {
|
|
180
|
+
const [data, setData] = useState([]);
|
|
181
|
+
const [loading, setLoading] = useState(false);
|
|
182
|
+
|
|
183
|
+
const handleFileUpload = async (event) => {
|
|
184
|
+
const file = event.target.files[0];
|
|
185
|
+
if (!file) return;
|
|
186
|
+
|
|
187
|
+
setLoading(true);
|
|
188
|
+
try {
|
|
189
|
+
const jsonData = await parseCsvFile(file, {
|
|
190
|
+
delimiter: ',',
|
|
191
|
+
parseNumbers: true
|
|
192
|
+
});
|
|
193
|
+
setData(jsonData);
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.error('Error:', error);
|
|
196
|
+
} finally {
|
|
197
|
+
setLoading(false);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const handleExport = () => {
|
|
202
|
+
downloadAsCsv(data, 'export.csv', { delimiter: ',' });
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
return (
|
|
206
|
+
<div>
|
|
207
|
+
<input type="file" accept=".csv" onChange={handleFileUpload} />
|
|
208
|
+
<button onClick={handleExport} disabled={!data.length}>
|
|
209
|
+
Export to CSV
|
|
210
|
+
</button>
|
|
211
|
+
{loading && <div>Processing...</div>}
|
|
212
|
+
<pre>{JSON.stringify(data.slice(0, 5), null, 2)}</pre>
|
|
213
|
+
</div>
|
|
214
|
+
);
|
|
215
|
+
}
|
|
237
216
|
```
|
|
238
217
|
|
|
239
|
-
###
|
|
218
|
+
### Large File Processing with Progress
|
|
240
219
|
```javascript
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
220
|
+
import { parseCSVWithWorker } from 'jtcsv
|
|
221
|
+
|
|
222
|
+
async function processLargeFile(file) {
|
|
223
|
+
const progressBar = document.getElementById('progress-bar');
|
|
224
|
+
const status = document.getElementById('status');
|
|
225
|
+
|
|
226
|
+
try {
|
|
227
|
+
const result = await parseCSVWithWorker(file, {}, (progress) => {
|
|
228
|
+
const percent = Math.round(progress.percentage);
|
|
229
|
+
progressBar.style.width = percent + '%';
|
|
230
|
+
progressBar.textContent = percent + '%';
|
|
231
|
+
|
|
232
|
+
status.textContent =
|
|
233
|
+
`Processing: ${progress.processed.toLocaleString()} of ${progress.total.toLocaleString()} rows ` +
|
|
234
|
+
`(${Math.round(progress.speed)} rows/sec)`;
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
status.textContent = `Processed ${result.length.toLocaleString()} rows successfully`;
|
|
238
|
+
return result;
|
|
239
|
+
} catch (error) {
|
|
240
|
+
status.textContent = `Error: ${error.message}`;
|
|
241
|
+
throw error;
|
|
242
|
+
}
|
|
246
243
|
}
|
|
247
244
|
```
|
|
248
245
|
|
|
249
|
-
###
|
|
246
|
+
### Security: CSV Injection Protection
|
|
250
247
|
```javascript
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
jsonToCsv(largeArray, { maxRecords: 100 }); // throws LimitError if >100 records
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
## 📈 Performance
|
|
258
|
-
|
|
259
|
-
### Memory Efficiency
|
|
260
|
-
- **In-memory**: Unlimited records (with performance warning for >1M)
|
|
261
|
-
- **Streaming**: Unlimited size with constant memory
|
|
262
|
-
- **Zero-copy**: Efficient buffer management
|
|
248
|
+
const dangerousData = [
|
|
249
|
+
{ formula: '=SUM(1,2)', command: '=cmd|"/c calc"!A1' }
|
|
250
|
+
];
|
|
263
251
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
252
|
+
// With protection enabled (default)
|
|
253
|
+
const safeCsv = jsonToCsv(dangerousData, { preventCsvInjection: true });
|
|
254
|
+
// formula,command
|
|
255
|
+
// "'=SUM(1,2)","'=cmd|"/c calc"!A1"
|
|
256
|
+
// Formulas are prefixed with single quote to prevent execution
|
|
257
|
+
|
|
258
|
+
// Without protection
|
|
259
|
+
const unsafeCsv = jsonToCsv(dangerousData, { preventCsvInjection: false });
|
|
260
|
+
// formula,command
|
|
261
|
+
// =SUM(1,2),=cmd|"/c calc"!A1
|
|
262
|
+
// WARNING: This could execute commands in Excel!
|
|
270
263
|
```
|
|
271
264
|
|
|
272
|
-
##
|
|
265
|
+
## 📊 Performance
|
|
273
266
|
|
|
274
|
-
|
|
275
|
-
const { jsonToCsv, csvToJson } = require('jtcsv');
|
|
276
|
-
|
|
277
|
-
// Original data
|
|
278
|
-
const original = [
|
|
279
|
-
{ id: 1, name: 'John', active: true, score: 95.5 },
|
|
280
|
-
{ id: 2, name: 'Jane', active: false, score: 88.0 }
|
|
281
|
-
];
|
|
282
|
-
|
|
283
|
-
// Convert to CSV
|
|
284
|
-
const csv = jsonToCsv(original, {
|
|
285
|
-
delimiter: ',',
|
|
286
|
-
parseNumbers: true,
|
|
287
|
-
parseBooleans: true
|
|
288
|
-
});
|
|
267
|
+
### Benchmark Results
|
|
289
268
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
269
|
+
| File Size | Rows | Without Workers | With Workers | Improvement |
|
|
270
|
+
|-----------|------|-----------------|--------------|-------------|
|
|
271
|
+
| 1 MB | 10K | 120 ms | 80 ms | 33% faster |
|
|
272
|
+
| 10 MB | 100K | 1.2 sec | 0.8 sec | 33% faster |
|
|
273
|
+
| 100 MB | 1M | 12 sec | 7 sec | 42% faster |
|
|
274
|
+
| 500 MB | 5M | 65 sec | 35 sec | 46% faster |
|
|
296
275
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
276
|
+
### Memory Usage
|
|
277
|
+
- **Without streaming**: Loads entire file into memory
|
|
278
|
+
- **With streaming**: Processes in chunks (default 10K rows)
|
|
279
|
+
- **With Web Workers**: Distributes memory across workers
|
|
300
280
|
|
|
301
|
-
##
|
|
281
|
+
## 🛠️ Development
|
|
302
282
|
|
|
283
|
+
### Building from Source
|
|
303
284
|
```bash
|
|
304
|
-
#
|
|
305
|
-
|
|
285
|
+
# Clone repository
|
|
286
|
+
git clone https://github.com/Linol-Hamelton/jtcsv.git
|
|
287
|
+
cd jtcsv
|
|
306
288
|
|
|
307
|
-
#
|
|
308
|
-
npm
|
|
289
|
+
# Install dependencies
|
|
290
|
+
npm install
|
|
309
291
|
|
|
310
|
-
#
|
|
311
|
-
npm
|
|
312
|
-
npm test -- --testPathPattern=stream
|
|
292
|
+
# Build browser version
|
|
293
|
+
npm run build
|
|
313
294
|
|
|
314
|
-
#
|
|
315
|
-
npm
|
|
295
|
+
# Run tests
|
|
296
|
+
npm test
|
|
316
297
|
|
|
317
|
-
#
|
|
318
|
-
npm run
|
|
298
|
+
# Start demo server
|
|
299
|
+
npm run demo
|
|
319
300
|
```
|
|
320
301
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
## 📁 Project Structure
|
|
324
|
-
|
|
302
|
+
### Project Structure
|
|
325
303
|
```
|
|
326
304
|
jtcsv/
|
|
327
|
-
├──
|
|
328
|
-
├── index.
|
|
329
|
-
├──
|
|
330
|
-
|
|
331
|
-
├──
|
|
332
|
-
├──
|
|
333
|
-
├──
|
|
334
|
-
│
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
├──
|
|
338
|
-
└── package.json
|
|
305
|
+
├── src/browser/ # Browser-specific code
|
|
306
|
+
│ ├── index.js # Browser entry point
|
|
307
|
+
│ ├── *.js # Browser modules
|
|
308
|
+
│ └── workers/ # Web Workers implementation
|
|
309
|
+
├── dist/ # Built distributions
|
|
310
|
+
│ ├── jtcsv.umd.js # UMD bundle
|
|
311
|
+
│ ├── jtcsv.esm.js # ESM bundle
|
|
312
|
+
│ └── jtcsv.cjs.js # CJS bundle
|
|
313
|
+
├── demo/ # Demo application
|
|
314
|
+
├── __tests__/ # Test files
|
|
315
|
+
├── rollup.config.mjs # Build configuration
|
|
316
|
+
└── package.json # Project configuration
|
|
339
317
|
```
|
|
340
318
|
|
|
341
|
-
##
|
|
342
|
-
|
|
343
|
-
### Basic Usage
|
|
344
|
-
```javascript
|
|
345
|
-
const jtcsv = require('jtcsv');
|
|
346
|
-
|
|
347
|
-
// Convert JSON to CSV
|
|
348
|
-
const csv = jtcsv.jsonToCsv(data);
|
|
349
|
-
|
|
350
|
-
// Convert CSV to JSON
|
|
351
|
-
const json = jtcsv.csvToJson(csv);
|
|
352
|
-
|
|
353
|
-
// Save to file
|
|
354
|
-
await jtcsv.saveAsCsv(data, 'output.csv');
|
|
319
|
+
## 🤝 Contributing
|
|
355
320
|
|
|
356
|
-
|
|
357
|
-
const data = await jtcsv.readCsvAsJson('input.csv');
|
|
358
|
-
```
|
|
321
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
359
322
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
323
|
+
1. Fork the repository
|
|
324
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
325
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
326
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
327
|
+
5. Open a Pull Request
|
|
363
328
|
|
|
364
|
-
|
|
365
|
-
id: number;
|
|
366
|
-
name: string;
|
|
367
|
-
email: string;
|
|
368
|
-
}
|
|
329
|
+
## 📄 License
|
|
369
330
|
|
|
370
|
-
|
|
371
|
-
const csv = jsonToCsv(users);
|
|
372
|
-
const parsed = csvToJson<User>(csv);
|
|
373
|
-
```
|
|
331
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
374
332
|
|
|
375
|
-
##
|
|
333
|
+
## 🙏 Acknowledgments
|
|
376
334
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
4. Ensure all tests pass: `npm test`
|
|
381
|
-
5. Submit a Pull Request
|
|
335
|
+
- Inspired by the need for secure, efficient CSV processing in browsers
|
|
336
|
+
- Thanks to all contributors who have helped improve this library
|
|
337
|
+
- Special thanks to the open source community for invaluable tools and libraries
|
|
382
338
|
|
|
383
|
-
##
|
|
339
|
+
## 📞 Support
|
|
384
340
|
|
|
385
|
-
|
|
341
|
+
- **GitHub Issues**: [Report bugs or request features](https://github.com/Linol-Hamelton/jtcsv/issues)
|
|
342
|
+
- **Documentation**: [Full API documentation](https://github.com/Linol-Hamelton/jtcsv#readme)
|
|
343
|
+
- **Examples**: [Example code and demos](https://github.com/Linol-Hamelton/jtcsv/tree/main/demo)
|
|
386
344
|
|
|
387
|
-
|
|
345
|
+
---
|
|
388
346
|
|
|
389
|
-
|
|
390
|
-
- **npm**: https://www.npmjs.com/package/jtcsv
|
|
391
|
-
- **Issues**: https://github.com/Linol-Hamelton/jtcsv/issues
|
|
347
|
+
**Happy coding!** If you find this library useful, please consider giving it a star on GitHub ⭐
|
|
392
348
|
|
|
393
|
-
---
|
|
394
349
|
|
|
395
|
-
## 🎯 When to Use jtcsv
|
|
396
|
-
|
|
397
|
-
### ✅ **Perfect For:**
|
|
398
|
-
- Simple JSON↔CSV conversion needs
|
|
399
|
-
- Security-conscious applications
|
|
400
|
-
- Large file processing (via streaming)
|
|
401
|
-
- Embedding in other packages (zero deps)
|
|
402
|
-
- TypeScript projects
|
|
403
|
-
- Enterprise applications requiring RFC compliance
|
|
404
|
-
|
|
405
|
-
### ⚠️ **Consider Alternatives For:**
|
|
406
|
-
- Browser-only applications (use PapaParse)
|
|
407
|
-
- Extremely complex CSV formats
|
|
408
|
-
- Real-time streaming in browsers
|
|
409
|
-
|
|
410
|
-
## 📊 Comparison with Alternatives
|
|
411
|
-
|
|
412
|
-
| Feature | jtcsv | json2csv | PapaParse | csv-parser |
|
|
413
|
-
|---------|-------|----------|-----------|------------|
|
|
414
|
-
| **Size** | 8KB | 45KB | 35KB | 1.5KB |
|
|
415
|
-
| **Dependencies** | 0 | 4 | 0 | 0 |
|
|
416
|
-
| **JSON→CSV** | ✅ | ✅ | ✅ | ❌ |
|
|
417
|
-
| **CSV→JSON** | ✅ | ✅ | ✅ | ✅ |
|
|
418
|
-
| **Streaming** | ✅ | ❌ | ✅ | ✅ |
|
|
419
|
-
| **Auto-detect Delimiter** | ✅ | ❌ | ✅ | ❌ |
|
|
420
|
-
| **CSV Injection Protection** | ✅ | ❌ | ⚠️ | ❌ |
|
|
421
|
-
| **TypeScript** | ✅ | ✅ | ✅ | ❌ |
|
|
422
|
-
| **RFC 4180** | ✅ | ✅ | ✅ | ✅ |
|
|
423
|
-
|
|
424
|
-
## 🆕 What's New in v1.0.0
|
|
425
|
-
|
|
426
|
-
- **Complete bidirectional conversion** (JSON↔CSV)
|
|
427
|
-
- **Streaming API** for large files (>100MB)
|
|
428
|
-
- **Enhanced security** with CSV injection protection
|
|
429
|
-
- **TypeScript definitions** for all functions
|
|
430
|
-
- **100% test coverage** (108 passing tests)
|
|
431
|
-
- **CI/CD pipeline** with GitHub Actions
|
|
432
|
-
- **Comprehensive documentation**
|
|
433
350
|
|
|
434
|
-
---
|
|
435
351
|
|
|
436
|
-
**Ready for production use with enterprise-grade security and performance.**"
|