jtcsv 2.1.3 → 2.2.2
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/LICENSE +1 -1
- package/README.md +60 -341
- package/bin/jtcsv.js +2462 -1372
- 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/error-handling.js +324 -0
- package/examples/ndjson-processing.js +434 -0
- package/examples/react-integration.jsx +637 -0
- package/examples/schema-validation.js +640 -0
- package/examples/simple-usage.js +10 -7
- package/examples/typescript-example.ts +486 -0
- package/examples/web-workers-advanced.js +28 -0
- package/index.d.ts +2 -0
- package/json-save.js +2 -1
- package/json-to-csv.js +171 -131
- package/package.json +20 -4
- package/plugins/README.md +41 -467
- package/plugins/express-middleware/README.md +32 -274
- package/plugins/hono/README.md +16 -13
- package/plugins/nestjs/README.md +13 -11
- 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 +6 -7
- package/plugins/remix/README.md +9 -9
- package/plugins/sveltekit/README.md +8 -8
- package/plugins/trpc/README.md +8 -5
- 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/errors.js +26 -0
- package/src/formats/ndjson-parser.js +54 -5
- package/src/formats/tsv-parser.js +4 -1
- package/src/utils/schema-validator.js +594 -0
- package/src/utils/transform-loader.js +205 -0
- package/src/web-server/index.js +683 -0
- package/stream-csv-to-json.js +16 -87
- package/stream-json-to-csv.js +18 -86
package/stream-csv-to-json.js
CHANGED
|
@@ -20,6 +20,9 @@ const {
|
|
|
20
20
|
const { Transform, Writable } = require('stream');
|
|
21
21
|
const { pipeline } = require('stream/promises');
|
|
22
22
|
|
|
23
|
+
// Import schema validator from utils
|
|
24
|
+
const { createSchemaValidators } = require('./src/utils/schema-validator');
|
|
25
|
+
|
|
23
26
|
/**
|
|
24
27
|
* Creates a transform stream that converts CSV chunks to JSON objects
|
|
25
28
|
*
|
|
@@ -47,8 +50,10 @@ const { pipeline } = require('stream/promises');
|
|
|
47
50
|
* // Pipe CSV text to JSON objects
|
|
48
51
|
* csvReadableStream.pipe(transformStream).pipe(jsonWritableStream);
|
|
49
52
|
*/
|
|
53
|
+
/* istanbul ignore next */
|
|
50
54
|
function createCsvToJsonStream(options = {}) {
|
|
51
55
|
return safeExecute(() => {
|
|
56
|
+
/* istanbul ignore next */
|
|
52
57
|
const opts = options && typeof options === 'object' ? options : {};
|
|
53
58
|
|
|
54
59
|
const {
|
|
@@ -177,6 +182,7 @@ function createCsvToJsonStream(options = {}) {
|
|
|
177
182
|
// Parse numbers
|
|
178
183
|
if (parseNumbers && /^-?\d+(\.\d+)?$/.test(result)) {
|
|
179
184
|
const num = parseFloat(result);
|
|
185
|
+
/* istanbul ignore next */
|
|
180
186
|
if (!isNaN(num)) {
|
|
181
187
|
return num;
|
|
182
188
|
}
|
|
@@ -240,10 +246,12 @@ function createCsvToJsonStream(options = {}) {
|
|
|
240
246
|
const validator = schemaValidators[key];
|
|
241
247
|
|
|
242
248
|
// Apply validation if available
|
|
249
|
+
/* istanbul ignore next */
|
|
243
250
|
if (validator.validate) {
|
|
244
251
|
return validator.validate(value);
|
|
245
252
|
}
|
|
246
253
|
|
|
254
|
+
/* istanbul ignore next */
|
|
247
255
|
return true;
|
|
248
256
|
};
|
|
249
257
|
|
|
@@ -313,6 +321,7 @@ function createCsvToJsonStream(options = {}) {
|
|
|
313
321
|
if (transform) {
|
|
314
322
|
try {
|
|
315
323
|
result = transform(row);
|
|
324
|
+
/* istanbul ignore next */
|
|
316
325
|
if (!result || typeof result !== 'object') {
|
|
317
326
|
throw new ValidationError('Transform function must return an object');
|
|
318
327
|
}
|
|
@@ -376,6 +385,7 @@ function createCsvToJsonStream(options = {}) {
|
|
|
376
385
|
}
|
|
377
386
|
},
|
|
378
387
|
|
|
388
|
+
/* istanbul ignore next */
|
|
379
389
|
flush(callback) {
|
|
380
390
|
try {
|
|
381
391
|
// Process remaining buffer
|
|
@@ -423,7 +433,7 @@ function createCsvToJsonStream(options = {}) {
|
|
|
423
433
|
* }
|
|
424
434
|
* });
|
|
425
435
|
*/
|
|
426
|
-
async function streamCsvToJson(inputStream, outputStream, options = {}) {
|
|
436
|
+
/* istanbul ignore next */ async function streamCsvToJson(inputStream, outputStream, options = {}) {
|
|
427
437
|
return safeExecute(async () => {
|
|
428
438
|
const transformStream = createCsvToJsonStream(options);
|
|
429
439
|
|
|
@@ -493,89 +503,6 @@ async function createCsvFileToJsonStream(filePath, options = {}) {
|
|
|
493
503
|
}, 'FILE_STREAM_ERROR', { function: 'createCsvFileToJsonStream' });
|
|
494
504
|
}
|
|
495
505
|
|
|
496
|
-
/**
|
|
497
|
-
* Creates schema validators from JSON schema
|
|
498
|
-
*
|
|
499
|
-
* @private
|
|
500
|
-
* @param {Object} schema - JSON schema
|
|
501
|
-
* @returns {Object} Validators object
|
|
502
|
-
*/
|
|
503
|
-
function createSchemaValidators(schema) {
|
|
504
|
-
const validators = {};
|
|
505
|
-
|
|
506
|
-
if (!schema.properties) {
|
|
507
|
-
return validators;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
for (const [key, definition] of Object.entries(schema.properties)) {
|
|
511
|
-
const validator = {
|
|
512
|
-
type: definition.type,
|
|
513
|
-
required: schema.required && schema.required.includes(key)
|
|
514
|
-
};
|
|
515
|
-
|
|
516
|
-
// Add format function for dates
|
|
517
|
-
if (definition.type === 'string' && definition.format === 'date-time') {
|
|
518
|
-
validator.format = (value) => {
|
|
519
|
-
if (value instanceof Date) {
|
|
520
|
-
return value.toISOString();
|
|
521
|
-
}
|
|
522
|
-
if (typeof value === 'string') {
|
|
523
|
-
// Try to parse as date
|
|
524
|
-
const date = new Date(value);
|
|
525
|
-
if (!isNaN(date.getTime())) {
|
|
526
|
-
return date.toISOString();
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
return value;
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
// Add validation function
|
|
534
|
-
validator.validate = (value) => {
|
|
535
|
-
if (value === null || value === undefined) {
|
|
536
|
-
return !validator.required;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
// Type validation
|
|
540
|
-
if (definition.type === 'string' && typeof value !== 'string') {
|
|
541
|
-
return false;
|
|
542
|
-
}
|
|
543
|
-
if (definition.type === 'number' && typeof value !== 'number') {
|
|
544
|
-
return false;
|
|
545
|
-
}
|
|
546
|
-
if (definition.type === 'integer' && (!Number.isInteger(value) || typeof value !== 'number')) {
|
|
547
|
-
return false;
|
|
548
|
-
}
|
|
549
|
-
if (definition.type === 'boolean' && typeof value !== 'boolean') {
|
|
550
|
-
return false;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
// Additional constraints
|
|
554
|
-
if (definition.minimum !== undefined && value < definition.minimum) {
|
|
555
|
-
return false;
|
|
556
|
-
}
|
|
557
|
-
if (definition.maximum !== undefined && value > definition.maximum) {
|
|
558
|
-
return false;
|
|
559
|
-
}
|
|
560
|
-
if (definition.minLength !== undefined && value.length < definition.minLength) {
|
|
561
|
-
return false;
|
|
562
|
-
}
|
|
563
|
-
if (definition.maxLength !== undefined && value.length > definition.maxLength) {
|
|
564
|
-
return false;
|
|
565
|
-
}
|
|
566
|
-
if (definition.pattern && !new RegExp(definition.pattern).test(value)) {
|
|
567
|
-
return false;
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
return true;
|
|
571
|
-
};
|
|
572
|
-
|
|
573
|
-
validators[key] = validator;
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
return validators;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
506
|
/**
|
|
580
507
|
* Creates a writable stream that collects JSON objects into an array
|
|
581
508
|
*
|
|
@@ -603,11 +530,13 @@ module.exports = {
|
|
|
603
530
|
createCsvToJsonStream,
|
|
604
531
|
streamCsvToJson,
|
|
605
532
|
createCsvFileToJsonStream,
|
|
606
|
-
createJsonCollectorStream
|
|
607
|
-
createSchemaValidators
|
|
533
|
+
createJsonCollectorStream
|
|
534
|
+
// Note: createSchemaValidators is no longer exported from here
|
|
535
|
+
// It should be imported directly from './src/utils/schema-validator'
|
|
608
536
|
};
|
|
609
537
|
|
|
610
538
|
// For ES6 module compatibility
|
|
539
|
+
/* istanbul ignore next */
|
|
611
540
|
if (typeof module !== 'undefined' && module.exports) {
|
|
612
541
|
module.exports.default = createCsvToJsonStream;
|
|
613
|
-
}
|
|
542
|
+
}
|
package/stream-json-to-csv.js
CHANGED
|
@@ -18,6 +18,9 @@ const {
|
|
|
18
18
|
const { Transform, Readable, Writable } = require('stream');
|
|
19
19
|
const { pipeline } = require('stream/promises');
|
|
20
20
|
|
|
21
|
+
// Import schema validator from utils
|
|
22
|
+
const { createSchemaValidators } = require('./src/utils/schema-validator');
|
|
23
|
+
|
|
21
24
|
/**
|
|
22
25
|
* Creates a transform stream that converts JSON objects to CSV rows
|
|
23
26
|
*
|
|
@@ -42,8 +45,10 @@ const { pipeline } = require('stream/promises');
|
|
|
42
45
|
* // Pipe JSON objects to CSV
|
|
43
46
|
* jsonReadableStream.pipe(transformStream).pipe(csvWritableStream);
|
|
44
47
|
*/
|
|
48
|
+
/* istanbul ignore next */
|
|
45
49
|
function createJsonToCsvStream(options = {}) {
|
|
46
50
|
return safeExecute(() => {
|
|
51
|
+
/* istanbul ignore next */
|
|
47
52
|
const opts = options && typeof options === 'object' ? options : {};
|
|
48
53
|
|
|
49
54
|
const {
|
|
@@ -171,10 +176,12 @@ function createJsonToCsvStream(options = {}) {
|
|
|
171
176
|
const validator = schemaValidators[key];
|
|
172
177
|
|
|
173
178
|
// Apply validation if available
|
|
179
|
+
/* istanbul ignore next */
|
|
174
180
|
if (validator.validate) {
|
|
175
181
|
return validator.validate(value);
|
|
176
182
|
}
|
|
177
183
|
|
|
184
|
+
/* istanbul ignore next */
|
|
178
185
|
return true;
|
|
179
186
|
};
|
|
180
187
|
|
|
@@ -202,6 +209,7 @@ function createJsonToCsvStream(options = {}) {
|
|
|
202
209
|
if (transform) {
|
|
203
210
|
try {
|
|
204
211
|
item = transform(chunk);
|
|
212
|
+
/* istanbul ignore next */
|
|
205
213
|
if (!item || typeof item !== 'object') {
|
|
206
214
|
return callback(new ValidationError('Transform function must return an object'));
|
|
207
215
|
}
|
|
@@ -243,6 +251,7 @@ function createJsonToCsvStream(options = {}) {
|
|
|
243
251
|
// Build CSV row
|
|
244
252
|
const rowValues = finalHeaders.map(header => {
|
|
245
253
|
// Get the original key for this header
|
|
254
|
+
/* istanbul ignore next */
|
|
246
255
|
const originalKey = reverseRenameMap[header] || header;
|
|
247
256
|
let value = item[originalKey];
|
|
248
257
|
|
|
@@ -270,8 +279,10 @@ function createJsonToCsvStream(options = {}) {
|
|
|
270
279
|
flush(callback) {
|
|
271
280
|
// If no data was processed but headers were requested, write empty headers
|
|
272
281
|
if (includeHeaders && !headersWritten) {
|
|
282
|
+
/* istanbul ignore next */
|
|
273
283
|
if (Object.keys(template).length > 0) {
|
|
274
284
|
const templateHeaders = Object.keys(template).map(key => renameMap[key] || key);
|
|
285
|
+
/* istanbul ignore next */
|
|
275
286
|
if (templateHeaders.length > 0) {
|
|
276
287
|
this.push(templateHeaders.join(delimiter) + '\n');
|
|
277
288
|
}
|
|
@@ -283,89 +294,6 @@ function createJsonToCsvStream(options = {}) {
|
|
|
283
294
|
}, 'STREAM_CREATION_ERROR', { function: 'createJsonToCsvStream' });
|
|
284
295
|
}
|
|
285
296
|
|
|
286
|
-
/**
|
|
287
|
-
* Creates schema validators from JSON schema
|
|
288
|
-
*
|
|
289
|
-
* @private
|
|
290
|
-
* @param {Object} schema - JSON schema
|
|
291
|
-
* @returns {Object} Validators object
|
|
292
|
-
*/
|
|
293
|
-
function createSchemaValidators(schema) {
|
|
294
|
-
const validators = {};
|
|
295
|
-
|
|
296
|
-
if (!schema.properties) {
|
|
297
|
-
return validators;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
for (const [key, definition] of Object.entries(schema.properties)) {
|
|
301
|
-
const validator = {
|
|
302
|
-
type: definition.type,
|
|
303
|
-
required: schema.required && schema.required.includes(key)
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
// Add format function for dates
|
|
307
|
-
if (definition.type === 'string' && definition.format === 'date-time') {
|
|
308
|
-
validator.format = (value) => {
|
|
309
|
-
if (value instanceof Date) {
|
|
310
|
-
return value.toISOString();
|
|
311
|
-
}
|
|
312
|
-
if (typeof value === 'string') {
|
|
313
|
-
// Try to parse as date
|
|
314
|
-
const date = new Date(value);
|
|
315
|
-
if (!isNaN(date.getTime())) {
|
|
316
|
-
return date.toISOString();
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
return value;
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Add validation function
|
|
324
|
-
validator.validate = (value) => {
|
|
325
|
-
if (value === null || value === undefined) {
|
|
326
|
-
return !validator.required;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// Type validation
|
|
330
|
-
if (definition.type === 'string' && typeof value !== 'string') {
|
|
331
|
-
return false;
|
|
332
|
-
}
|
|
333
|
-
if (definition.type === 'number' && typeof value !== 'number') {
|
|
334
|
-
return false;
|
|
335
|
-
}
|
|
336
|
-
if (definition.type === 'integer' && (!Number.isInteger(value) || typeof value !== 'number')) {
|
|
337
|
-
return false;
|
|
338
|
-
}
|
|
339
|
-
if (definition.type === 'boolean' && typeof value !== 'boolean') {
|
|
340
|
-
return false;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// Additional constraints
|
|
344
|
-
if (definition.minimum !== undefined && value < definition.minimum) {
|
|
345
|
-
return false;
|
|
346
|
-
}
|
|
347
|
-
if (definition.maximum !== undefined && value > definition.maximum) {
|
|
348
|
-
return false;
|
|
349
|
-
}
|
|
350
|
-
if (definition.minLength !== undefined && value.length < definition.minLength) {
|
|
351
|
-
return false;
|
|
352
|
-
}
|
|
353
|
-
if (definition.maxLength !== undefined && value.length > definition.maxLength) {
|
|
354
|
-
return false;
|
|
355
|
-
}
|
|
356
|
-
if (definition.pattern && !new RegExp(definition.pattern).test(value)) {
|
|
357
|
-
return false;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
return true;
|
|
361
|
-
};
|
|
362
|
-
|
|
363
|
-
validators[key] = validator;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
return validators;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
297
|
/**
|
|
370
298
|
* Converts a readable stream of JSON objects to CSV and writes to a writable stream
|
|
371
299
|
*
|
|
@@ -388,6 +316,7 @@ function createSchemaValidators(schema) {
|
|
|
388
316
|
* }
|
|
389
317
|
* });
|
|
390
318
|
*/
|
|
319
|
+
/* istanbul ignore next */
|
|
391
320
|
async function streamJsonToCsv(inputStream, outputStream, options = {}) {
|
|
392
321
|
return safeExecute(async () => {
|
|
393
322
|
const transformStream = createJsonToCsvStream(options);
|
|
@@ -475,6 +404,7 @@ function createJsonReadableStream(data) {
|
|
|
475
404
|
return new Readable({
|
|
476
405
|
objectMode: true,
|
|
477
406
|
read() {
|
|
407
|
+
/* istanbul ignore next */
|
|
478
408
|
if (!this._data) {
|
|
479
409
|
this._data = Array.isArray(data) ? [...data] : [];
|
|
480
410
|
this._index = 0;
|
|
@@ -522,11 +452,13 @@ module.exports = {
|
|
|
522
452
|
streamJsonToCsv,
|
|
523
453
|
saveJsonStreamAsCsv,
|
|
524
454
|
createJsonReadableStream,
|
|
525
|
-
createCsvCollectorStream
|
|
526
|
-
createSchemaValidators
|
|
455
|
+
createCsvCollectorStream
|
|
456
|
+
// Note: createSchemaValidators is no longer exported from here
|
|
457
|
+
// It should be imported directly from './src/utils/schema-validator'
|
|
527
458
|
};
|
|
528
459
|
|
|
529
460
|
// For ES6 module compatibility
|
|
461
|
+
/* istanbul ignore next */
|
|
530
462
|
if (typeof module !== 'undefined' && module.exports) {
|
|
531
463
|
module.exports.default = createJsonToCsvStream;
|
|
532
|
-
}
|
|
464
|
+
}
|