jtcsv 2.1.1 → 2.1.5
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 +64 -327
- package/bin/jtcsv.js +7 -24
- package/csv-to-json.js +35 -26
- package/dist/jtcsv.cjs.js +807 -133
- package/dist/jtcsv.cjs.js.map +1 -1
- package/dist/jtcsv.esm.js +800 -134
- package/dist/jtcsv.esm.js.map +1 -1
- package/dist/jtcsv.umd.js +807 -133
- package/dist/jtcsv.umd.js.map +1 -1
- package/errors.js +20 -0
- package/examples/browser-vanilla.html +37 -0
- package/examples/cli-batch-processing.js +38 -0
- package/examples/simple-usage.js +12 -10
- package/examples/web-workers-advanced.js +28 -0
- package/json-save.js +2 -1
- package/package.json +41 -21
- package/plugins/README.md +50 -332
- package/plugins/express-middleware/README.md +32 -274
- package/plugins/hono/README.md +28 -0
- package/plugins/hono/index.d.ts +12 -0
- package/plugins/hono/index.js +36 -0
- package/plugins/hono/package.json +35 -0
- package/plugins/nestjs/README.md +35 -0
- package/plugins/nestjs/index.d.ts +25 -0
- package/plugins/nestjs/index.js +77 -0
- package/plugins/nestjs/package.json +37 -0
- package/plugins/nextjs-api/README.md +28 -423
- package/plugins/nextjs-api/index.js +1 -2
- package/plugins/nextjs-api/route.js +1 -2
- package/plugins/nuxt/README.md +24 -0
- package/plugins/nuxt/index.js +21 -0
- package/plugins/nuxt/package.json +35 -0
- package/plugins/nuxt/runtime/composables/useJtcsv.js +6 -0
- package/plugins/nuxt/runtime/plugin.js +6 -0
- package/plugins/remix/README.md +26 -0
- package/plugins/remix/index.d.ts +16 -0
- package/plugins/remix/index.js +62 -0
- package/plugins/remix/package.json +35 -0
- package/plugins/sveltekit/README.md +28 -0
- package/plugins/sveltekit/index.d.ts +17 -0
- package/plugins/sveltekit/index.js +54 -0
- package/plugins/sveltekit/package.json +33 -0
- package/plugins/trpc/README.md +25 -0
- package/plugins/trpc/index.d.ts +7 -0
- package/plugins/trpc/index.js +32 -0
- package/plugins/trpc/package.json +34 -0
- package/src/browser/browser-functions.js +33 -3
- package/src/browser/csv-to-json-browser.js +269 -11
- package/src/browser/errors-browser.js +19 -1
- package/src/browser/index.js +39 -5
- package/src/browser/streams.js +393 -0
- package/src/browser/workers/csv-parser.worker.js +20 -2
- package/src/browser/workers/worker-pool.js +507 -447
- package/src/core/plugin-system.js +4 -0
- package/src/engines/fast-path-engine.js +31 -23
- package/src/formats/ndjson-parser.js +54 -5
- package/src/formats/tsv-parser.js +4 -1
- package/stream-csv-to-json.js +11 -2
- package/stream-json-to-csv.js +13 -1
- package/cli-tui.js +0 -1498
package/README.md
CHANGED
|
@@ -1,154 +1,48 @@
|
|
|
1
|
-
# jtcsv -
|
|
1
|
+
# jtcsv - JSON <-> CSV toolkit for Node.js and browser
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
[jtcsv
|
|
3
|
+
[](https://www.npmjs.com/package/jtcsv)
|
|
6
4
|
[](https://opensource.org/licenses/MIT)
|
|
7
|
-
[](https://www.npmjs.com/package/jtcsv)
|
|
26
6
|
|
|
27
|
-
|
|
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
|
|
7
|
+
Fast JSON <-> CSV conversion with streaming helpers, NDJSON/TSV support, and optional integrations.
|
|
32
8
|
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
9
|
+
## Features
|
|
10
|
+
- JSON <-> CSV conversion with security defaults
|
|
11
|
+
- Streaming helpers and async iterator API
|
|
12
|
+
- NDJSON and TSV helpers
|
|
13
|
+
- Browser bundle with Web Worker helpers
|
|
14
|
+
- Optional plugin system and framework adapters
|
|
15
|
+
- CLI and optional TUI
|
|
39
16
|
|
|
40
|
-
##
|
|
41
|
-
|
|
42
|
-
### Node.js
|
|
17
|
+
## Installation
|
|
43
18
|
```bash
|
|
44
19
|
npm install jtcsv
|
|
45
20
|
```
|
|
46
21
|
|
|
47
|
-
###
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
<!-- ESM version -->
|
|
53
|
-
<script type="module">
|
|
54
|
-
import { jsonToCsv } from 'https://cdn.jsdelivr.net/npm/jtcsvst/jtcsv.esm.js';
|
|
55
|
-
</script>
|
|
22
|
+
### Optional add-ons
|
|
23
|
+
```bash
|
|
24
|
+
npm install @jtcsv/tui
|
|
25
|
+
npm install @jtcsv/excel exceljs
|
|
26
|
+
npm install @jtcsv/validator
|
|
56
27
|
```
|
|
57
28
|
|
|
58
|
-
##
|
|
59
|
-
|
|
60
|
-
### Node.js Usage
|
|
29
|
+
## Quick start (Node.js)
|
|
61
30
|
```javascript
|
|
62
|
-
const { jsonToCsv, csvToJson } = require('jtcsv
|
|
31
|
+
const { jsonToCsv, csvToJson } = require('jtcsv');
|
|
63
32
|
|
|
64
|
-
// JSON to CSV
|
|
65
33
|
const data = [
|
|
66
34
|
{ id: 1, name: 'John', email: 'john@example.com' },
|
|
67
35
|
{ id: 2, name: 'Jane', email: 'jane@example.com' }
|
|
68
36
|
];
|
|
69
37
|
|
|
70
|
-
const csv = jsonToCsv(data, {
|
|
71
|
-
|
|
72
|
-
includeHeaders: true,
|
|
73
|
-
preventCsvInjection: true
|
|
74
|
-
});
|
|
38
|
+
const csv = jsonToCsv(data, { delimiter: ',', includeHeaders: true });
|
|
39
|
+
const json = csvToJson(csv, { delimiter: ',', parseNumbers: true });
|
|
75
40
|
|
|
76
41
|
console.log(csv);
|
|
77
|
-
// id,name,email
|
|
78
|
-
// 1,John,john@example.com
|
|
79
|
-
// 2,Jane,jane@example.com
|
|
80
|
-
|
|
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, {
|
|
84
|
-
delimiter: ',',
|
|
85
|
-
parseNumbers: true
|
|
86
|
-
});
|
|
87
|
-
|
|
88
42
|
console.log(json);
|
|
89
|
-
// [
|
|
90
|
-
// { id: 1, name: 'John', email: 'john@example.com' },
|
|
91
|
-
// { id: 2, name: 'Jane', email: 'jane@example.com' }
|
|
92
|
-
// ]
|
|
93
43
|
```
|
|
94
44
|
|
|
95
|
-
###
|
|
96
|
-
```javascript
|
|
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: ',' });
|
|
102
|
-
|
|
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
|
|
108
|
-
});
|
|
109
|
-
|
|
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)}%`);
|
|
114
|
-
});
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
## 🔧 API Reference
|
|
118
|
-
|
|
119
|
-
### Core Functions
|
|
120
|
-
|
|
121
|
-
#### `jsonToCsv(data, options)`
|
|
122
|
-
Converts an array of objects to CSV string.
|
|
123
|
-
|
|
124
|
-
**Options:**
|
|
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
|
|
131
|
-
|
|
132
|
-
#### `csvToJson(csv, options)`
|
|
133
|
-
Converts CSV string to array of objects.
|
|
134
|
-
|
|
135
|
-
**Options:**
|
|
136
|
-
Fast path parsing is the default pipeline; use `fastPathMode` to control row shape.
|
|
137
|
-
- `delimiter` (string): Delimiter (auto-detected if not specified)
|
|
138
|
-
- `autoDetect` (boolean, default: true): Auto-detect delimiter
|
|
139
|
-
- `hasHeaders` (boolean, default: true): CSV has header row
|
|
140
|
-
- `parseNumbers` (boolean, default: false): Parse numeric values
|
|
141
|
-
- `parseBooleans` (boolean, default: false): Parse boolean values
|
|
142
|
-
- `trim` (boolean, default: true): Trim whitespace
|
|
143
|
-
- `maxRows` (number): Maximum rows to process
|
|
144
|
-
- `useFastPath` (boolean, default: true): Enable fast-path parser (set `false` to force quote-aware path)
|
|
145
|
-
- `fastPathMode` (string, default: 'objects'): `'objects'` for object rows, `'compact'` for arrays (lower memory), `'stream'` to return an async iterator
|
|
146
|
-
|
|
147
|
-
#### `csvToJsonIterator(csv, options)`
|
|
148
|
-
Convert CSV to JSON rows as an async iterator for large inputs.
|
|
149
|
-
You can also call `csvToJson(csv, { fastPathMode: 'stream' })` to get the same async iterator.
|
|
150
|
-
|
|
151
|
-
**Example:**
|
|
45
|
+
### Async iterator
|
|
152
46
|
```javascript
|
|
153
47
|
const { csvToJsonIterator } = require('jtcsv');
|
|
154
48
|
|
|
@@ -158,222 +52,65 @@ for await (const row of csvToJsonIterator(csv, { fastPathMode: 'compact' })) {
|
|
|
158
52
|
}
|
|
159
53
|
```
|
|
160
54
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
#### `parseCsvFile(file, options)`
|
|
167
|
-
Parses CSV File object to JSON.
|
|
168
|
-
|
|
169
|
-
#### `createCsvBlob(data, options)`
|
|
170
|
-
Creates CSV Blob without downloading.
|
|
55
|
+
## Browser usage
|
|
56
|
+
- Bundler: `import { csvToJson, jsonToCsv } from 'jtcsv/browser';`
|
|
57
|
+
- CDN UMD: `https://cdn.jsdelivr.net/npm/jtcsv/dist/jtcsv.umd.js`
|
|
58
|
+
- CDN ESM: `https://cdn.jsdelivr.net/npm/jtcsv/dist/jtcsv.esm.js`
|
|
171
59
|
|
|
172
|
-
|
|
173
|
-
Parses CSV Blob to JSON.
|
|
60
|
+
See `README-browser.md` for full browser API and worker helpers.
|
|
174
61
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
62
|
+
## CLI
|
|
63
|
+
```bash
|
|
64
|
+
npx jtcsv csv-to-json input.csv output.json
|
|
65
|
+
npx jtcsv json-to-csv input.json output.csv
|
|
66
|
+
npx jtcsv stream csv-to-json big.csv output.json
|
|
67
|
+
npx jtcsv batch json-to-csv "data/*.json" output/
|
|
179
68
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
- `autoScale` (boolean, default: true): Auto-scale workers
|
|
184
|
-
- `idleTimeout` (number, default: 60000): Idle timeout in ms
|
|
69
|
+
# optional TUI
|
|
70
|
+
npx jtcsv tui
|
|
71
|
+
```
|
|
185
72
|
|
|
186
|
-
|
|
187
|
-
Parses CSV using Web Workers with progress tracking.
|
|
73
|
+
See `CLI.md` for full command list and options.
|
|
188
74
|
|
|
189
|
-
##
|
|
75
|
+
## Demos
|
|
76
|
+
Run these from the repo root:
|
|
77
|
+
```bash
|
|
78
|
+
# Express API demo
|
|
79
|
+
npm run demo
|
|
190
80
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
import React, { useState } from 'react';
|
|
194
|
-
import { parseCsvFile, downloadAsCsv } from 'jtcsv
|
|
81
|
+
# Web demo (Vite dev server on http://localhost:3000)
|
|
82
|
+
npm run demo:web
|
|
195
83
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const [loading, setLoading] = useState(false);
|
|
199
|
-
|
|
200
|
-
const handleFileUpload = async (event) => {
|
|
201
|
-
const file = event.target.files[0];
|
|
202
|
-
if (!file) return;
|
|
203
|
-
|
|
204
|
-
setLoading(true);
|
|
205
|
-
try {
|
|
206
|
-
const jsonData = await parseCsvFile(file, {
|
|
207
|
-
delimiter: ',',
|
|
208
|
-
parseNumbers: true
|
|
209
|
-
});
|
|
210
|
-
setData(jsonData);
|
|
211
|
-
} catch (error) {
|
|
212
|
-
console.error('Error:', error);
|
|
213
|
-
} finally {
|
|
214
|
-
setLoading(false);
|
|
215
|
-
}
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
const handleExport = () => {
|
|
219
|
-
downloadAsCsv(data, 'export.csv', { delimiter: ',' });
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
return (
|
|
223
|
-
<div>
|
|
224
|
-
<input type="file" accept=".csv" onChange={handleFileUpload} />
|
|
225
|
-
<button onClick={handleExport} disabled={!data.length}>
|
|
226
|
-
Export to CSV
|
|
227
|
-
</button>
|
|
228
|
-
{loading && <div>Processing...</div>}
|
|
229
|
-
<pre>{JSON.stringify(data.slice(0, 5), null, 2)}</pre>
|
|
230
|
-
</div>
|
|
231
|
-
);
|
|
232
|
-
}
|
|
84
|
+
# Preview built demo
|
|
85
|
+
npm run demo:serve
|
|
233
86
|
```
|
|
234
87
|
|
|
235
|
-
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
const progressBar = document.getElementById('progress-bar');
|
|
241
|
-
const status = document.getElementById('status');
|
|
242
|
-
|
|
243
|
-
try {
|
|
244
|
-
const result = await parseCSVWithWorker(file, {}, (progress) => {
|
|
245
|
-
const percent = Math.round(progress.percentage);
|
|
246
|
-
progressBar.style.width = percent + '%';
|
|
247
|
-
progressBar.textContent = percent + '%';
|
|
248
|
-
|
|
249
|
-
status.textContent =
|
|
250
|
-
`Processing: ${progress.processed.toLocaleString()} of ${progress.total.toLocaleString()} rows ` +
|
|
251
|
-
`(${Math.round(progress.speed)} rows/sec)`;
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
status.textContent = `Processed ${result.length.toLocaleString()} rows successfully`;
|
|
255
|
-
return result;
|
|
256
|
-
} catch (error) {
|
|
257
|
-
status.textContent = `Error: ${error.message}`;
|
|
258
|
-
throw error;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
88
|
+
From inside `demo/` use:
|
|
89
|
+
```bash
|
|
90
|
+
npm run dev
|
|
91
|
+
npm run preview
|
|
92
|
+
npm run serve
|
|
261
93
|
```
|
|
262
94
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
const dangerousData = [
|
|
266
|
-
{ formula: '=SUM(1,2)', command: '=cmd|"/c calc"!A1' }
|
|
267
|
-
];
|
|
95
|
+
## Plugin system
|
|
96
|
+
The plugin-enabled API is exported from `jtcsv/plugins`.
|
|
268
97
|
|
|
269
|
-
|
|
270
|
-
const
|
|
271
|
-
// formula,command
|
|
272
|
-
// "'=SUM(1,2)","'=cmd|"/c calc"!A1"
|
|
273
|
-
// Formulas are prefixed with single quote to prevent execution
|
|
98
|
+
```javascript
|
|
99
|
+
const { create } = require('jtcsv/plugins');
|
|
274
100
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
// formula,command
|
|
278
|
-
// =SUM(1,2),=cmd|"/c calc"!A1
|
|
279
|
-
// WARNING: This could execute commands in Excel!
|
|
101
|
+
const jtcsv = create();
|
|
102
|
+
jtcsv.use('my-plugin', { name: 'My Plugin', version: '1.0.0' });
|
|
280
103
|
```
|
|
281
104
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
### Benchmark Results (Node.js 22, 10K rows/records)
|
|
285
|
-
|
|
286
|
-
**CSV → JSON (10K rows)**
|
|
287
|
-
|
|
288
|
-
| Library | Time | Memory | Rank |
|
|
289
|
-
|---------|------|--------|------|
|
|
290
|
-
| **JTCSV (FastPath Compact)** | 16.79 ms | 4.47 MB | 🥇 1st |
|
|
291
|
-
| **JTCSV (FastPath Stream)** | 18.27 ms | 6.03 MB | 🥈 2nd |
|
|
292
|
-
| **JTCSV** | 19.76 ms | 8.96 MB | 🥉 3rd |
|
|
293
|
-
| PapaParse | 21.57 ms | 6.97 MB | 4th |
|
|
294
|
-
| csv-parser | 30.52 ms | 6.53 MB | 5th |
|
|
295
|
-
|
|
296
|
-
**JSON → CSV (10K records)**
|
|
105
|
+
See `README-PLUGINS.md` and `plugins/README.md` for integrations.
|
|
297
106
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
| **JTCSV** | 11.21 ms | 4.77 MB | 🥇 1st |
|
|
301
|
-
| json2csv | 12.27 ms | 12.11 MB | 🥈 2nd |
|
|
302
|
-
|
|
303
|
-
### Scaling (JTCSV only)
|
|
304
|
-
|
|
305
|
-
| Rows/Records | CSV→JSON Time (FastPath Compact) | JSON→CSV Time (JTCSV) | CSV→JSON Memory | JSON→CSV Memory |
|
|
306
|
-
|--------------|----------------------------------|-----------------------|-----------------|-----------------|
|
|
307
|
-
| 1,000 | 2.06 ms | 1.04 ms | 2.15 MB | 0.52 MB |
|
|
308
|
-
| 10,000 | 14.68 ms | 8.23 ms | 2.11 MB | 4.14 MB |
|
|
309
|
-
| 100,000 | 164.18 ms | 90.93 ms | 44.93 MB | 34.79 MB |
|
|
310
|
-
|
|
311
|
-
See `BENCHMARK-RESULTS.md` and `docs/PERFORMANCE.md` for environment details and methodology.
|
|
312
|
-
|
|
313
|
-
## 🛠️ Development
|
|
314
|
-
|
|
315
|
-
### Building from Source
|
|
107
|
+
## Development
|
|
108
|
+
Run from the repo root:
|
|
316
109
|
```bash
|
|
317
|
-
# Clone repository
|
|
318
|
-
git clone https://github.com/Linol-Hamelton/jtcsv.git
|
|
319
|
-
cd jtcsv
|
|
320
|
-
|
|
321
|
-
# Install dependencies
|
|
322
|
-
npm install
|
|
323
|
-
|
|
324
|
-
# Build browser version
|
|
325
|
-
npm run build
|
|
326
|
-
|
|
327
|
-
# Run tests
|
|
328
110
|
npm test
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
npm run demo
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
### Project Structure
|
|
335
|
-
```
|
|
336
|
-
jtcsv/
|
|
337
|
-
├── src/browser/ # Browser-specific code
|
|
338
|
-
│ ├── index.js # Browser entry point
|
|
339
|
-
│ ├── *.js # Browser modules
|
|
340
|
-
│ └── workers/ # Web Workers implementation
|
|
341
|
-
├── dist/ # Built distributions
|
|
342
|
-
│ ├── jtcsv.umd.js # UMD bundle
|
|
343
|
-
│ ├── jtcsv.esm.js # ESM bundle
|
|
344
|
-
│ └── jtcsv.cjs.js # CJS bundle
|
|
345
|
-
├── demo/ # Demo application
|
|
346
|
-
├── __tests__/ # Test files
|
|
347
|
-
├── rollup.config.mjs # Build configuration
|
|
348
|
-
└── package.json # Project configuration
|
|
111
|
+
npm run test:coverage
|
|
112
|
+
npm run build
|
|
349
113
|
```
|
|
350
114
|
|
|
351
|
-
##
|
|
352
|
-
|
|
353
|
-
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
354
|
-
|
|
355
|
-
1. Fork the repository
|
|
356
|
-
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
357
|
-
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
358
|
-
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
359
|
-
5. Open a Pull Request
|
|
360
|
-
|
|
361
|
-
## 📄 License
|
|
362
|
-
|
|
363
|
-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
364
|
-
|
|
365
|
-
## 🙏 Acknowledgments
|
|
366
|
-
|
|
367
|
-
- Inspired by the need for secure, efficient CSV processing in browsers
|
|
368
|
-
- Thanks to all contributors who have helped improve this library
|
|
369
|
-
- Special thanks to the open source community for invaluable tools and libraries
|
|
370
|
-
|
|
371
|
-
## 📞 Support
|
|
372
|
-
|
|
373
|
-
- **GitHub Issues**: [Report bugs or request features](https://github.com/Linol-Hamelton/jtcsv/issues)
|
|
374
|
-
- **Documentation**: [Full API documentation](https://github.com/Linol-Hamelton/jtcsv#readme)
|
|
375
|
-
- **Examples**: [Example code and demos](https://github.com/Linol-Hamelton/jtcsv/tree/main/demo)
|
|
376
|
-
|
|
377
|
-
---
|
|
378
|
-
|
|
379
|
-
**Happy coding!** If you find this library useful, please consider giving it a star on GitHub ⭐
|
|
115
|
+
## License
|
|
116
|
+
MIT. See `LICENSE`.
|
package/bin/jtcsv.js
CHANGED
|
@@ -47,7 +47,7 @@ ${color('MAIN COMMANDS:', 'bright')}
|
|
|
47
47
|
${color('stream', 'yellow')} Streaming conversion for large files
|
|
48
48
|
${color('batch', 'yellow')} Batch process multiple files
|
|
49
49
|
${color('preprocess', 'magenta')} Preprocess JSON with deep unwrapping
|
|
50
|
-
${color('tui', 'magenta')} Launch Terminal User Interface
|
|
50
|
+
${color('tui', 'magenta')} Launch Terminal User Interface (@jtcsv/tui)
|
|
51
51
|
${color('help', 'blue')} Show this help message
|
|
52
52
|
${color('version', 'blue')} Show version information
|
|
53
53
|
|
|
@@ -1038,34 +1038,17 @@ function parseOptions(args) {
|
|
|
1038
1038
|
|
|
1039
1039
|
async function launchTUI() {
|
|
1040
1040
|
try {
|
|
1041
|
-
// Check if blessed is installed
|
|
1042
|
-
require.resolve('blessed');
|
|
1043
|
-
|
|
1044
1041
|
console.log(color('Launching Terminal User Interface...', 'cyan'));
|
|
1045
1042
|
console.log(color('Press Ctrl+Q to exit', 'dim'));
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
const
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
if (stats.size < 100) {
|
|
1052
|
-
console.log(color('⚠️ TUI interface is not fully implemented yet', 'yellow'));
|
|
1053
|
-
console.log(color(' Basic TUI will be started...', 'dim'));
|
|
1054
|
-
|
|
1055
|
-
// Start basic TUI
|
|
1056
|
-
await startBasicTUI();
|
|
1057
|
-
} else {
|
|
1058
|
-
// Import and launch full TUI
|
|
1059
|
-
const JtcsvTUI = require('../cli-tui.js');
|
|
1060
|
-
const tui = new JtcsvTUI();
|
|
1061
|
-
tui.start();
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1043
|
+
|
|
1044
|
+
const JtcsvTUI = require('@jtcsv/tui');
|
|
1045
|
+
const tui = new JtcsvTUI();
|
|
1046
|
+
tui.start();
|
|
1064
1047
|
} catch (error) {
|
|
1065
1048
|
if (error.code === 'MODULE_NOT_FOUND') {
|
|
1066
|
-
console.error(color('Error:
|
|
1049
|
+
console.error(color('Error: @jtcsv/tui is not installed', 'red'));
|
|
1067
1050
|
console.log(color('Install it with:', 'dim'));
|
|
1068
|
-
console.log(color(' npm install
|
|
1051
|
+
console.log(color(' npm install @jtcsv/tui', 'cyan'));
|
|
1069
1052
|
console.log(color('\nOr use the CLI interface instead:', 'dim'));
|
|
1070
1053
|
console.log(color(' jtcsv help', 'cyan'));
|
|
1071
1054
|
} else {
|
package/csv-to-json.js
CHANGED
|
@@ -114,8 +114,9 @@ function validateCsvInput(csv, options) {
|
|
|
114
114
|
* Parses a value based on options
|
|
115
115
|
* @private
|
|
116
116
|
*/
|
|
117
|
-
function parseCsvValue(value, options) {
|
|
118
|
-
|
|
117
|
+
function parseCsvValue(value, options) {
|
|
118
|
+
/* istanbul ignore next */
|
|
119
|
+
const { trim = true, parseNumbers = false, parseBooleans = false } = options;
|
|
119
120
|
|
|
120
121
|
let result = value;
|
|
121
122
|
|
|
@@ -131,10 +132,11 @@ function parseCsvValue(value, options) {
|
|
|
131
132
|
// Parse numbers
|
|
132
133
|
if (parseNumbers && /^-?\d+(\.\d+)?$/.test(result)) {
|
|
133
134
|
const num = parseFloat(result);
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
135
|
+
/* istanbul ignore next */
|
|
136
|
+
if (!isNaN(num)) {
|
|
137
|
+
return num;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
138
140
|
|
|
139
141
|
// Parse booleans
|
|
140
142
|
if (parseBooleans) {
|
|
@@ -342,12 +344,13 @@ function csvToJson(csv, options = {}) {
|
|
|
342
344
|
console.warn(`[jtcsv] Line ${totalRows}: ${fields.length - headers.length} extra fields ignored`);
|
|
343
345
|
}
|
|
344
346
|
});
|
|
345
|
-
} catch (error) {
|
|
346
|
-
if (error && error.code === 'FAST_PATH_UNCLOSED_QUOTES') {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
347
|
+
} catch (error) {
|
|
348
|
+
if (error && error.code === 'FAST_PATH_UNCLOSED_QUOTES') {
|
|
349
|
+
const lineInfo = error.lineNumber ? ` at line ${error.lineNumber}` : '';
|
|
350
|
+
throw new ParsingError(`Unclosed quotes in CSV${lineInfo}`, error.lineNumber);
|
|
351
|
+
}
|
|
352
|
+
throw error;
|
|
353
|
+
}
|
|
351
354
|
|
|
352
355
|
if (!headers) {
|
|
353
356
|
return [];
|
|
@@ -371,7 +374,8 @@ function csvToJson(csv, options = {}) {
|
|
|
371
374
|
}, 'PARSE_FAILED', { function: 'csvToJson' });
|
|
372
375
|
}
|
|
373
376
|
|
|
374
|
-
|
|
377
|
+
/* istanbul ignore next */
|
|
378
|
+
async function* csvToJsonIterator(csv, options = {}) {
|
|
375
379
|
validateCsvInput(csv, options);
|
|
376
380
|
|
|
377
381
|
const opts = options && typeof options === 'object' ? options : {};
|
|
@@ -498,7 +502,8 @@ async function* csvToJsonIterator(csv, options = {}) {
|
|
|
498
502
|
}
|
|
499
503
|
} catch (error) {
|
|
500
504
|
if (error && error.code === 'FAST_PATH_UNCLOSED_QUOTES') {
|
|
501
|
-
|
|
505
|
+
const lineInfo = error.lineNumber ? ` at line ${error.lineNumber}` : '';
|
|
506
|
+
throw new ParsingError(`Unclosed quotes in CSV${lineInfo}`, error.lineNumber);
|
|
502
507
|
}
|
|
503
508
|
throw error;
|
|
504
509
|
}
|
|
@@ -638,24 +643,27 @@ function createTransformHooks() {
|
|
|
638
643
|
* @param {number} maxSize - Maximum cache size (default: 100)
|
|
639
644
|
* @returns {DelimiterCache} New DelimiterCache instance
|
|
640
645
|
*/
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
646
|
+
/* istanbul ignore next */
|
|
647
|
+
function createDelimiterCache(maxSize = 100) {
|
|
648
|
+
return new DelimiterCache(maxSize);
|
|
649
|
+
}
|
|
644
650
|
|
|
645
651
|
/**
|
|
646
652
|
* Gets statistics from the global delimiter cache
|
|
647
653
|
* @returns {Object} Cache statistics
|
|
648
654
|
*/
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
655
|
+
/* istanbul ignore next */
|
|
656
|
+
function getDelimiterCacheStats() {
|
|
657
|
+
return globalDelimiterCache.getStats();
|
|
658
|
+
}
|
|
652
659
|
|
|
653
660
|
/**
|
|
654
661
|
* Clears the global delimiter cache
|
|
655
662
|
*/
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
663
|
+
/* istanbul ignore next */
|
|
664
|
+
function clearDelimiterCache() {
|
|
665
|
+
globalDelimiterCache.clear();
|
|
666
|
+
}
|
|
659
667
|
|
|
660
668
|
// Export the functions
|
|
661
669
|
module.exports = {
|
|
@@ -674,6 +682,7 @@ module.exports = {
|
|
|
674
682
|
};
|
|
675
683
|
|
|
676
684
|
// For ES6 module compatibility
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
685
|
+
/* istanbul ignore next */
|
|
686
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
687
|
+
module.exports.default = csvToJson;
|
|
688
|
+
}
|