diff --git a/.husky/commit-msg b/.husky/commit-msg index 7398961c0..1ba698a9c 100755 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1,3 +1,2 @@ -#!/bin/sh -npx commitlint --edit $1 +npx --no-install commitlint --edit $1 diff --git a/.husky/pre-commit b/.husky/pre-commit index 1fb913e3d..cec3fa551 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1,2 @@ + npm run lint:staged diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 918cb1dd9..2190dc23f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,9 +1,9 @@ -## How to contribute to CoffeeScript +## How to contribute to the CSV project -* Before you open a ticket or send a pull request, [search](https://github.com/adaltas/node-csv/issues) for previous discussions about the same feature or issue. Add to the earlier ticket if you find one. +- Before you open a ticket or send a pull request, [search](https://github.com/adaltas/node-csv/issues) for previous discussions about the same feature or issue. Add to the earlier ticket if you find one. -* Before sending a pull request for a feature, be sure to have [tests](https://github.com/adaltas/node-csv/tree/master/packages/csv/test). +- Before sending a pull request for a feature, be sure to have [tests](https://github.com/adaltas/node-csv/tree/master/packages/csv/test). -* Use the same coding style as the rest of the [codebase](https://github.com/adaltas/node-csv/tree/master/packages). If you’re writing a test and if you're just getting started with CoffeeScript, there’s a nice [style guide](https://github.com/polarmobile/coffeescript-style-guide). +- Use the same coding style as the rest of the [codebase](https://github.com/adaltas/node-csv/tree/master/packages). -* Documentation is published on [GitHub](https://github.com/adaltas/node-csv-docs) and you are invited to submit a pull request with your changes. For convenience, you can also browse the website and click on the Edit link present at the top of every page. +- Documentation is published on [GitHub](https://github.com/adaltas/node-csv-docs) and you are invited to submit a pull request with your changes. For convenience, you can also browse the website and click on the Edit link present at the top of every page. diff --git a/demo/browser/CHANGELOG.md b/demo/browser/CHANGELOG.md index b407c0556..95fc362cd 100644 --- a/demo/browser/CHANGELOG.md +++ b/demo/browser/CHANGELOG.md @@ -3,6 +3,20 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.1](https://github.com/adaltas/node-csv/compare/csv-demo-browser@0.1.21...csv-demo-browser@0.2.1) (2025-07-16) + +**Note:** Version bump only for package csv-demo-browser + +## 0.2.0 (2025-07-10) + +### Features + +- **csv-demo-webpack:** split usages by packages ([214c759](https://github.com/adaltas/node-csv/commit/214c75980d61bf96ec1d6892858887ba29235987)) + +### Bug Fixes + +- support ts node16 resolution in cjs ([#354](https://github.com/adaltas/node-csv/issues/354)) ([fa09d03](https://github.com/adaltas/node-csv/commit/fa09d03aaf0008b2790656871ca6b2c4be12d14c)) + ## [0.1.21](https://github.com/adaltas/node-csv/compare/csv-demo-browser@0.1.20...csv-demo-browser@0.1.21) (2024-11-21) **Note:** Version bump only for package csv-demo-browser diff --git a/demo/browser/package.json b/demo/browser/package.json index d2ad63617..b1c4e1dd8 100644 --- a/demo/browser/package.json +++ b/demo/browser/package.json @@ -1,6 +1,6 @@ { "name": "csv-demo-browser", - "version": "0.1.21", + "version": "0.2.1", "main": "index.js", "license": "MIT", "type": "module", @@ -17,14 +17,15 @@ "timeout": 40000 }, "scripts": { - "start": "node server.js" + "start": "node server.js", + "test": "exit 0" }, "dependencies": { - "csv": "^6.3.11", - "csv-generate": "^4.4.2", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2", - "express": "^4.21.1", - "stream-transform": "^3.3.3" + "csv": "^6.4.1", + "csv-generate": "^4.5.0", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0", + "express": "^5.1.0", + "stream-transform": "^3.4.0" } } diff --git a/demo/cjs/CHANGELOG.md b/demo/cjs/CHANGELOG.md index 481b189d6..e7a0ef846 100644 --- a/demo/cjs/CHANGELOG.md +++ b/demo/cjs/CHANGELOG.md @@ -3,6 +3,25 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.3.1](https://github.com/adaltas/node-csv/compare/csv-demo-cjs@0.2.19...csv-demo-cjs@0.3.1) (2025-07-16) + +### Bug Fixes + +- **csv-demo-cjs:** ts type ([9bb1bf8](https://github.com/adaltas/node-csv/commit/9bb1bf8e0084cd38f788dd56851b9af4149ac49d)) + +## 0.3.0 (2025-07-10) + +### Features + +- backward support for node 8 ([496231d](https://github.com/adaltas/node-csv/commit/496231dfd838f0a6a72269a5a2390a4c637cef95)) +- **csv-demo-cjs:** new stringify.ts sample ([b44de05](https://github.com/adaltas/node-csv/commit/b44de05d70b4577cdb85c4f285321eea840f8fa3)) + +### Bug Fixes + +- **csv-demo-cjs:** ts type ([9bb1bf8](https://github.com/adaltas/node-csv/commit/9bb1bf8e0084cd38f788dd56851b9af4149ac49d)) +- **csv-demo-ts-cjs-node16:** upgrade module definition after latest typescript ([87fe919](https://github.com/adaltas/node-csv/commit/87fe91996fb2a8895c252177fca4f0cb59a518f9)) +- support ts node16 resolution in cjs ([#354](https://github.com/adaltas/node-csv/issues/354)) ([fa09d03](https://github.com/adaltas/node-csv/commit/fa09d03aaf0008b2790656871ca6b2c4be12d14c)) + ## [0.2.19](https://github.com/adaltas/node-csv/compare/csv-demo-cjs@0.2.18...csv-demo-cjs@0.2.19) (2024-11-21) **Note:** Version bump only for package csv-demo-cjs diff --git a/demo/cjs/lib/csv.ts b/demo/cjs/lib/csv.ts index 285406407..efcd4c1eb 100644 --- a/demo/cjs/lib/csv.ts +++ b/demo/cjs/lib/csv.ts @@ -1,35 +1,30 @@ - // Import the package main module -import * as csv from 'csv' +import * as csv from "csv"; // Generate 20 records const generator: csv.generator.Generator = csv.generate({ - delimiter: '|', - length: 20 -}) + delimiter: "|", + length: 20, +}); // Transform CSV data into records const parser: csv.parser.Parser = csv.parse({ - delimiter: '|' -}) + delimiter: "|", +}); // Transform each value into uppercase const transformer: csv.transformer.Transformer = csv.transform((record) => { - return record.map((value: string) => { - return value.toUpperCase() - }); -}) + return record.map((value: string) => { + return value.toUpperCase(); + }); +}); // Convert objects into a stream const stringifier: csv.stringifier.Stringifier = csv.stringify({ cast: { string: (value: string, context: csv.stringifier.CastingContext) => { return context.index % 2 ? value.toLowerCase() : value.toUpperCase(); - } + }, }, quoted: true, -}) +}); // Run the pipeline -generator -.pipe(parser) -.pipe(transformer) -.pipe(stringifier) -.pipe(process.stdout) +generator.pipe(parser).pipe(transformer).pipe(stringifier).pipe(process.stdout); diff --git a/demo/cjs/lib/csv_sync.ts b/demo/cjs/lib/csv_sync.ts index 379a71db1..51e5abbe3 100644 --- a/demo/cjs/lib/csv_sync.ts +++ b/demo/cjs/lib/csv_sync.ts @@ -1,31 +1,30 @@ - // Import the package sync module // Node.js >= 14 -import * as csv from 'csv/sync'; +import * as csv from "csv/sync"; // Node.js < 14 // import * as csv from 'csv/dist/cjs/sync'; // Generate 20 records const input: string = csv.generate({ - delimiter: '|', + delimiter: "|", length: 20, }); // Transform CSV data into records const records: any = csv.parse(input, { - delimiter: '|', + delimiter: "|", }); // Transform each value into uppercase const uppercaseRecords: any = csv.transform(records, (record) => { - return record.map((value: string) => { - return value.toUpperCase() - }); + return record.map((value: string) => { + return value.toUpperCase(); + }); }); // Convert objects into a stream const output: any = csv.stringify(uppercaseRecords, { cast: { string: (value: string, context: csv.stringifier.CastingContext) => { return context.index % 2 ? value.toLowerCase() : value.toUpperCase(); - } + }, }, quoted: true, }); diff --git a/demo/cjs/lib/parse.ts b/demo/cjs/lib/parse.ts index c5a8203b5..7c3cb444f 100644 --- a/demo/cjs/lib/parse.ts +++ b/demo/cjs/lib/parse.ts @@ -1,31 +1,28 @@ - -import assert from 'node:assert' -import { parse, Parser } from 'csv-parse' +import assert from "node:assert"; +import { parse, Parser } from "csv-parse"; const output: any = []; // Create the parser const parser: Parser = parse({ - delimiter: ':' + delimiter: ":", }); // Use the readable stream api to consume records -parser.on('readable', function(){ - let record; while ((record = parser.read()) !== null) { - output.push(record) +parser.on("readable", function () { + let record; + while ((record = parser.read()) !== null) { + output.push(record); } }); // Catch any error -parser.on('error', function(err){ - console.error(err.message) +parser.on("error", function (err) { + console.error(err.message); }); // Test that the parsed records matched what's expected -parser.on('end', function(){ - assert.deepStrictEqual( - output, - [ - [ 'a','b','c' ], - [ '1','2','3' ] - ] - ) +parser.on("end", function () { + assert.deepStrictEqual(output, [ + ["a", "b", "c"], + ["1", "2", "3"], + ]); }); // Write data to the stream parser.write("a:b:c\n"); diff --git a/demo/cjs/lib/parse_sync.ts b/demo/cjs/lib/parse_sync.ts index f4ace4a21..55eb79da5 100644 --- a/demo/cjs/lib/parse_sync.ts +++ b/demo/cjs/lib/parse_sync.ts @@ -1,22 +1,15 @@ - -import assert from 'node:assert' +import assert from "node:assert"; // Node.js >= 14 -import { parse } from 'csv-parse/sync' +import { parse } from "csv-parse/sync"; // Node.js < 14 // import { parse } from 'csv-parse/dist/cjs/sync' // Create the parser -const records: [] = parse([ - "a:b:c\n", - "1:2:3\n" -].join(''), { - delimiter: ':' +const records: string[][] = parse(["a:b:c\n", "1:2:3\n"].join(""), { + delimiter: ":", }); // Test that the parsed records matched what's expected -assert.deepStrictEqual( - records, - [ - [ 'a','b','c' ], - [ '1','2','3' ] - ] -); +assert.deepStrictEqual(records, [ + ["a", "b", "c"], + ["1", "2", "3"], +]); diff --git a/demo/cjs/lib/stringify.ts b/demo/cjs/lib/stringify.ts index be5951997..2f985f1be 100644 --- a/demo/cjs/lib/stringify.ts +++ b/demo/cjs/lib/stringify.ts @@ -1,29 +1,26 @@ +import assert from "node:assert"; +import { stringify, Stringifier } from "csv-stringify"; -import assert from 'node:assert' -import { stringify, Stringifier } from 'csv-stringify'; - -let output: string = ''; +let output: string = ""; // Create the parser const stringifier: Stringifier = stringify({ - delimiter: ':', - encoding: 'utf8' + delimiter: ":", + encoding: "utf8", }); // Use the readable stream api to consume records -stringifier.on('readable', function(){ - let record; while ((record = stringifier.read()) !== null) { - output += record +stringifier.on("readable", function () { + let record; + while ((record = stringifier.read()) !== null) { + output += record; } }); // Catch any error -stringifier.on('error', function(err){ - console.error(err.message) +stringifier.on("error", function (err) { + console.error(err.message); }); // Test that the parsed records matched what's expected -stringifier.on('end', function(){ - assert.deepStrictEqual( - output, - 'a:b:c\n1:2:3\n' - ) +stringifier.on("end", function () { + assert.deepStrictEqual(output, "a:b:c\n1:2:3\n"); }); // Write data to the stream stringifier.write(["a", "b", "c"]); diff --git a/demo/cjs/package.json b/demo/cjs/package.json index 46d76053c..f97bd2318 100644 --- a/demo/cjs/package.json +++ b/demo/cjs/package.json @@ -1,22 +1,22 @@ { "name": "csv-demo-cjs", - "version": "0.2.19", + "version": "0.3.1", "main": "index.js", "license": "MIT", "type": "commonjs", "private": true, "dependencies": { - "csv": "^6.3.11", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2" + "csv": "^6.4.1", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0" }, "devDependencies": { - "@types/node": "^22.9.1", + "@types/node": "^22.15.30", "coffeescript": "^2.7.0", - "mocha": "^10.8.2", + "mocha": "^11.5.0", "should": "^13.2.3", "ts-node": "^10.9.2", - "typescript": "^5.6.3" + "typescript": "^5.8.3" }, "mocha": { "inline-diffs": true, diff --git a/demo/eslint/CHANGELOG.md b/demo/eslint/CHANGELOG.md index 27d1a34f3..a93357527 100644 --- a/demo/eslint/CHANGELOG.md +++ b/demo/eslint/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 0.2.0 (2025-07-10) + +### Features + +- wg stream api ([8a5eb7d](https://github.com/adaltas/node-csv/commit/8a5eb7dfd31b22217db4fbbc832d707221850785)) + +### Bug Fixes + +- commonjs types, run tsc and lint to validate changes ([#397](https://github.com/adaltas/node-csv/issues/397)) ([e6870fe](https://github.com/adaltas/node-csv/commit/e6870fe272c119e273196522c9771d12ff8b2a35)) +- **csv-demo-eslint:** private package ([28d6066](https://github.com/adaltas/node-csv/commit/28d60660de1c886e51e9cc16771f17fc4257a304)) +- **csv-demo-ts-cjs-node16:** upgrade module definition after latest typescript ([87fe919](https://github.com/adaltas/node-csv/commit/87fe91996fb2a8895c252177fca4f0cb59a518f9)) + ## [0.1.23](https://github.com/adaltas/node-csv/compare/csv-demo-eslint@0.1.22...csv-demo-eslint@0.1.23) (2024-11-21) **Note:** Version bump only for package csv-demo-eslint diff --git a/demo/eslint/package.json b/demo/eslint/package.json index 3d1871f3c..c88a8f7ee 100644 --- a/demo/eslint/package.json +++ b/demo/eslint/package.json @@ -1,6 +1,6 @@ { "name": "csv-demo-eslint", - "version": "0.1.23", + "version": "0.2.0", "description": "", "main": "index.js", "private": true, @@ -10,10 +10,10 @@ }, "license": "MIT", "dependencies": { - "csv-stringify": "^6.5.2" + "csv-stringify": "^6.6.0" }, "devDependencies": { - "eslint": "^9.15.0", + "eslint": "^9.28.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-plugin-import": "^2.31.0" } diff --git a/demo/esm/CHANGELOG.md b/demo/esm/CHANGELOG.md index 704e0528e..be1d51eaa 100644 --- a/demo/esm/CHANGELOG.md +++ b/demo/esm/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.0.35](https://github.com/adaltas/node-csv/compare/csv-demo-esm@0.0.33...csv-demo-esm@0.0.35) (2025-07-16) + +### Bug Fixes + +- **csv-demo-esm:** ts type ([5ad1f2d](https://github.com/adaltas/node-csv/commit/5ad1f2db3229867d0e2f58f056752e65e4e37102)) + +## 0.0.34 (2025-07-10) + +### Bug Fixes + +- **csv-demo-esm:** csv dependencies ([64afead](https://github.com/adaltas/node-csv/commit/64afead8dc41b9d379c9761ddb70d6a29251b4e2)) +- **csv-demo-esm:** ts type ([5ad1f2d](https://github.com/adaltas/node-csv/commit/5ad1f2db3229867d0e2f58f056752e65e4e37102)) + ## [0.0.33](https://github.com/adaltas/node-csv/compare/csv-demo-esm@0.0.32...csv-demo-esm@0.0.33) (2024-11-21) **Note:** Version bump only for package csv-demo-esm diff --git a/demo/esm/lib/csv.ts b/demo/esm/lib/csv.ts index 285406407..efcd4c1eb 100644 --- a/demo/esm/lib/csv.ts +++ b/demo/esm/lib/csv.ts @@ -1,35 +1,30 @@ - // Import the package main module -import * as csv from 'csv' +import * as csv from "csv"; // Generate 20 records const generator: csv.generator.Generator = csv.generate({ - delimiter: '|', - length: 20 -}) + delimiter: "|", + length: 20, +}); // Transform CSV data into records const parser: csv.parser.Parser = csv.parse({ - delimiter: '|' -}) + delimiter: "|", +}); // Transform each value into uppercase const transformer: csv.transformer.Transformer = csv.transform((record) => { - return record.map((value: string) => { - return value.toUpperCase() - }); -}) + return record.map((value: string) => { + return value.toUpperCase(); + }); +}); // Convert objects into a stream const stringifier: csv.stringifier.Stringifier = csv.stringify({ cast: { string: (value: string, context: csv.stringifier.CastingContext) => { return context.index % 2 ? value.toLowerCase() : value.toUpperCase(); - } + }, }, quoted: true, -}) +}); // Run the pipeline -generator -.pipe(parser) -.pipe(transformer) -.pipe(stringifier) -.pipe(process.stdout) +generator.pipe(parser).pipe(transformer).pipe(stringifier).pipe(process.stdout); diff --git a/demo/esm/lib/csv_sync.ts b/demo/esm/lib/csv_sync.ts index 82a7f75b6..09af0ce36 100644 --- a/demo/esm/lib/csv_sync.ts +++ b/demo/esm/lib/csv_sync.ts @@ -1,28 +1,27 @@ - // Import the package sync module -import * as csv from 'csv/sync'; +import * as csv from "csv/sync"; // Generate 20 records const input: string = csv.generate({ - delimiter: '|', + delimiter: "|", length: 20, }); // Transform CSV data into records const records: any = csv.parse(input, { - delimiter: '|', + delimiter: "|", }); // Transform each value into uppercase const uppercaseRecords: any = csv.transform(records, (record) => { - return record.map((value: string) => { - return value.toUpperCase() - }); + return record.map((value: string) => { + return value.toUpperCase(); + }); }); // Convert objects into a stream const output: any = csv.stringify(uppercaseRecords, { cast: { string: (value: string, context: csv.stringifier.CastingContext) => { return context.index % 2 ? value.toLowerCase() : value.toUpperCase(); - } + }, }, quoted: true, }); diff --git a/demo/esm/lib/parse.ts b/demo/esm/lib/parse.ts index 43c02be86..add7876e6 100644 --- a/demo/esm/lib/parse.ts +++ b/demo/esm/lib/parse.ts @@ -1,31 +1,28 @@ - -import assert from 'assert' -import { parse, Parser } from 'csv-parse' +import assert from "assert"; +import { parse, Parser } from "csv-parse"; const output: any = []; // Create the parser const parser: Parser = parse({ - delimiter: ':' + delimiter: ":", }); // Use the readable stream api to consume records -parser.on('readable', function(){ - let record; while ((record = parser.read()) !== null) { - output.push(record) +parser.on("readable", function () { + let record; + while ((record = parser.read()) !== null) { + output.push(record); } }); // Catch any error -parser.on('error', function(err){ - console.error(err.message) +parser.on("error", function (err) { + console.error(err.message); }); // Test that the parsed records matched what's expected -parser.on('end', function(){ - assert.deepStrictEqual( - output, - [ - [ 'a','b','c' ], - [ '1','2','3' ] - ] - ) +parser.on("end", function () { + assert.deepStrictEqual(output, [ + ["a", "b", "c"], + ["1", "2", "3"], + ]); }); // Write data to the stream parser.write("a:b:c\n"); diff --git a/demo/esm/lib/parse_sync.ts b/demo/esm/lib/parse_sync.ts index efba9da7d..e7e3c3e4e 100644 --- a/demo/esm/lib/parse_sync.ts +++ b/demo/esm/lib/parse_sync.ts @@ -1,19 +1,12 @@ - -import assert from 'assert' -import { parse } from 'csv-parse/sync' +import assert from "assert"; +import { parse } from "csv-parse/sync"; // Create the parser -const records: [] = parse([ - "a:b:c\n", - "1:2:3\n" -].join(''), { - delimiter: ':' +const records: string[][] = parse(["a:b:c\n", "1:2:3\n"].join(""), { + delimiter: ":", }); // Test that the parsed records matched what's expected -assert.deepStrictEqual( - records, - [ - [ 'a','b','c' ], - [ '1','2','3' ] - ] -); +assert.deepStrictEqual(records, [ + ["a", "b", "c"], + ["1", "2", "3"], +]); diff --git a/demo/esm/package.json b/demo/esm/package.json index 745c0011b..541801cf4 100644 --- a/demo/esm/package.json +++ b/demo/esm/package.json @@ -1,17 +1,17 @@ { "name": "csv-demo-esm", - "version": "0.0.33", + "version": "0.0.35", "main": "index.js", "license": "MIT", "type": "module", "private": true, "dependencies": { - "csv": "^6.3.11", - "csv-parse": "^5.6.0" + "csv": "^6.4.1", + "csv-parse": "^6.1.0" }, "devDependencies": { "coffeescript": "^2.7.0", - "mocha": "^10.8.2", + "mocha": "^11.5.0", "should": "^13.2.3" }, "mocha": { diff --git a/demo/issues-cjs/CHANGELOG.md b/demo/issues-cjs/CHANGELOG.md index df19e5909..b5593e78d 100644 --- a/demo/issues-cjs/CHANGELOG.md +++ b/demo/issues-cjs/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.3.1](https://github.com/adaltas/node-csv/compare/csv-issues-cjs@0.2.8...csv-issues-cjs@0.3.1) (2025-07-16) + +**Note:** Version bump only for package csv-issues-cjs + +## 0.3.0 (2025-07-10) + +### Features + +- **csv-issues-cjs:** 330 sample code ([3d85a41](https://github.com/adaltas/node-csv/commit/3d85a411007416f3cb750ca6b427f55c0331a8b8)) +- **csv-issues-cjs:** 399 issue ([b8df8db](https://github.com/adaltas/node-csv/commit/b8df8dbf071021aa398ea82dbe650ab3e7b16a0b)) + +### Bug Fixes + +- **csv-issues-esm:** illustrate issue [#300](https://github.com/adaltas/node-csv/issues/300) ([7358f9d](https://github.com/adaltas/node-csv/commit/7358f9d2b150655579dadf2af1aa64206fc7e2fa)) +- **csv-stringify:** catch error with sync api, fix [#296](https://github.com/adaltas/node-csv/issues/296) ([e157f40](https://github.com/adaltas/node-csv/commit/e157f407eeffe5bcfb179cb20476169037bfb4f1)) +- dont insert polyfills in cjs [#303](https://github.com/adaltas/node-csv/issues/303) ([9baf334](https://github.com/adaltas/node-csv/commit/9baf334044dab90b4a0d096a7e456d0fd5807d5b)) +- support ts node16 resolution in cjs ([#354](https://github.com/adaltas/node-csv/issues/354)) ([fa09d03](https://github.com/adaltas/node-csv/commit/fa09d03aaf0008b2790656871ca6b2c4be12d14c)) + ## [0.2.8](https://github.com/adaltas/node-csv/compare/csv-issues-cjs@0.2.7...csv-issues-cjs@0.2.8) (2024-11-21) **Note:** Version bump only for package csv-issues-cjs diff --git a/demo/issues-cjs/package.json b/demo/issues-cjs/package.json index a658939e8..b37b4f077 100644 --- a/demo/issues-cjs/package.json +++ b/demo/issues-cjs/package.json @@ -1,16 +1,16 @@ { "name": "csv-issues-cjs", - "version": "0.2.8", + "version": "0.3.1", "main": "index.js", "license": "MIT", "private": true, "dependencies": { - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2" + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0" }, "devDependencies": { "coffeescript": "^2.7.0", - "mocha": "^10.8.2", + "mocha": "^11.5.0", "should": "^13.2.3" }, "mocha": { diff --git a/demo/issues-esm/CHANGELOG.md b/demo/issues-esm/CHANGELOG.md index b0316ff22..e0e3e0f0c 100644 --- a/demo/issues-esm/CHANGELOG.md +++ b/demo/issues-esm/CHANGELOG.md @@ -3,6 +3,32 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.5.1](https://github.com/adaltas/node-csv/compare/csv-issues-esm@0.4.0...csv-issues-esm@0.5.1) (2025-07-16) + +**Note:** Version bump only for package csv-issues-esm + +## 0.5.0 (2025-07-10) + +### Features + +- **csv-issues-esm:** 437 sample with endable transformer ([bec3f12](https://github.com/adaltas/node-csv/commit/bec3f12072f47f2eaf7f67b25d081d292c36de26)) +- **csv-issues-esm:** issue 411 reproductible 2nd attempt ([41fca27](https://github.com/adaltas/node-csv/commit/41fca279cb10e7bb1a97e09c301e52cfd07856f0)) +- **csv-issues-esm:** issue 411 reproductible attempt ([6c5cb5e](https://github.com/adaltas/node-csv/commit/6c5cb5efb333ed0f6e3f64d2a8cddb2d4f813521)) +- **csv-issues-esm:** issue 423 ([c255eb5](https://github.com/adaltas/node-csv/commit/c255eb57015f821c4dea6558ddb5f58ae908b616)) +- **csv-issues-esm:** issue 436 ([0cbe4c7](https://github.com/adaltas/node-csv/commit/0cbe4c781dcd77b9e4354f9b12abe8dfca539771)) +- **csv-issues-esm:** issue 441 ([6ecf900](https://github.com/adaltas/node-csv/commit/6ecf90049a7e08a3fe9ff2f99c53ab032d91ff05)) +- **csv-issues-esm:** more transform config in sample ([0c2acf1](https://github.com/adaltas/node-csv/commit/0c2acf10ca61faa4d97fae147596905e7316ac95)) +- **csv-issues-esm:** reproduce issue [#415](https://github.com/adaltas/node-csv/issues/415) ([28088bc](https://github.com/adaltas/node-csv/commit/28088bcfb72331fe6ba26046a0af283c8dc0c40d)) + +### Bug Fixes + +- **csv-issues-esm:** illustrate cas [#381](https://github.com/adaltas/node-csv/issues/381) ([5f8fcb6](https://github.com/adaltas/node-csv/commit/5f8fcb639af87d04f96115ddc811df90f435c483)) +- **csv-parse:** comment infix when comment first field char (fix [#415](https://github.com/adaltas/node-csv/issues/415)) ([8e0f8b8](https://github.com/adaltas/node-csv/commit/8e0f8b8e11736f1223b0bda4dd2a3b37506dd531)) +- **csv-parse:** record_delimiter and non default encoding (fix [#365](https://github.com/adaltas/node-csv/issues/365)) ([16fdb2d](https://github.com/adaltas/node-csv/commit/16fdb2dd2c3221d00568f28bed44106ffc0d49ef)) +- **csv-parse:** skip event not raised with bom (fix [#411](https://github.com/adaltas/node-csv/issues/411)) ([1326351](https://github.com/adaltas/node-csv/commit/13263514ef6ec02000cf2da39ba6aa2ff92f00ae)) +- **stream-transform:** backpressure after push ([3e83f4e](https://github.com/adaltas/node-csv/commit/3e83f4e604b7b944835de18afcb41716ce4bbfad)) +- support ts node16 resolution in cjs ([#354](https://github.com/adaltas/node-csv/issues/354)) ([fa09d03](https://github.com/adaltas/node-csv/commit/fa09d03aaf0008b2790656871ca6b2c4be12d14c)) + ## [0.4.0](https://github.com/adaltas/node-csv/compare/csv-issues-esm@0.3.1...csv-issues-esm@0.4.0) (2024-11-21) ### Features diff --git a/demo/issues-esm/package.json b/demo/issues-esm/package.json index c3f93c903..12e415a89 100644 --- a/demo/issues-esm/package.json +++ b/demo/issues-esm/package.json @@ -1,6 +1,6 @@ { "name": "csv-issues-esm", - "version": "0.4.0", + "version": "0.5.1", "main": "index.js", "license": "MIT", "type": "module", @@ -8,7 +8,7 @@ "devDependencies": { "coffeescript": "^2.7.0", "dirname-filename-esm": "^1.1.2", - "mocha": "^10.8.2", + "mocha": "^11.5.0", "should": "^13.2.3" }, "mocha": { @@ -33,11 +33,11 @@ "test": "mocha 'test/**/*.coffee'" }, "dependencies": { - "csv-generate": "^4.4.2", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2", - "dedent": "^1.5.3", + "csv-generate": "^4.5.0", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0", + "dedent": "^1.6.0", "desm": "^1.3.1", - "duckdb-async": "^1.1.3" + "duckdb-async": "^1.2.1" } } diff --git a/demo/ts-cjs-node16/CHANGELOG.md b/demo/ts-cjs-node16/CHANGELOG.md index 2ffd376de..8d541536f 100644 --- a/demo/ts-cjs-node16/CHANGELOG.md +++ b/demo/ts-cjs-node16/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.21](https://github.com/adaltas/node-csv/compare/csv-demo-ts-cjs-node16@0.2.19...csv-demo-ts-cjs-node16@0.2.21) (2025-07-16) + +**Note:** Version bump only for package csv-demo-ts-cjs-node16 + +## 0.2.20 (2025-07-10) + +### Bug Fixes + +- **csv-demo-ts-cjs-node16:** upgrade module definition after latest typescript ([87fe919](https://github.com/adaltas/node-csv/commit/87fe91996fb2a8895c252177fca4f0cb59a518f9)) +- support ts node16 resolution in cjs ([#354](https://github.com/adaltas/node-csv/issues/354)) ([fa09d03](https://github.com/adaltas/node-csv/commit/fa09d03aaf0008b2790656871ca6b2c4be12d14c)) + ## [0.2.19](https://github.com/adaltas/node-csv/compare/csv-demo-ts-cjs-node16@0.2.18...csv-demo-ts-cjs-node16@0.2.19) (2024-11-21) **Note:** Version bump only for package csv-demo-ts-cjs-node16 diff --git a/demo/ts-cjs-node16/lib/index.ts b/demo/ts-cjs-node16/lib/index.ts index dc885b67d..e6e4fd69c 100644 --- a/demo/ts-cjs-node16/lib/index.ts +++ b/demo/ts-cjs-node16/lib/index.ts @@ -1,28 +1,30 @@ +import assert from "assert"; +import { generate, Generator } from "csv-generate"; +import { parse, Parser } from "csv-parse"; +import { transform, Transformer } from "stream-transform"; +import { stringify, Stringifier } from "csv-stringify"; -import assert from 'assert' -import { generate, Generator } from 'csv-generate'; -import { parse, Parser } from 'csv-parse'; -import { transform, Transformer } from 'stream-transform'; -import { stringify, Stringifier } from 'csv-stringify'; - -let chunks: string[] = []; +const chunks: string[] = []; // Create the parser -const generator: Generator = generate({length: 2, seed: true}); +const generator: Generator = generate({ length: 2, seed: true }); const parser: Parser = parse(); const transformer: Transformer = transform((record) => record); const stringifier: Stringifier = stringify(); -generator.pipe(parser).pipe(transformer).pipe(stringifier) - .on('data', function(data) { - chunks.push(data.toString()) +generator + .pipe(parser) + .pipe(transformer) + .pipe(stringifier) + .on("data", function (data) { + chunks.push(data.toString()); }) - .on('end', () => { + .on("end", () => { assert.strictEqual( - chunks.join(''), + chunks.join(""), [ - 'OMH,ONKCHhJmjadoA,D,GeACHiN,nnmiN,CGfDKB,NIl,JnnmjadnmiNL', - 'KB,dmiM,fENL,Jn,opEMIkdmiOMFckep,MIj,bgIjadnn,fENLEOMIkbhLDK', - '', - ].join('\n') - ) - }) + "OMH,ONKCHhJmjadoA,D,GeACHiN,nnmiN,CGfDKB,NIl,JnnmjadnmiNL", + "KB,dmiM,fENL,Jn,opEMIkdmiOMFckep,MIj,bgIjadnn,fENLEOMIkbhLDK", + "", + ].join("\n"), + ); + }); diff --git a/demo/ts-cjs-node16/package.json b/demo/ts-cjs-node16/package.json index 3f727a074..472412027 100644 --- a/demo/ts-cjs-node16/package.json +++ b/demo/ts-cjs-node16/package.json @@ -1,17 +1,17 @@ { "name": "csv-demo-ts-cjs-node16", - "version": "0.2.19", + "version": "0.2.21", "dependencies": { - "csv-generate": "^4.4.2", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2", - "stream-transform": "^3.3.3" + "csv-generate": "^4.5.0", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0", + "stream-transform": "^3.4.0" }, "main": "index.js", "license": "MIT", "private": true, "devDependencies": { - "typescript": "^5.6.3" + "typescript": "^5.8.3" }, "scripts": { "test": "tsc --noEmit" diff --git a/demo/ts-esm-node16/CHANGELOG.md b/demo/ts-esm-node16/CHANGELOG.md index 543532b72..78bd5a433 100644 --- a/demo/ts-esm-node16/CHANGELOG.md +++ b/demo/ts-esm-node16/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.21](https://github.com/adaltas/node-csv/compare/csv-demo-ts-module-node16@0.2.19...csv-demo-ts-module-node16@0.2.21) (2025-07-16) + +**Note:** Version bump only for package csv-demo-ts-module-node16 + +## 0.2.20 (2025-07-10) + +### Bug Fixes + +- **csv-demo-ts-cjs-node16:** upgrade module definition after latest typescript ([87fe919](https://github.com/adaltas/node-csv/commit/87fe91996fb2a8895c252177fca4f0cb59a518f9)) +- support ts node16 resolution in cjs ([#354](https://github.com/adaltas/node-csv/issues/354)) ([fa09d03](https://github.com/adaltas/node-csv/commit/fa09d03aaf0008b2790656871ca6b2c4be12d14c)) + ## [0.2.19](https://github.com/adaltas/node-csv/compare/csv-demo-ts-module-node16@0.2.18...csv-demo-ts-module-node16@0.2.19) (2024-11-21) **Note:** Version bump only for package csv-demo-ts-module-node16 diff --git a/demo/ts-esm-node16/lib/stringify-import.ts b/demo/ts-esm-node16/lib/stringify-import.ts index 64a8a2ead..5ad6b09f6 100644 --- a/demo/ts-esm-node16/lib/stringify-import.ts +++ b/demo/ts-esm-node16/lib/stringify-import.ts @@ -1,37 +1,34 @@ +import assert from "assert"; +import { Stringifier } from "csv-stringify"; -import assert from 'assert' -import { Stringifier } from 'csv-stringify'; - -(async function(){ - const {stringify} = await import('csv-stringify'); +(async function () { + const { stringify } = await import("csv-stringify"); console.log(stringify); - - let output: string = ''; + + let output: string = ""; // Create the parser const stringifier: Stringifier = stringify({ - delimiter: ':', - encoding: 'utf8' + delimiter: ":", + encoding: "utf8", }); // Use the readable stream api to consume records - stringifier.on('readable', function(){ - let record; while ((record = stringifier.read()) !== null) { - output += record + stringifier.on("readable", function () { + let record; + while ((record = stringifier.read()) !== null) { + output += record; } }); // Catch any error - stringifier.on('error', function(err){ - console.error(err.message) + stringifier.on("error", function (err) { + console.error(err.message); }); // Test that the parsed records matched what's expected - stringifier.on('end', function(){ - assert.deepStrictEqual( - output, - 'a:b:c\n1:2:3\n' - ) + stringifier.on("end", function () { + assert.deepStrictEqual(output, "a:b:c\n1:2:3\n"); }); // Write data to the stream stringifier.write(["a", "b", "c"]); stringifier.write([1, 2, 3]); // Close the readable stream stringifier.end(); -})() +})(); diff --git a/demo/ts-esm-node16/lib/stringify.ts b/demo/ts-esm-node16/lib/stringify.ts index f4cf1db94..bbe4202d1 100644 --- a/demo/ts-esm-node16/lib/stringify.ts +++ b/demo/ts-esm-node16/lib/stringify.ts @@ -1,29 +1,26 @@ +import assert from "assert"; +import { stringify, Stringifier } from "csv-stringify"; -import assert from 'assert' -import { stringify, Stringifier } from 'csv-stringify'; - -let output: string = ''; +let output: string = ""; // Create the parser const stringifier: Stringifier = stringify({ - delimiter: ':', - encoding: 'utf8' + delimiter: ":", + encoding: "utf8", }); // Use the readable stream api to consume records -stringifier.on('readable', function(){ - let record; while ((record = stringifier.read()) !== null) { - output += record +stringifier.on("readable", function () { + let record; + while ((record = stringifier.read()) !== null) { + output += record; } }); // Catch any error -stringifier.on('error', function(err){ - console.error(err.message) +stringifier.on("error", function (err) { + console.error(err.message); }); // Test that the parsed records matched what's expected -stringifier.on('end', function(){ - assert.deepStrictEqual( - output, - 'a:b:c\n1:2:3\n' - ) +stringifier.on("end", function () { + assert.deepStrictEqual(output, "a:b:c\n1:2:3\n"); }); // Write data to the stream stringifier.write(["a", "b", "c"]); diff --git a/demo/ts-esm-node16/package.json b/demo/ts-esm-node16/package.json index 70e44a160..bcfe5d34d 100644 --- a/demo/ts-esm-node16/package.json +++ b/demo/ts-esm-node16/package.json @@ -1,23 +1,23 @@ { "name": "csv-demo-ts-module-node16", - "version": "0.2.19", + "version": "0.2.21", "main": "index.js", "license": "MIT", "type": "module", "private": true, "dependencies": { - "csv-generate": "^4.4.2", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2", - "stream-transform": "^3.3.3" + "csv-generate": "^4.5.0", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0", + "stream-transform": "^3.4.0" }, "devDependencies": { - "@types/node": "^22.9.1", + "@types/node": "^22.15.30", "coffeescript": "^2.7.0", - "mocha": "^10.8.2", + "mocha": "^11.5.0", "should": "^13.2.3", "ts-node": "^10.9.2", - "typescript": "^5.6.3" + "typescript": "^5.8.3" }, "mocha": { "inline-diffs": true, diff --git a/demo/webpack-ts/CHANGELOG.md b/demo/webpack-ts/CHANGELOG.md index 41280c1c5..4e9dec120 100644 --- a/demo/webpack-ts/CHANGELOG.md +++ b/demo/webpack-ts/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.1](https://github.com/adaltas/node-csv/compare/csv-demo-webpack-ts@0.1.21...csv-demo-webpack-ts@0.2.1) (2025-07-16) + +**Note:** Version bump only for package csv-demo-webpack-ts + +## 0.2.0 (2025-07-10) + +### Features + +- **csv-demo-webpack-ts:** new demo webpack with TypeScript ([624c62d](https://github.com/adaltas/node-csv/commit/624c62d465f65a33fd43c0cf75eda1ae01388b1d)) + +### Bug Fixes + +- **csv-demo-ts-cjs-node16:** upgrade module definition after latest typescript ([87fe919](https://github.com/adaltas/node-csv/commit/87fe91996fb2a8895c252177fca4f0cb59a518f9)) +- **csv-demo-webpack-ts:** remove polyfill ([47a99bd](https://github.com/adaltas/node-csv/commit/47a99bd944d1d943e6374227dbc4e20aaa2c8c7f)) +- **csv-demo-webpack-ts:** simplify export paths ([8d63a14](https://github.com/adaltas/node-csv/commit/8d63a14313bb6b26f13fafb740cc686f1dfaa65f)) +- support ts node16 resolution in cjs ([#354](https://github.com/adaltas/node-csv/issues/354)) ([fa09d03](https://github.com/adaltas/node-csv/commit/fa09d03aaf0008b2790656871ca6b2c4be12d14c)) + ## [0.1.21](https://github.com/adaltas/node-csv/compare/csv-demo-webpack-ts@0.1.20...csv-demo-webpack-ts@0.1.21) (2024-11-21) **Note:** Version bump only for package csv-demo-webpack-ts diff --git a/demo/webpack-ts/package.json b/demo/webpack-ts/package.json index d86861b3c..88c41950c 100644 --- a/demo/webpack-ts/package.json +++ b/demo/webpack-ts/package.json @@ -1,26 +1,26 @@ { "name": "csv-demo-webpack-ts", - "version": "0.1.21", + "version": "0.2.1", "description": "", "private": true, "keywords": [], "author": "", "license": "ISC", "dependencies": { - "csv-generate": "^4.4.2", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2", + "csv-generate": "^4.5.0", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0", "http-server": "^14.1.1", - "stream-transform": "^3.3.3" + "stream-transform": "^3.4.0" }, "devDependencies": { "buffer-browserify": "^0.2.5", - "node-polyfill-webpack-plugin": "^4.0.0", + "node-polyfill-webpack-plugin": "^4.1.0", "stream-browserify": "^3.0.0", - "ts-loader": "^9.5.1", - "typescript": "^5.6.3", - "webpack": "^5.96.1", - "webpack-cli": "^5.1.4" + "ts-loader": "^9.5.2", + "typescript": "^5.8.3", + "webpack": "^5.99.9", + "webpack-cli": "^6.0.1" }, "scripts": { "build": "npx webpack --config webpack.config.js", diff --git a/demo/webpack-ts/src/generate.ts b/demo/webpack-ts/src/generate.ts index 3a5e368e2..b6690cd04 100644 --- a/demo/webpack-ts/src/generate.ts +++ b/demo/webpack-ts/src/generate.ts @@ -1,16 +1,18 @@ - -import {generate} from 'csv-generate/browser/esm'; +import { generate } from "csv-generate/browser/esm"; window.onload = () => { - const runEl = document.getElementById('run'); - const outputEl = document.getElementById('output'); - if(!runEl || !outputEl) return; + const runEl = document.getElementById("run"); + const outputEl = document.getElementById("output"); + if (!runEl || !outputEl) return; runEl.onclick = () => { - generate({ - objectMode: true, - length: 2 - }, (err, records) => { - outputEl.innerHTML = JSON.stringify(records, null, 2); - }); + generate( + { + objectMode: true, + length: 2, + }, + (err, records) => { + outputEl.innerHTML = JSON.stringify(records, null, 2); + }, + ); }; }; diff --git a/demo/webpack-ts/src/parse.ts b/demo/webpack-ts/src/parse.ts index 1f0f43afb..c750a9604 100644 --- a/demo/webpack-ts/src/parse.ts +++ b/demo/webpack-ts/src/parse.ts @@ -1,12 +1,11 @@ - -import { parse, CsvError } from 'csv-parse/browser/esm' +import { parse, CsvError } from "csv-parse/browser/esm"; window.onload = () => { - const runEl = document.getElementById('run'); - const outputEl = document.getElementById('output'); - if(!runEl || !outputEl) return; + const runEl = document.getElementById("run"); + const outputEl = document.getElementById("output"); + if (!runEl || !outputEl) return; runEl.onclick = () => { - parse('a,b,c\n1,2,3', (err: CsvError|undefined, records: any) => { + parse("a,b,c\n1,2,3", (err: CsvError | undefined, records: any) => { outputEl.innerHTML = JSON.stringify(records, null, 2); }); }; diff --git a/demo/webpack-ts/src/stringify.ts b/demo/webpack-ts/src/stringify.ts index 6d2a2f0ea..62d8f2cb0 100644 --- a/demo/webpack-ts/src/stringify.ts +++ b/demo/webpack-ts/src/stringify.ts @@ -1,13 +1,18 @@ - -import {stringify} from 'csv-stringify/browser/esm'; +import { stringify } from "csv-stringify/browser/esm"; window.onload = () => { - const runEl = document.getElementById('run'); - const outputEl = document.getElementById('output'); - if(!runEl || !outputEl) return; + const runEl = document.getElementById("run"); + const outputEl = document.getElementById("output"); + if (!runEl || !outputEl) return; runEl.onclick = () => { - stringify([['a', 'b', 'c'], [1, 2, 3]], (err, data) => { - outputEl.innerHTML = data; - }); + stringify( + [ + ["a", "b", "c"], + [1, 2, 3], + ], + (err, data) => { + outputEl.innerHTML = data; + }, + ); }; }; diff --git a/demo/webpack-ts/src/transform.ts b/demo/webpack-ts/src/transform.ts index 1d260fde8..4ce005f0c 100644 --- a/demo/webpack-ts/src/transform.ts +++ b/demo/webpack-ts/src/transform.ts @@ -1,23 +1,26 @@ - -import {transform} from 'stream-transform/browser/esm'; +import { transform } from "stream-transform/browser/esm"; window.onload = () => { - const runEl = document.getElementById('run'); - const outputEl = document.getElementById('output'); - if(!runEl || !outputEl) return; + const runEl = document.getElementById("run"); + const outputEl = document.getElementById("output"); + if (!runEl || !outputEl) return; runEl.onclick = () => { - transform([ - ['a', 'b', 'c'], - [1, 2, 3] - ], (record: string[] | number[]) => { - const el = record.shift(); - // `never` is awkward to me, without it, we got the following error: - // TS2345: Argument of type 'string | number' is not assignable to parameter of type 'never'. - // solution is mentionned here https://stackoverflow.com/questions/52423842/what-is-not-assignable-to-parameter-of-type-never-error-in-typescript - if(el !== undefined) record.push(el as never); - return record; - }, (err, records) => { - outputEl.innerHTML = JSON.stringify(records, null, 2); - }); + transform( + [ + ["a", "b", "c"], + [1, 2, 3], + ], + (record: string[] | number[]) => { + const el = record.shift(); + // `never` is awkward to me, without it, we got the following error: + // TS2345: Argument of type 'string | number' is not assignable to parameter of type 'never'. + // solution is mentionned here https://stackoverflow.com/questions/52423842/what-is-not-assignable-to-parameter-of-type-never-error-in-typescript + if (el !== undefined) record.push(el as never); + return record; + }, + (err, records) => { + outputEl.innerHTML = JSON.stringify(records, null, 2); + }, + ); }; }; diff --git a/demo/webpack/CHANGELOG.md b/demo/webpack/CHANGELOG.md index 6a88c70bf..7fd54e0d0 100644 --- a/demo/webpack/CHANGELOG.md +++ b/demo/webpack/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.1](https://github.com/adaltas/node-csv/compare/csv-demo-webpack@0.1.23...csv-demo-webpack@0.2.1) (2025-07-16) + +**Note:** Version bump only for package csv-demo-webpack + +## 0.2.0 (2025-07-10) + +### Features + +- **csv-demo-webpack:** split usages by packages ([214c759](https://github.com/adaltas/node-csv/commit/214c75980d61bf96ec1d6892858887ba29235987)) + +### Bug Fixes + +- correct exports in package.json with webpack ([154eafb](https://github.com/adaltas/node-csv/commit/154eafbac866eb4499a0d392f8dcd057695c2586)) +- **csv-demo-webpack-ts:** simplify export paths ([8d63a14](https://github.com/adaltas/node-csv/commit/8d63a14313bb6b26f13fafb740cc686f1dfaa65f)) +- **csv-demo-webpack:** start with version 0.0.0 ([3369efa](https://github.com/adaltas/node-csv/commit/3369efa09831fabb57fef9c94cd4ca14e0b05981)) +- support ts node16 resolution in cjs ([#354](https://github.com/adaltas/node-csv/issues/354)) ([fa09d03](https://github.com/adaltas/node-csv/commit/fa09d03aaf0008b2790656871ca6b2c4be12d14c)) + ## [0.1.23](https://github.com/adaltas/node-csv/compare/csv-demo-webpack@0.1.22...csv-demo-webpack@0.1.23) (2024-11-21) **Note:** Version bump only for package csv-demo-webpack diff --git a/demo/webpack/package.json b/demo/webpack/package.json index 8bccab5a3..c7fc14e61 100644 --- a/demo/webpack/package.json +++ b/demo/webpack/package.json @@ -1,6 +1,6 @@ { "name": "csv-demo-webpack", - "version": "0.1.23", + "version": "0.2.1", "description": "", "private": true, "scripts": { @@ -12,16 +12,16 @@ "author": "", "license": "ISC", "devDependencies": { - "webpack": "^5.96.1", - "webpack-cli": "^5.1.4" + "webpack": "^5.99.9", + "webpack-cli": "^6.0.1" }, "dependencies": { - "csv": "^6.3.11", - "csv-generate": "^4.4.2", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2", + "csv": "^6.4.1", + "csv-generate": "^4.5.0", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0", "http-server": "^14.1.1", "stream-browserify": "^3.0.0", - "stream-transform": "^3.3.3" + "stream-transform": "^3.4.0" } } diff --git a/eslint.config.js b/eslint.config.js index 6168f8a94..c2fb11cb8 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,7 +1,9 @@ import globals from "globals"; import js from "@eslint/js"; +import ts from "typescript-eslint"; import mocha from "eslint-plugin-mocha"; import prettier from "eslint-plugin-prettier/recommended"; +// const __dirname = new URL(".", import.meta.url).pathname; export default [ { @@ -11,8 +13,17 @@ export default [ languageOptions: { globals: { ...globals.node } }, }, js.configs.recommended, - mocha.configs.flat.recommended, + ...ts.configs.recommended, + mocha.configs.recommended, prettier, + // { + // files: ["**/*.ts"], + // languageOptions: { + // parserOptions: { + // project: true, + // }, + // }, + // }, { files: ["demo/webpack/**/*.js"], languageOptions: { @@ -21,4 +32,24 @@ export default [ }, }, }, + { + files: ["**/test/**/*.js", "**/test/**/*.ts"], + languageOptions: { + // globals: { + // ...globals.mocha, + // }, + // https://typescript-eslint.io/blog/parser-options-project-true/ + // parserOptions: { + // project: ["./packages/csv/tsconfig.json"], + // tsconfigRootDir: __dirname, + // }, + // parserOptions: { + // project: true, + // tsconfigRootDir: __dirname, + // }, + }, + rules: { + "@typescript-eslint/no-unused-expressions": 0, // Applies to both js and ts + }, + }, ]; diff --git a/package-lock.json b/package-lock.json index cede13400..5c7426de9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,15 +4,20 @@ "requires": true, "packages": { "": { - "hasInstallScript": true, "devDependencies": { - "@commitlint/cli": "^19.6.0", - "@commitlint/config-conventional": "^19.6.0", + "@commitlint/cli": "^19.8.1", + "@commitlint/config-conventional": "^19.8.1", + "@eslint/js": "^9.28.0", "cz-conventional-changelog": "^3.3.0", - "glob": "^11.0.0", + "eslint": "^9.28.0", + "eslint-config-prettier": "^10.1.5", + "eslint-plugin-mocha": "^11.1.0", + "eslint-plugin-prettier": "^5.4.1", + "glob": "^11.0.2", "husky": "^9.1.7", - "lerna": "^8.1.9", - "lint-staged": "^15.2.10" + "lerna": "^8.2.2", + "lint-staged": "^16.1.0", + "typescript-eslint": "^8.33.1" }, "workspaces": { "packages": [ @@ -27,97 +32,97 @@ }, "demo/browser": { "name": "csv-demo-browser", - "version": "0.1.21", + "version": "0.2.1", "license": "MIT", "dependencies": { - "csv": "^6.3.11", - "csv-generate": "^4.4.2", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2", - "express": "^4.21.1", - "stream-transform": "^3.3.3" + "csv": "^6.4.1", + "csv-generate": "^4.5.0", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0", + "express": "^5.1.0", + "stream-transform": "^3.4.0" } }, "demo/cjs": { "name": "csv-demo-cjs", - "version": "0.2.19", + "version": "0.3.1", "license": "MIT", "dependencies": { - "csv": "^6.3.11", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2" + "csv": "^6.4.1", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0" }, "devDependencies": { - "@types/node": "^22.9.1", + "@types/node": "^22.15.30", "coffeescript": "^2.7.0", - "mocha": "^10.8.2", + "mocha": "^11.5.0", "should": "^13.2.3", "ts-node": "^10.9.2", - "typescript": "^5.6.3" + "typescript": "^5.8.3" } }, "demo/eslint": { "name": "csv-demo-eslint", - "version": "0.1.23", + "version": "0.2.0", "license": "MIT", "dependencies": { - "csv-stringify": "^6.5.2" + "csv-stringify": "^6.6.0" }, "devDependencies": { - "eslint": "^9.15.0", + "eslint": "^9.28.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-plugin-import": "^2.31.0" } }, "demo/esm": { "name": "csv-demo-esm", - "version": "0.0.33", + "version": "0.0.35", "license": "MIT", "dependencies": { - "csv": "^6.3.11", - "csv-parse": "^5.6.0" + "csv": "^6.4.1", + "csv-parse": "^6.1.0" }, "devDependencies": { "coffeescript": "^2.7.0", - "mocha": "^10.8.2", + "mocha": "^11.5.0", "should": "^13.2.3" } }, "demo/issues-cjs": { "name": "csv-issues-cjs", - "version": "0.2.8", + "version": "0.3.1", "license": "MIT", "dependencies": { - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2" + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0" }, "devDependencies": { "coffeescript": "^2.7.0", - "mocha": "^10.8.2", + "mocha": "^11.5.0", "should": "^13.2.3" } }, "demo/issues-esm": { "name": "csv-issues-esm", - "version": "0.4.0", + "version": "0.5.1", "license": "MIT", "dependencies": { - "csv-generate": "^4.4.2", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2", - "dedent": "^1.5.3", + "csv-generate": "^4.5.0", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0", + "dedent": "^1.6.0", "desm": "^1.3.1", - "duckdb-async": "^1.1.3" + "duckdb-async": "^1.2.1" }, "devDependencies": { "coffeescript": "^2.7.0", "dirname-filename-esm": "^1.1.2", - "mocha": "^10.8.2", + "mocha": "^11.5.0", "should": "^13.2.3" } }, "demo/issues-esm/node_modules/dedent": { - "version": "1.5.3", + "version": "1.6.0", "license": "MIT", "peerDependencies": { "babel-plugin-macros": "^3.1.0" @@ -130,95 +135,95 @@ }, "demo/ts-cjs-node16": { "name": "csv-demo-ts-cjs-node16", - "version": "0.2.19", + "version": "0.2.21", "license": "MIT", "dependencies": { - "csv-generate": "^4.4.2", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2", - "stream-transform": "^3.3.3" + "csv-generate": "^4.5.0", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0", + "stream-transform": "^3.4.0" }, "devDependencies": { - "typescript": "^5.6.3" + "typescript": "^5.8.3" } }, "demo/ts-esm-node16": { "name": "csv-demo-ts-module-node16", - "version": "0.2.19", + "version": "0.2.21", "license": "MIT", "dependencies": { - "csv-generate": "^4.4.2", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2", - "stream-transform": "^3.3.3" + "csv-generate": "^4.5.0", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0", + "stream-transform": "^3.4.0" }, "devDependencies": { - "@types/node": "^22.9.1", + "@types/node": "^22.15.30", "coffeescript": "^2.7.0", - "mocha": "^10.8.2", + "mocha": "^11.5.0", "should": "^13.2.3", "ts-node": "^10.9.2", - "typescript": "^5.6.3" + "typescript": "^5.8.3" } }, "demo/webpack": { "name": "csv-demo-webpack", - "version": "0.1.23", + "version": "0.2.1", "license": "ISC", "dependencies": { - "csv": "^6.3.11", - "csv-generate": "^4.4.2", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2", + "csv": "^6.4.1", + "csv-generate": "^4.5.0", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0", "http-server": "^14.1.1", "stream-browserify": "^3.0.0", - "stream-transform": "^3.3.3" + "stream-transform": "^3.4.0" }, "devDependencies": { - "webpack": "^5.96.1", - "webpack-cli": "^5.1.4" + "webpack": "^5.99.9", + "webpack-cli": "^6.0.1" } }, "demo/webpack-ts": { "name": "csv-demo-webpack-ts", - "version": "0.1.21", + "version": "0.2.1", "license": "ISC", "dependencies": { - "csv-generate": "^4.4.2", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2", + "csv-generate": "^4.5.0", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0", "http-server": "^14.1.1", - "stream-transform": "^3.3.3" + "stream-transform": "^3.4.0" }, "devDependencies": { "buffer-browserify": "^0.2.5", - "node-polyfill-webpack-plugin": "^4.0.0", + "node-polyfill-webpack-plugin": "^4.1.0", "stream-browserify": "^3.0.0", - "ts-loader": "^9.5.1", - "typescript": "^5.6.3", - "webpack": "^5.96.1", - "webpack-cli": "^5.1.4" + "ts-loader": "^9.5.2", + "typescript": "^5.8.3", + "webpack": "^5.99.9", + "webpack-cli": "^6.0.1" } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "dev": true, "license": "MIT", "engines": { @@ -226,18 +231,18 @@ } }, "node_modules/@commitlint/cli": { - "version": "19.6.0", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.6.0.tgz", - "integrity": "sha512-v17BgGD9w5KnthaKxXnEg6KLq6DYiAxyiN44TpiRtqyW8NSq+Kx99mkEG8Qo6uu6cI5eMzMojW2muJxjmPnF8w==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.8.1.tgz", + "integrity": "sha512-LXUdNIkspyxrlV6VDHWBmCZRtkEVRpBKxi2Gtw3J54cGWhLCTouVD/Q6ZSaSvd2YaDObWK8mDjrz3TIKtaQMAA==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/format": "^19.5.0", - "@commitlint/lint": "^19.6.0", - "@commitlint/load": "^19.5.0", - "@commitlint/read": "^19.5.0", - "@commitlint/types": "^19.5.0", - "tinyexec": "^0.3.0", + "@commitlint/format": "^19.8.1", + "@commitlint/lint": "^19.8.1", + "@commitlint/load": "^19.8.1", + "@commitlint/read": "^19.8.1", + "@commitlint/types": "^19.8.1", + "tinyexec": "^1.0.0", "yargs": "^17.0.0" }, "bin": { @@ -248,13 +253,13 @@ } }, "node_modules/@commitlint/config-conventional": { - "version": "19.6.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-19.6.0.tgz", - "integrity": "sha512-DJT40iMnTYtBtUfw9ApbsLZFke1zKh6llITVJ+x9mtpHD08gsNXaIRqHTmwTZL3dNX5+WoyK7pCN/5zswvkBCQ==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-19.8.1.tgz", + "integrity": "sha512-/AZHJL6F6B/G959CsMAzrPKKZjeEiAVifRyEwXxcT6qtqbPwGw+iQxmNS+Bu+i09OCtdNRW6pNpBvgPrtMr9EQ==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.5.0", + "@commitlint/types": "^19.8.1", "conventional-changelog-conventionalcommits": "^7.0.2" }, "engines": { @@ -262,13 +267,13 @@ } }, "node_modules/@commitlint/config-validator": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.5.0.tgz", - "integrity": "sha512-CHtj92H5rdhKt17RmgALhfQt95VayrUo2tSqY9g2w+laAXyk7K/Ef6uPm9tn5qSIwSmrLjKaXK9eiNuxmQrDBw==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.8.1.tgz", + "integrity": "sha512-0jvJ4u+eqGPBIzzSdqKNX1rvdbSU1lPNYlfQQRIFnBgLy26BtC0cFnr7c/AyuzExMxWsMOte6MkTi9I3SQ3iGQ==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.5.0", + "@commitlint/types": "^19.8.1", "ajv": "^8.11.0" }, "engines": { @@ -276,13 +281,13 @@ } }, "node_modules/@commitlint/ensure": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-19.5.0.tgz", - "integrity": "sha512-Kv0pYZeMrdg48bHFEU5KKcccRfKmISSm9MvgIgkpI6m+ohFTB55qZlBW6eYqh/XDfRuIO0x4zSmvBjmOwWTwkg==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-19.8.1.tgz", + "integrity": "sha512-mXDnlJdvDzSObafjYrOSvZBwkD01cqB4gbnnFuVyNpGUM5ijwU/r/6uqUmBXAAOKRfyEjpkGVZxaDsCVnHAgyw==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.5.0", + "@commitlint/types": "^19.8.1", "lodash.camelcase": "^4.3.0", "lodash.kebabcase": "^4.1.1", "lodash.snakecase": "^4.1.1", @@ -294,9 +299,9 @@ } }, "node_modules/@commitlint/execute-rule": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.5.0.tgz", - "integrity": "sha512-aqyGgytXhl2ejlk+/rfgtwpPexYyri4t8/n4ku6rRJoRhGZpLFMqrZ+YaubeGysCP6oz4mMA34YSTaSOKEeNrg==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.8.1.tgz", + "integrity": "sha512-YfJyIqIKWI64Mgvn/sE7FXvVMQER/Cd+s3hZke6cI1xgNT/f6ZAz5heND0QtffH+KbcqAwXDEE1/5niYayYaQA==", "dev": true, "license": "MIT", "engines": { @@ -304,13 +309,13 @@ } }, "node_modules/@commitlint/format": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-19.5.0.tgz", - "integrity": "sha512-yNy088miE52stCI3dhG/vvxFo9e4jFkU1Mj3xECfzp/bIS/JUay4491huAlVcffOoMK1cd296q0W92NlER6r3A==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-19.8.1.tgz", + "integrity": "sha512-kSJj34Rp10ItP+Eh9oCItiuN/HwGQMXBnIRk69jdOwEW9llW9FlyqcWYbHPSGofmjsqeoxa38UaEA5tsbm2JWw==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.5.0", + "@commitlint/types": "^19.8.1", "chalk": "^5.3.0" }, "engines": { @@ -318,13 +323,13 @@ } }, "node_modules/@commitlint/is-ignored": { - "version": "19.6.0", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.6.0.tgz", - "integrity": "sha512-Ov6iBgxJQFR9koOupDPHvcHU9keFupDgtB3lObdEZDroiG4jj1rzky60fbQozFKVYRTUdrBGICHG0YVmRuAJmw==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.8.1.tgz", + "integrity": "sha512-AceOhEhekBUQ5dzrVhDDsbMaY5LqtN8s1mqSnT2Kz1ERvVZkNihrs3Sfk1Je/rxRNbXYFzKZSHaPsEJJDJV8dg==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.5.0", + "@commitlint/types": "^19.8.1", "semver": "^7.6.0" }, "engines": { @@ -332,35 +337,35 @@ } }, "node_modules/@commitlint/lint": { - "version": "19.6.0", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.6.0.tgz", - "integrity": "sha512-LRo7zDkXtcIrpco9RnfhOKeg8PAnE3oDDoalnrVU/EVaKHYBWYL1DlRR7+3AWn0JiBqD8yKOfetVxJGdEtZ0tg==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.8.1.tgz", + "integrity": "sha512-52PFbsl+1EvMuokZXLRlOsdcLHf10isTPlWwoY1FQIidTsTvjKXVXYb7AvtpWkDzRO2ZsqIgPK7bI98x8LRUEw==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/is-ignored": "^19.6.0", - "@commitlint/parse": "^19.5.0", - "@commitlint/rules": "^19.6.0", - "@commitlint/types": "^19.5.0" + "@commitlint/is-ignored": "^19.8.1", + "@commitlint/parse": "^19.8.1", + "@commitlint/rules": "^19.8.1", + "@commitlint/types": "^19.8.1" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/load": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.5.0.tgz", - "integrity": "sha512-INOUhkL/qaKqwcTUvCE8iIUf5XHsEPCLY9looJ/ipzi7jtGhgmtH7OOFiNvwYgH7mA8osUWOUDV8t4E2HAi4xA==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.8.1.tgz", + "integrity": "sha512-9V99EKG3u7z+FEoe4ikgq7YGRCSukAcvmKQuTtUyiYPnOd9a2/H9Ak1J9nJA1HChRQp9OA/sIKPugGS+FK/k1A==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/config-validator": "^19.5.0", - "@commitlint/execute-rule": "^19.5.0", - "@commitlint/resolve-extends": "^19.5.0", - "@commitlint/types": "^19.5.0", + "@commitlint/config-validator": "^19.8.1", + "@commitlint/execute-rule": "^19.8.1", + "@commitlint/resolve-extends": "^19.8.1", + "@commitlint/types": "^19.8.1", "chalk": "^5.3.0", "cosmiconfig": "^9.0.0", - "cosmiconfig-typescript-loader": "^5.0.0", + "cosmiconfig-typescript-loader": "^6.1.0", "lodash.isplainobject": "^4.0.6", "lodash.merge": "^4.6.2", "lodash.uniq": "^4.5.0" @@ -370,9 +375,9 @@ } }, "node_modules/@commitlint/message": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.5.0.tgz", - "integrity": "sha512-R7AM4YnbxN1Joj1tMfCyBryOC5aNJBdxadTZkuqtWi3Xj0kMdutq16XQwuoGbIzL2Pk62TALV1fZDCv36+JhTQ==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.8.1.tgz", + "integrity": "sha512-+PMLQvjRXiU+Ae0Wc+p99EoGEutzSXFVwQfa3jRNUZLNW5odZAyseb92OSBTKCu+9gGZiJASt76Cj3dLTtcTdg==", "dev": true, "license": "MIT", "engines": { @@ -380,13 +385,13 @@ } }, "node_modules/@commitlint/parse": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-19.5.0.tgz", - "integrity": "sha512-cZ/IxfAlfWYhAQV0TwcbdR1Oc0/r0Ik1GEessDJ3Lbuma/MRO8FRQX76eurcXtmhJC//rj52ZSZuXUg0oIX0Fw==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-19.8.1.tgz", + "integrity": "sha512-mmAHYcMBmAgJDKWdkjIGq50X4yB0pSGpxyOODwYmoexxxiUCy5JJT99t1+PEMK7KtsCtzuWYIAXYAiKR+k+/Jw==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.5.0", + "@commitlint/types": "^19.8.1", "conventional-changelog-angular": "^7.0.0", "conventional-commits-parser": "^5.0.0" }, @@ -395,31 +400,31 @@ } }, "node_modules/@commitlint/read": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.5.0.tgz", - "integrity": "sha512-TjS3HLPsLsxFPQj6jou8/CZFAmOP2y+6V4PGYt3ihbQKTY1Jnv0QG28WRKl/d1ha6zLODPZqsxLEov52dhR9BQ==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.8.1.tgz", + "integrity": "sha512-03Jbjb1MqluaVXKHKRuGhcKWtSgh3Jizqy2lJCRbRrnWpcM06MYm8th59Xcns8EqBYvo0Xqb+2DoZFlga97uXQ==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/top-level": "^19.5.0", - "@commitlint/types": "^19.5.0", + "@commitlint/top-level": "^19.8.1", + "@commitlint/types": "^19.8.1", "git-raw-commits": "^4.0.0", "minimist": "^1.2.8", - "tinyexec": "^0.3.0" + "tinyexec": "^1.0.0" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/resolve-extends": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.5.0.tgz", - "integrity": "sha512-CU/GscZhCUsJwcKTJS9Ndh3AKGZTNFIOoQB2n8CmFnizE0VnEuJoum+COW+C1lNABEeqk6ssfc1Kkalm4bDklA==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.8.1.tgz", + "integrity": "sha512-GM0mAhFk49I+T/5UCYns5ayGStkTt4XFFrjjf0L4S26xoMTSkdCf9ZRO8en1kuopC4isDFuEm7ZOm/WRVeElVg==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/config-validator": "^19.5.0", - "@commitlint/types": "^19.5.0", + "@commitlint/config-validator": "^19.8.1", + "@commitlint/types": "^19.8.1", "global-directory": "^4.0.1", "import-meta-resolve": "^4.0.0", "lodash.mergewith": "^4.6.2", @@ -430,25 +435,25 @@ } }, "node_modules/@commitlint/rules": { - "version": "19.6.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.6.0.tgz", - "integrity": "sha512-1f2reW7lbrI0X0ozZMesS/WZxgPa4/wi56vFuJENBmed6mWq5KsheN/nxqnl/C23ioxpPO/PL6tXpiiFy5Bhjw==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.8.1.tgz", + "integrity": "sha512-Hnlhd9DyvGiGwjfjfToMi1dsnw1EXKGJNLTcsuGORHz6SS9swRgkBsou33MQ2n51/boIDrbsg4tIBbRpEWK2kw==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/ensure": "^19.5.0", - "@commitlint/message": "^19.5.0", - "@commitlint/to-lines": "^19.5.0", - "@commitlint/types": "^19.5.0" + "@commitlint/ensure": "^19.8.1", + "@commitlint/message": "^19.8.1", + "@commitlint/to-lines": "^19.8.1", + "@commitlint/types": "^19.8.1" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/to-lines": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-19.5.0.tgz", - "integrity": "sha512-R772oj3NHPkodOSRZ9bBVNq224DOxQtNef5Pl8l2M8ZnkkzQfeSTr4uxawV2Sd3ui05dUVzvLNnzenDBO1KBeQ==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-19.8.1.tgz", + "integrity": "sha512-98Mm5inzbWTKuZQr2aW4SReY6WUukdWXuZhrqf1QdKPZBCCsXuG87c+iP0bwtD6DBnmVVQjgp4whoHRVixyPBg==", "dev": true, "license": "MIT", "engines": { @@ -456,9 +461,9 @@ } }, "node_modules/@commitlint/top-level": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-19.5.0.tgz", - "integrity": "sha512-IP1YLmGAk0yWrImPRRc578I3dDUI5A2UBJx9FbSOjxe9sTlzFiwVJ+zeMLgAtHMtGZsC8LUnzmW1qRemkFU4ng==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-19.8.1.tgz", + "integrity": "sha512-Ph8IN1IOHPSDhURCSXBz44+CIu+60duFwRsg6HqaISFHQHbmBtxVw4ZrFNIYUzEP7WwrNPxa2/5qJ//NK1FGcw==", "dev": true, "license": "MIT", "dependencies": { @@ -469,9 +474,9 @@ } }, "node_modules/@commitlint/types": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.5.0.tgz", - "integrity": "sha512-DSHae2obMSMkAtTBSOulg5X7/z+rGLxcXQIkg3OmWvY6wifojge5uVMydfhUvs7yQj+V7jNmRZ2Xzl8GJyqRgg==", + "version": "19.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.8.1.tgz", + "integrity": "sha512-/yCrWGCoA1SVKOks25EGadP9Pnj0oAIHGpl2wH2M2Y46dPM2ueb8wyCVOD7O3WCTkaJ0IkKvzhl1JY7+uCT2Dw==", "dev": true, "license": "MIT", "dependencies": { @@ -496,30 +501,30 @@ } }, "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", + "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": ">=14.17.0" } }, "node_modules/@emnapi/core": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.3.1.tgz", - "integrity": "sha512-pVGjBIt1Y6gg3EJN8jTcfpP/+uuRksIo055oE/OBkDNcjZqVbfkWCksG1Jp4yZnj3iKWyWX8fdG/j6UDYPbFog==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", + "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", "dev": true, "license": "MIT", "dependencies": { - "@emnapi/wasi-threads": "1.0.1", + "@emnapi/wasi-threads": "1.0.2", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", - "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", + "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", "dev": true, "license": "MIT", "dependencies": { @@ -527,218 +532,612 @@ } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", - "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz", + "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", "dev": true, "license": "MIT", "dependencies": { "tslib": "^2.4.0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=18" } }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/@esbuild/android-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "cpu": [ + "arm" + ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "node_modules/@esbuild/android-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@eslint/config-array": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", - "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", + "node_modules/@esbuild/android-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.4", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "*" + "node": ">=18" } }, - "node_modules/@eslint/core": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", - "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", - "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@esbuild/linux-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "cpu": [ + "ia32" + ], "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "*" + "node": ">=18" } }, - "node_modules/@eslint/js": { - "version": "9.15.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz", - "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "cpu": [ + "loong64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "cpu": [ + "mips64el" + ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/plugin-kit": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", - "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "levn": "^0.4.1" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "license": "MIT" - }, - "node_modules/@humanfs/core": { + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", + "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", + "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", + "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/js": { + "version": "9.28.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz", + "integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", + "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.14.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT" + }, + "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", @@ -791,9 +1190,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", - "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -917,6 +1316,18 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@isaacs/string-locale-compare": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", @@ -938,9 +1349,9 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, "license": "MIT", "dependencies": { @@ -1024,9 +1435,9 @@ } }, "node_modules/@lerna/create": { - "version": "8.1.9", - "resolved": "https://registry.npmjs.org/@lerna/create/-/create-8.1.9.tgz", - "integrity": "sha512-DPnl5lPX4v49eVxEbJnAizrpMdMTBz1qykZrAbBul9rfgk531v8oAt+Pm6O/rpAleRombNM7FJb5rYGzBJatOQ==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@lerna/create/-/create-8.2.2.tgz", + "integrity": "sha512-1yn1MvWn2Yz0SFgTTQnef2m1YedF7KwqLLVIOrGkgQrkVHzsveAIk1A1RcRa2yyUh+siKI1YcJ7lUZIEt+qQ3Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1035,7 +1446,7 @@ "@npmcli/run-script": "8.1.0", "@nx/devkit": ">=17.1.2 < 21", "@octokit/plugin-enterprise-rest": "6.0.1", - "@octokit/rest": "19.0.11", + "@octokit/rest": "20.1.2", "aproba": "2.0.0", "byte-size": "8.1.1", "chalk": "4.1.0", @@ -1088,7 +1499,6 @@ "slash": "^3.0.0", "ssri": "^10.0.6", "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", "strong-log-transformer": "2.1.0", "tar": "6.2.1", "temp-dir": "1.0.0", @@ -1122,17 +1532,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@lerna/create/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/@lerna/create/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -1166,9 +1565,9 @@ } }, "node_modules/@lerna/create/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", "dev": true, "license": "MIT", "dependencies": { @@ -1208,152 +1607,110 @@ "license": "ISC" }, "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-2.0.0.tgz", + "integrity": "sha512-llMXd39jtP0HpQLVI37Bf1m2ADlEb35GYSh1SDSLsBhR+5iCxiNGlT31yqbNtVHygHAtMy6dWFERpU2JgufhPg==", "license": "BSD-3-Clause", "dependencies": { + "consola": "^3.2.3", "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", + "https-proxy-agent": "^7.0.5", "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" + "nopt": "^8.0.0", + "semver": "^7.5.3", + "tar": "^7.4.0" }, "bin": { "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "license": "ISC" - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", - "dependencies": { - "debug": "4" }, "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node": ">=18" } }, - "node_modules/@mapbox/node-pre-gyp/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/@mapbox/node-pre-gyp/node_modules/abbrev": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@mapbox/node-pre-gyp/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, + "node_modules/@mapbox/node-pre-gyp/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">= 6" + "node": ">=18" } }, - "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "node_modules/@mapbox/node-pre-gyp/node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", "license": "MIT", "dependencies": { - "semver": "^6.0.0" + "minipass": "^7.1.2" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 18" } }, - "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", + "node_modules/@mapbox/node-pre-gyp/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "license": "MIT", "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" + "mkdirp": "dist/cjs/src/bin.js" }, "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", "license": "ISC", "dependencies": { - "abbrev": "1" + "abbrev": "^3.0.0" }, "bin": { "nopt": "bin/nopt.js" }, "engines": { - "node": ">=6" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@mapbox/node-pre-gyp/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "node_modules/@mapbox/node-pre-gyp/node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", "license": "ISC", "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=18" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/@napi-rs/wasm-runtime": { @@ -1473,6 +1830,16 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/@npmcli/arborist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@npmcli/arborist/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -1592,6 +1959,16 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/@npmcli/map-workspaces/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@npmcli/map-workspaces/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -1693,16 +2070,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/@npmcli/move-file/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/@npmcli/move-file/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -1724,18 +2091,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@npmcli/move-file/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@npmcli/move-file/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -1791,6 +2146,16 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/@npmcli/package-json/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@npmcli/package-json/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -1968,9 +2333,9 @@ } }, "node_modules/@nx/devkit": { - "version": "20.1.2", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.1.2.tgz", - "integrity": "sha512-MTEWiEST7DhzZ2QmrixLnHfYVDZk7QN9omLL8m+5Etcn/3ZKa1aAo9Amd2MkUM+0MPoTKnxoGdw0fQUpAy21Mg==", + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.8.2.tgz", + "integrity": "sha512-rr9p2/tZDQivIpuBUpZaFBK6bZ+b5SAjZk75V4tbCUqGW3+5OPuVvBPm+X+7PYwUF6rwSpewxkjWNeGskfCe+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1987,6 +2352,16 @@ "nx": ">= 19 <= 21" } }, + "node_modules/@nx/devkit/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@nx/devkit/node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -2014,9 +2389,9 @@ } }, "node_modules/@nx/nx-darwin-arm64": { - "version": "20.1.2", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.1.2.tgz", - "integrity": "sha512-PJ91TQhd28kitDBubKUOXMYvrtSDrG+rr8MsIe9cHo1CvU9smcGVBwuHBxniq0DXsyOX/5GL6ngq7hjN2nQ3XQ==", + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.8.2.tgz", + "integrity": "sha512-t+bmCn6sRPNGU6hnSyWNvbQYA/KgsxGZKYlaCLRwkNhI2akModcBUqtktJzCKd1XHDqs6EkEFBWjFr8/kBEkSg==", "cpu": [ "arm64" ], @@ -2031,9 +2406,9 @@ } }, "node_modules/@nx/nx-darwin-x64": { - "version": "20.1.2", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-20.1.2.tgz", - "integrity": "sha512-1fopau7nxIhTF26vDTIzMxl15AtW4FvUSdy+r1mNRKrKyjjpqnlu00SQBW7JzGV0agDD1B/61yYei5Q2aMOt7Q==", + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-20.8.2.tgz", + "integrity": "sha512-pt/wmDLM31Es8/EzazlyT5U+ou2l60rfMNFGCLqleHEQ0JUTc0KWnOciBLbHIQFiPsCQZJFEKyfV5V/ncePmmw==", "cpu": [ "x64" ], @@ -2048,9 +2423,9 @@ } }, "node_modules/@nx/nx-freebsd-x64": { - "version": "20.1.2", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-20.1.2.tgz", - "integrity": "sha512-55YgIp3v4zz7xMzJO93dtglbOTER2XdS6jrCt8GbKaWGFl5drRrBoNGONtiGNU7C3hLx1VsorbynCkJT18PjKQ==", + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-20.8.2.tgz", + "integrity": "sha512-joZxFbgJfkHkB9uMIJr73Gpnm9pnpvr0XKGbWC409/d2x7q1qK77tKdyhGm+A3+kaZFwstNVPmCUtUwJYyU6LA==", "cpu": [ "x64" ], @@ -2065,9 +2440,9 @@ } }, "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "20.1.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-20.1.2.tgz", - "integrity": "sha512-sMhNA8uAV43UYVEXEa8TZ8Fjpom4CGq1umTptEGOF4TTtdNn2AUBreg+0bVODM8MMSzRWGI1VbkZzHESnAPwqw==", + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-20.8.2.tgz", + "integrity": "sha512-98O/qsxn4vIMPY/FyzvmVrl7C5yFhCUVk0/4PF+PA2SvtQ051L1eMRY6bq/lb69qfN6szJPZ41PG5mPx0NeLZw==", "cpu": [ "arm" ], @@ -2082,9 +2457,9 @@ } }, "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "20.1.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-20.1.2.tgz", - "integrity": "sha512-bsevarNHglaYLmIvPNQOdHrBnBgaW3EOUM0flwaXdWuZbL1bWx8GoVwHp9yJpZOAOfIF/Nhq5iTpaZB2nYFrAA==", + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-20.8.2.tgz", + "integrity": "sha512-h6a+HxwfSpxsi4KpxGgPh9GDBmD2E+XqGCdfYpobabxqEBvlnIlJyuDhlRR06cTWpuNXHpRdrVogmV6m/YbtDg==", "cpu": [ "arm64" ], @@ -2099,9 +2474,9 @@ } }, "node_modules/@nx/nx-linux-arm64-musl": { - "version": "20.1.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-20.1.2.tgz", - "integrity": "sha512-GFZTptkhZPL/iZ3tYDmspIcPEaXyy/L/o59gyp33GoFAAyDhiXIF7J1Lz81Xn8VKrX6TvEY8/9qSh86pb7qzDQ==", + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-20.8.2.tgz", + "integrity": "sha512-4Ev+jM0VAxDHV/dFgMXjQTCXS4I8W4oMe7FSkXpG8RUn6JK659DC8ExIDPoGIh+Cyqq6r6mw1CSia+ciQWICWQ==", "cpu": [ "arm64" ], @@ -2116,9 +2491,9 @@ } }, "node_modules/@nx/nx-linux-x64-gnu": { - "version": "20.1.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-20.1.2.tgz", - "integrity": "sha512-yqEW/iglKT4d9lgfnwSNhmDzPxCkRhtdmZqOYpGDM0eZFwYwJF+WRGjW8xIqMj8PA1yrGItzXZOmyFjJqHAF2w==", + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-20.8.2.tgz", + "integrity": "sha512-nR0ev+wxu+nQYRd7bhqggOxK7UfkV6h+Ko1mumUFyrM5GvPpz/ELhjJFSnMcOkOMcvH0b6G5uTBJvN1XWCkbmg==", "cpu": [ "x64" ], @@ -2133,9 +2508,9 @@ } }, "node_modules/@nx/nx-linux-x64-musl": { - "version": "20.1.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-20.1.2.tgz", - "integrity": "sha512-SP6PpWT4cQVrC4WJQdpfADrYJQzkbhgmcGleWbpr7II1HJgOsAcvoDwQGpPQX+3Wo+VBiNecvUAOzacMQkXPGw==", + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-20.8.2.tgz", + "integrity": "sha512-ost41l5yc2aq2Gc9bMMpaPi/jkXqbXEMEPHrxWKuKmaek3K2zbVDQzvBBNcQKxf/mlCsrqN4QO0mKYSRRqag5A==", "cpu": [ "x64" ], @@ -2150,9 +2525,9 @@ } }, "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "20.1.2", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-20.1.2.tgz", - "integrity": "sha512-JZQx9gr39LY3D7uleiXlpxUsavuOrOQNBocwKHkAMnykaT/e1VCxTnm/hk+2b4foWwfURTqoRiFEba70iiCdYg==", + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-20.8.2.tgz", + "integrity": "sha512-0SEOqT/daBG5WtM9vOGilrYaAuf1tiALdrFavY62+/arXYxXemUKmRI5qoKDTnvoLMBGkJs6kxhMO5b7aUXIvQ==", "cpu": [ "arm64" ], @@ -2167,9 +2542,9 @@ } }, "node_modules/@nx/nx-win32-x64-msvc": { - "version": "20.1.2", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-20.1.2.tgz", - "integrity": "sha512-6GmT8iswDiCvJaCtW9DpWeAQmLS/kfAuRLYBisfzlONuLPaDdjhgVIxZBqqUSFfclwcVz+NhIOGvdr0aGFZCtQ==", + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-20.8.2.tgz", + "integrity": "sha512-iIsY+tVqes/NOqTbJmggL9Juie/iaDYlWgXA9IUv88FE9thqWKhVj4/tCcPjsOwzD+1SVna3YISEEFsx5UV4ew==", "cpu": [ "x64" ], @@ -2184,68 +2559,67 @@ } }, "node_modules/@octokit/auth-token": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz", - "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/core": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz", - "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.1.tgz", + "integrity": "sha512-dKYCMuPO1bmrpuogcjQ8z7ICCH3FP6WmxpwC03yjzGfZhj9fTJg6+bS1+UAplekbN2C+M61UNllGOOoAfGCrdQ==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.4.1", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/endpoint": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz", - "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==", + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", + "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", + "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/graphql": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", - "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz", + "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", + "@octokit/request": "^8.4.1", + "@octokit/types": "^13.0.0", "universal-user-agent": "^6.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/openapi-types": { - "version": "18.1.1", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.1.1.tgz", - "integrity": "sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==", + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", "dev": true, "license": "MIT" }, @@ -2257,122 +2631,105 @@ "license": "MIT" }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", - "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", + "version": "11.4.4-cjs.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.4.4-cjs.2.tgz", + "integrity": "sha512-2dK6z8fhs8lla5PaOTgqfCGBxgAv/le+EhPs27KklPhm1bKObpu6lXzwfUEQ16ajXzqNrKMujsFyo9K2eaoISw==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/tsconfig": "^1.0.2", - "@octokit/types": "^9.2.3" + "@octokit/types": "^13.7.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=4" + "@octokit/core": "5" } }, "node_modules/@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.1.tgz", + "integrity": "sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==", "dev": true, "license": "MIT", + "engines": { + "node": ">= 18" + }, "peerDependencies": { - "@octokit/core": ">=3" + "@octokit/core": "5" } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz", - "integrity": "sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==", + "version": "13.3.2-cjs.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.3.2-cjs.1.tgz", + "integrity": "sha512-VUjIjOOvF2oELQmiFpWA1aOPdawpyaCUqcEBc/UOUnj3Xp6DJGrJ1+bjUIIDzdHjnFNO6q57ODMfdEZnoBkCwQ==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/types": "^10.0.0" + "@octokit/types": "^13.8.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-10.0.0.tgz", - "integrity": "sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^18.0.0" + "@octokit/core": "^5" } }, "node_modules/@octokit/request": { - "version": "6.2.8", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz", - "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", + "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", + "@octokit/endpoint": "^9.0.6", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", + "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/types": "^9.0.0", + "@octokit/types": "^13.1.0", "deprecation": "^2.0.0", "once": "^1.4.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/rest": { - "version": "19.0.11", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", - "integrity": "sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==", + "version": "20.1.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.2.tgz", + "integrity": "sha512-GmYiltypkHHtihFwPRxlaorG5R9VAHuk/vbszVoRTGXnAsY60wYLkh/E2XiFmdZmqrisw+9FaazS1i5SbdWYgA==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/core": "^4.2.1", - "@octokit/plugin-paginate-rest": "^6.1.2", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.1.2" + "@octokit/core": "^5.0.2", + "@octokit/plugin-paginate-rest": "11.4.4-cjs.2", + "@octokit/plugin-request-log": "^4.0.0", + "@octokit/plugin-rest-endpoint-methods": "13.3.2-cjs.1" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, - "node_modules/@octokit/tsconfig": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", - "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", - "dev": true, - "license": "MIT" - }, "node_modules/@octokit/types": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz", - "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^18.0.0" + "@octokit/openapi-types": "^24.2.0" } }, "node_modules/@pkgjs/parseargs": { @@ -2387,22 +2744,22 @@ } }, "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz", + "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==", "dev": true, "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/pkgr" } }, "node_modules/@rollup/plugin-node-resolve": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz", - "integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==", + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.1.tgz", + "integrity": "sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==", "dev": true, "license": "MIT", "dependencies": { @@ -2425,9 +2782,9 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz", - "integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", + "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2461,9 +2818,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.3.tgz", - "integrity": "sha512-EzxVSkIvCFxUd4Mgm4xR9YXrcp976qVaHnqom/Tgm+vU79k4vV4eYTjmRvGfeoW8m9LVcsAy/lGjcgVegKEhLQ==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz", + "integrity": "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==", "cpu": [ "arm" ], @@ -2475,9 +2832,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.3.tgz", - "integrity": "sha512-LJc5pDf1wjlt9o/Giaw9Ofl+k/vLUaYsE2zeQGH85giX2F+wn/Cg8b3c5CDP3qmVmeO5NzwVUzQQxwZvC2eQKw==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz", + "integrity": "sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==", "cpu": [ "arm64" ], @@ -2489,9 +2846,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.3.tgz", - "integrity": "sha512-OuRysZ1Mt7wpWJ+aYKblVbJWtVn3Cy52h8nLuNSzTqSesYw1EuN6wKp5NW/4eSre3mp12gqFRXOKTcN3AI3LqA==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz", + "integrity": "sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==", "cpu": [ "arm64" ], @@ -2503,9 +2860,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.3.tgz", - "integrity": "sha512-xW//zjJMlJs2sOrCmXdB4d0uiilZsOdlGQIC/jjmMWT47lkLLoB1nsNhPUcnoqyi5YR6I4h+FjBpILxbEy8JRg==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz", + "integrity": "sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==", "cpu": [ "x64" ], @@ -2517,9 +2874,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.3.tgz", - "integrity": "sha512-58E0tIcwZ+12nK1WiLzHOD8I0d0kdrY/+o7yFVPRHuVGY3twBwzwDdTIBGRxLmyjciMYl1B/U515GJy+yn46qw==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz", + "integrity": "sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==", "cpu": [ "arm64" ], @@ -2531,9 +2888,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.3.tgz", - "integrity": "sha512-78fohrpcVwTLxg1ZzBMlwEimoAJmY6B+5TsyAZ3Vok7YabRBUvjYTsRXPTjGEvv/mfgVBepbW28OlMEz4w8wGA==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz", + "integrity": "sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==", "cpu": [ "x64" ], @@ -2545,9 +2902,23 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.3.tgz", - "integrity": "sha512-h2Ay79YFXyQi+QZKo3ISZDyKaVD7uUvukEHTOft7kh00WF9mxAaxZsNs3o/eukbeKuH35jBvQqrT61fzKfAB/Q==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz", + "integrity": "sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz", + "integrity": "sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==", "cpu": [ "arm" ], @@ -2558,12 +2929,26 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.3.tgz", - "integrity": "sha512-Sv2GWmrJfRY57urktVLQ0VKZjNZGogVtASAgosDZ1aUB+ykPxSi3X1nWORL5Jk0sTIIwQiPH7iE3BMi9zGWfkg==", + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz", + "integrity": "sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz", + "integrity": "sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==", "cpu": [ - "arm" + "arm64" ], "dev": true, "license": "MIT", @@ -2572,12 +2957,12 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.3.tgz", - "integrity": "sha512-FPoJBLsPW2bDNWjSrwNuTPUt30VnfM8GPGRoLCYKZpPx0xiIEdFip3dH6CqgoT0RnoGXptaNziM0WlKgBc+OWQ==", + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz", + "integrity": "sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==", "cpu": [ - "arm64" + "loong64" ], "dev": true, "license": "MIT", @@ -2586,12 +2971,12 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.3.tgz", - "integrity": "sha512-TKxiOvBorYq4sUpA0JT+Fkh+l+G9DScnG5Dqx7wiiqVMiRSkzTclP35pE6eQQYjP4Gc8yEkJGea6rz4qyWhp3g==", + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz", + "integrity": "sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==", "cpu": [ - "arm64" + "ppc64" ], "dev": true, "license": "MIT", @@ -2600,12 +2985,12 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.3.tgz", - "integrity": "sha512-v2M/mPvVUKVOKITa0oCFksnQQ/TqGrT+yD0184/cWHIu0LoIuYHwox0Pm3ccXEz8cEQDLk6FPKd1CCm+PlsISw==", + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz", + "integrity": "sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==", "cpu": [ - "ppc64" + "riscv64" ], "dev": true, "license": "MIT", @@ -2614,10 +2999,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.3.tgz", - "integrity": "sha512-LdrI4Yocb1a/tFVkzmOE5WyYRgEBOyEhWYJe4gsDWDiwnjYKjNs7PS6SGlTDB7maOHF4kxevsuNBl2iOcj3b4A==", + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz", + "integrity": "sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==", "cpu": [ "riscv64" ], @@ -2629,9 +3014,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.3.tgz", - "integrity": "sha512-d4wVu6SXij/jyiwPvI6C4KxdGzuZOvJ6y9VfrcleHTwo68fl8vZC5ZYHsCVPUi4tndCfMlFniWgwonQ5CUpQcA==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz", + "integrity": "sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==", "cpu": [ "s390x" ], @@ -2657,9 +3042,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.3.tgz", - "integrity": "sha512-nBXOfJds8OzUT1qUreT/en3eyOXd2EH5b0wr2bVB5999qHdGKkzGzIyKYaKj02lXk6wpN71ltLIaQpu58YFBoQ==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz", + "integrity": "sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==", "cpu": [ "x64" ], @@ -2671,9 +3056,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.3.tgz", - "integrity": "sha512-ogfbEVQgIZOz5WPWXF2HVb6En+kWzScuxJo/WdQTqEgeyGkaa2ui5sQav9Zkr7bnNCLK48uxmmK0TySm22eiuw==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz", + "integrity": "sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==", "cpu": [ "arm64" ], @@ -2685,9 +3070,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.3.tgz", - "integrity": "sha512-ecE36ZBMLINqiTtSNQ1vzWc5pXLQHlf/oqGp/bSbi7iedcjcNb6QbCBNG73Euyy2C+l/fn8qKWEwxr+0SSfs3w==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz", + "integrity": "sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==", "cpu": [ "ia32" ], @@ -2699,9 +3084,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.3.tgz", - "integrity": "sha512-vliZLrDmYKyaUoMzEbMTg2JkerfBjn03KmAw9CykO0Zzkzoyd7o3iZNam/TpyWNjNT+Cz2iO3P9Smv2wgrR+Eg==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz", + "integrity": "sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==", "cpu": [ "x64" ], @@ -2743,13 +3128,13 @@ } }, "node_modules/@sigstore/protobuf-specs": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.3.2.tgz", - "integrity": "sha512-c6B0ehIWxMI8wiS/bj6rHMPqeFvngFV7cDU/MY+B16P9Z3Mp9k8L93eYZ7BYzSickzuqAQqAq0V956b3Ju6mLw==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.3.3.tgz", + "integrity": "sha512-RpacQhBlwpBWd7KEJsRKcBQalbV28fvkxwTOJIqhIuDysMMaJW47V4OqW30iJB9uRpqOSxxEAQFdr8tTattReQ==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@sigstore/sign": { @@ -2867,6 +3252,16 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/@tufjs/models/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@tufjs/models/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -2894,9 +3289,9 @@ } }, "node_modules/@types/conventional-commits-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", - "integrity": "sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.1.tgz", + "integrity": "sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2926,9 +3321,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, @@ -2961,20 +3356,20 @@ "license": "MIT" }, "node_modules/@types/mocha": { - "version": "10.0.9", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.9.tgz", - "integrity": "sha512-sicdRoWtYevwxjOHNMPTl3vSfJM6oyW8o1wXeI7uww6b6xHg8eBznQDNSGBCDJmsE8UMxP05JgZRtsKbTqt//Q==", + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", + "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", "dev": true, "license": "MIT" }, "node_modules/@types/node": { - "version": "22.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.1.tgz", - "integrity": "sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg==", + "version": "22.15.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz", + "integrity": "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.19.8" + "undici-types": "~6.21.0" } }, "node_modules/@types/normalize-package-data": { @@ -2991,6 +3386,263 @@ "dev": true, "license": "MIT" }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.1.tgz", + "integrity": "sha512-TDCXj+YxLgtvxvFlAvpoRv9MAncDLBV2oT9Bd7YBGC/b/sEURoOYuIwLI99rjWOfY3QtDzO+mk0n4AmdFExW8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.33.1", + "@typescript-eslint/type-utils": "8.33.1", + "@typescript-eslint/utils": "8.33.1", + "@typescript-eslint/visitor-keys": "8.33.1", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.33.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.1.tgz", + "integrity": "sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.33.1", + "@typescript-eslint/types": "8.33.1", + "@typescript-eslint/typescript-estree": "8.33.1", + "@typescript-eslint/visitor-keys": "8.33.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.1.tgz", + "integrity": "sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.33.1", + "@typescript-eslint/types": "^8.33.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.1.tgz", + "integrity": "sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.33.1", + "@typescript-eslint/visitor-keys": "8.33.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.1.tgz", + "integrity": "sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.1.tgz", + "integrity": "sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.33.1", + "@typescript-eslint/utils": "8.33.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.1.tgz", + "integrity": "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.1.tgz", + "integrity": "sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.33.1", + "@typescript-eslint/tsconfig-utils": "8.33.1", + "@typescript-eslint/types": "8.33.1", + "@typescript-eslint/visitor-keys": "8.33.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.1.tgz", + "integrity": "sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.33.1", + "@typescript-eslint/types": "8.33.1", + "@typescript-eslint/typescript-estree": "8.33.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.1.tgz", + "integrity": "sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.33.1", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -3153,45 +3805,45 @@ } }, "node_modules/@webpack-cli/configtest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", - "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-3.0.1.tgz", + "integrity": "sha512-u8d0pJ5YFgneF/GuvEiDA61Tf1VDomHHYMjv/wc9XzYj7nopltpG96nXN5dJRstxZhcNpV1g+nT6CydO7pHbjA==", "dev": true, "license": "MIT", "engines": { - "node": ">=14.15.0" + "node": ">=18.12.0" }, "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" + "webpack": "^5.82.0", + "webpack-cli": "6.x.x" } }, "node_modules/@webpack-cli/info": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", - "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-3.0.1.tgz", + "integrity": "sha512-coEmDzc2u/ffMvuW9aCjoRzNSPDl/XLuhPdlFRpT9tZHmJ/039az33CE7uH+8s0uL1j5ZNtfdv0HkfaKRBGJsQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=14.15.0" + "node": ">=18.12.0" }, "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" + "webpack": "^5.82.0", + "webpack-cli": "6.x.x" } }, "node_modules/@webpack-cli/serve": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", - "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-3.0.1.tgz", + "integrity": "sha512-sbgw03xQaCLiT6gcY/6u3qBDn01CWw/nbaXl3gTdTFuJJ75Gffv3E3DBpgvY2fkkrdS1fpjaXNOmJlnbtKauKg==", "dev": true, "license": "MIT", "engines": { - "node": ">=14.15.0" + "node": ">=18.12.0" }, "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" + "webpack": "^5.82.0", + "webpack-cli": "6.x.x" }, "peerDependenciesMeta": { "webpack-dev-server": { @@ -3288,23 +3940,11 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/abstract-leveldown": { "version": "0.12.4", "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-0.12.4.tgz", "integrity": "sha512-TOod9d5RDExo6STLMGa+04HGkl+TlMfbDnTyN93/ETJ9DpQ0DaYLqcMZlbXvdc4W3vVo1Qrl+WhSp8zvDsJ+jA==", + "deprecated": "Superseded by abstract-level (https://github.com/Level/community#faq)", "dev": true, "license": "MIT", "dependencies": { @@ -3321,31 +3961,52 @@ } }, "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "license": "MIT", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "mime-db": "^1.54.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/accepts/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "dev": true, "license": "MIT", "bin": { @@ -3386,22 +4047,18 @@ "license": "MIT" }, "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, "engines": { "node": ">= 14" } }, "node_modules/agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", "license": "MIT", "dependencies": { "humanize-ms": "^1.2.1" @@ -3440,14 +4097,35 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, "peerDependencies": { - "ajv": "^6.9.1" + "ajv": "^8.8.2" } }, "node_modules/ansi-colors": { @@ -3494,22 +4172,8 @@ "engines": { "node": ">=10" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/aproba": { @@ -3519,9 +4183,9 @@ "license": "ISC" }, "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", "deprecated": "This package is no longer supported.", "license": "ISC", "dependencies": { @@ -3529,7 +4193,7 @@ "readable-stream": "^3.6.0" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/arg": { @@ -3547,14 +4211,14 @@ "license": "Python-2.0" }, "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, "engines": { "node": ">= 0.4" @@ -3573,12 +4237,6 @@ "node": ">=8" } }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", @@ -3587,18 +4245,20 @@ "license": "MIT" }, "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -3618,18 +4278,19 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -3639,16 +4300,16 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3658,16 +4319,16 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3677,20 +4338,19 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" @@ -3722,9 +4382,9 @@ } }, "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", "dev": true, "license": "MIT" }, @@ -3746,9 +4406,18 @@ "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, "license": "MIT" }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3783,9 +4452,9 @@ } }, "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", + "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", "dev": true, "license": "MIT", "dependencies": { @@ -3862,19 +4531,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -3888,59 +4544,52 @@ } }, "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", + "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", "dev": true, "license": "MIT" }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=18" } }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", "dependencies": { - "ms": "2.0.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/braces": { @@ -3963,6 +4612,16 @@ "dev": true, "license": "MIT" }, + "node_modules/browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.17.0" + } + }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -4109,9 +4768,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", + "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", "dev": true, "funding": [ { @@ -4129,10 +4788,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.1" + "caniuse-lite": "^1.0.30001718", + "electron-to-chromium": "^1.5.160", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -4258,6 +4917,16 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/cacache/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -4339,16 +5008,45 @@ } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -4396,9 +5094,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001680", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz", - "integrity": "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==", + "version": "1.0.30001721", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz", + "integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==", "dev": true, "funding": [ { @@ -4417,9 +5115,9 @@ "license": "CC-BY-4.0" }, "node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "dev": true, "license": "MIT", "engines": { @@ -4437,41 +5135,19 @@ "license": "MIT" }, "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 14.16.0" }, "funding": { "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" } }, "node_modules/chownr": { @@ -4510,9 +5186,9 @@ } }, "node_modules/cipher-base": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.5.tgz", - "integrity": "sha512-xq7ICKB4TMHUx7Tz1L9O2SGKOhYMOTR32oir45Bq28/AQTpHogKgHcoYFSdRbMtddl+ozNXfXY9jWcgYKmde0w==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", + "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", "dev": true, "license": "MIT", "dependencies": { @@ -4679,19 +5355,6 @@ "node": ">=6" } }, - "node_modules/clone-deep/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "license": "MIT", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/cmd-shim": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-6.0.3.tgz", @@ -4778,13 +5441,13 @@ } }, "node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", + "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/commitizen": { @@ -4818,17 +5481,6 @@ "node": ">= 12" } }, - "node_modules/commitizen/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/commitizen/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -4851,19 +5503,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/commitizen/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/commitizen/node_modules/minimist": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", @@ -4921,6 +5560,15 @@ "dev": true, "license": "MIT" }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, "node_modules/console-browserify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", @@ -4941,9 +5589,9 @@ "license": "MIT" }, "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" @@ -5988,19 +6636,22 @@ } }, "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } }, "node_modules/core-util-is": { "version": "1.0.3", @@ -6046,21 +6697,21 @@ } }, "node_modules/cosmiconfig-typescript-loader": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.1.0.tgz", - "integrity": "sha512-7PtBB+6FdsOvZyJtlF3hEPpACq7RQX6BVGsgC7/lfVXnKMvNCu/XY3ykreqG5w/rBNdu2z8LCIKoF3kpHHdHlA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.1.0.tgz", + "integrity": "sha512-tJ1w35ZRUiM5FeTzT7DtYWAFFv37ZLqSRkGi2oeCK1gPhvaWjkAtfXvLmvE1pRfxxp9aQo6ba/Pvg1dKj05D4g==", "dev": true, "license": "MIT", "dependencies": { - "jiti": "^1.21.6" + "jiti": "^2.4.1" }, "engines": { - "node": ">=v16" + "node": ">=v18" }, "peerDependencies": { "@types/node": "*", - "cosmiconfig": ">=8.2", - "typescript": ">=4" + "cosmiconfig": ">=9", + "typescript": ">=5" } }, "node_modules/create-ecdh": { @@ -6075,9 +6726,9 @@ } }, "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", "dev": true, "license": "MIT" }, @@ -6301,6 +6952,16 @@ "dev": true, "license": "MIT" }, + "node_modules/cz-conventional-changelog/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/cz-conventional-changelog/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -6338,15 +6999,15 @@ } }, "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -6356,31 +7017,31 @@ } }, "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/inspect-js" } }, "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" }, @@ -6402,9 +7063,9 @@ } }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -6496,6 +7157,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-0.2.0.tgz", "integrity": "sha512-+WCbb4+ez/SZ77Sdy1iadagFiVzMB89IKOBhglgnUkVxOxRWmmFsz8UDSNWh4Rhq+3wr/vMFlYj+rdEwWUDdng==", + "deprecated": "Superseded by abstract-level (https://github.com/Level/community#faq)", "dev": true, "license": "MIT", "dependencies": { @@ -6506,6 +7168,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -6596,16 +7259,6 @@ "integrity": "sha512-vgTAOosB1aHrmzjGnzFCbjvXbk8QAOC/36JxJhcBkeAuUy8QwRFxAWBHemiDpUB3cbrBruFUdzpUS21aocvaWg==", "license": "MIT" }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, "node_modules/detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", @@ -6627,18 +7280,18 @@ } }, "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", "license": "Apache-2.0", "engines": { "node": ">=8" } }, "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -6668,9 +7321,9 @@ } }, "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", "dev": true, "license": "MIT" }, @@ -6708,13 +7361,13 @@ } }, "node_modules/domain-browser": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-5.7.0.tgz", - "integrity": "sha512-edTFu0M/7wO1pXY6GDxVNVW086uqwWYIHP98txhcPyV995X21JIH2DtYp33sQJOupYoXKe9RwTw2Ya2vWaquTQ==", + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", + "integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==", "dev": true, - "license": "Artistic-2.0", + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=10" }, "funding": { "url": "https://bevry.me/fund" @@ -6734,9 +7387,9 @@ } }, "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -6763,24 +7416,24 @@ } }, "node_modules/duckdb": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/duckdb/-/duckdb-1.1.3.tgz", - "integrity": "sha512-tIpZr2NsSkYmfGC1ETl75RuVsaDyjvR3yAOrECcIyw7bdluzcyzEXOXoiuT+4t54hT+CppZv43gk/HiZdKW9Vw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/duckdb/-/duckdb-1.3.0.tgz", + "integrity": "sha512-7PMLj/1xVXaFRYR2RlsmFEweeaR7z/y8rPCa9BG7ZGNUGMy+BUGTYceiV7FxbPIJLDho2Kr6SF4hICDsDTIUlQ==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.0", + "@mapbox/node-pre-gyp": "^2.0.0", "node-addon-api": "^7.0.0", "node-gyp": "^9.3.0" } }, "node_modules/duckdb-async": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/duckdb-async/-/duckdb-async-1.1.3.tgz", - "integrity": "sha512-8Q8BYTjfzjPFJ3J8bafLGUcdxI2ZXPxpw3u8x+SFr7s3T7JM0Nn26LKis4rA0i4TCBSZ9ilhB8NOJ/9HrPGSlw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/duckdb-async/-/duckdb-async-1.2.1.tgz", + "integrity": "sha512-Q48ki2lxIWRmTYUxycnPIWKEOQemsYQuATFIWDrz8l56ymaLao5hm4iFZCzSQ9t4dpNfQgYR+cVunxH3DT3o4A==", "license": "MIT", "dependencies": { - "duckdb": "1.1.3" + "duckdb": "^1.2.1" } }, "node_modules/duckdb/node_modules/@npmcli/fs": { @@ -6814,28 +7467,13 @@ "node": ">= 6.0.0" } }, - "node_modules/duckdb/node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/duckdb/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/duckdb/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/duckdb/node_modules/cacache": { @@ -6867,15 +7505,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/duckdb/node_modules/cacache/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/duckdb/node_modules/cacache/node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", @@ -6920,26 +7549,6 @@ "node": ">= 8" } }, - "node_modules/duckdb/node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/duckdb/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -7024,18 +7633,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/duckdb/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/duckdb/node_modules/minipass": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", @@ -7117,22 +7714,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/duckdb/node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/duckdb/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -7149,12 +7730,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/duckdb/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" - }, "node_modules/duckdb/node_modules/socks-proxy-agent": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", @@ -7205,6 +7780,20 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -7252,9 +7841,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.63", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.63.tgz", - "integrity": "sha512-ddeXKuY9BHo/mw145axlyWjlJ1UBt4WK3AlvkT7W2AbqfRQoacVoRUCF6wL3uIx/8wT9oLKXzI+rFqHHscByaA==", + "version": "1.5.165", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz", + "integrity": "sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==", "dev": true, "license": "ISC" }, @@ -7275,9 +7864,9 @@ } }, "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", "dev": true, "license": "MIT" }, @@ -7330,9 +7919,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", "dev": true, "license": "MIT", "dependencies": { @@ -7421,58 +8010,66 @@ } }, "node_modules/es-abstract": { - "version": "1.23.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.5.tgz", - "integrity": "sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", "dev": true, "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", - "gopd": "^1.0.1", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", + "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.3", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" }, "engines": { "node": ">= 0.4" @@ -7482,13 +8079,10 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" } @@ -7503,17 +8097,16 @@ } }, "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -7523,40 +8116,44 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -7565,6 +8162,47 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -7582,40 +8220,44 @@ "license": "MIT" }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { - "version": "9.15.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.15.0.tgz", - "integrity": "sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==", + "version": "9.28.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.28.0.tgz", + "integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.9.0", - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.15.0", - "@eslint/plugin-kit": "^0.2.3", + "@eslint/config-array": "^0.20.0", + "@eslint/config-helpers": "^0.2.1", + "@eslint/core": "^0.14.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.28.0", + "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.1", + "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.5", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", + "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", @@ -7682,14 +8324,17 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz", + "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==", "dev": true, "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, "peerDependencies": { "eslint": ">=7.0.0" } @@ -7778,17 +8423,6 @@ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/eslint-plugin-import/node_modules/debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", @@ -7812,19 +8446,6 @@ "json5": "lib/cli.js" } }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/eslint-plugin-import/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -7859,61 +8480,41 @@ } }, "node_modules/eslint-plugin-mocha": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.5.0.tgz", - "integrity": "sha512-F2ALmQVPT1GoP27O1JTZGrV9Pqg8k79OeIuvw63UxMtQKREZtmkK1NFgkZQ2TW7L2JSSFKHFPTtHu5z8R9QNRw==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-11.1.0.tgz", + "integrity": "sha512-rKntVWRsQFPbf8OkSgVNRVRrcVAPaGTyEgWCEyXaPDJkTl0v5/lwu1vTk5sWiUJU8l2sxwvGUZzSNrEKdVMeQw==", "dev": true, "license": "MIT", "dependencies": { - "eslint-utils": "^3.0.0", - "globals": "^13.24.0", - "rambda": "^7.4.0" - }, - "engines": { - "node": ">=14.0.0" + "@eslint-community/eslint-utils": "^4.4.1", + "globals": "^15.14.0" }, "peerDependencies": { - "eslint": ">=7.0.0" + "eslint": ">=9.0.0" } }, "node_modules/eslint-plugin-mocha/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", "dev": true, "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-plugin-mocha/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz", + "integrity": "sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg==", "dev": true, "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.9.1" + "synckit": "^0.11.7" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -7924,7 +8525,7 @@ "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", - "eslint-config-prettier": "*", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "peerDependenciesMeta": { @@ -7937,9 +8538,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -7953,35 +8554,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10" - } - }, "node_modules/eslint-visitor-keys": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", @@ -8028,17 +8600,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/eslint/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -8056,19 +8617,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -8109,19 +8657,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/eslint/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -8271,16 +8806,6 @@ "node": ">= 0.6" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -8354,67 +8879,73 @@ } }, "node_modules/exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz", + "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==", "license": "Apache-2.0" }, "node_modules/express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" }, - "engines": { - "node": ">= 0.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/express/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">= 0.6" } }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" + "node_modules/express/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } }, "node_modules/external-editor": { "version": "3.1.0", @@ -8446,9 +8977,9 @@ "license": "Apache-2.0" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", "dependencies": { @@ -8456,7 +8987,7 @@ "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -8490,10 +9021,20 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", - "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "BSD-3-Clause" }, "node_modules/fastest-levenshtein": { @@ -8507,9 +9048,9 @@ } }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, "license": "ISC", "dependencies": { @@ -8532,6 +9073,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -8555,6 +9106,16 @@ "minimatch": "^5.0.1" } }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/filelist/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -8582,38 +9143,22 @@ } }, "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" }, "engines": { "node": ">= 0.8" } }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/find-node-modules": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.3.tgz", @@ -8691,9 +9236,9 @@ } }, "node_modules/flatted": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", - "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, "license": "ISC" }, @@ -8718,13 +9263,19 @@ } }, "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/foreach": { @@ -8735,13 +9286,13 @@ "license": "MIT" }, "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -8752,14 +9303,16 @@ } }, "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -8776,12 +9329,12 @@ } }, "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/front-matter": { @@ -8892,16 +9445,18 @@ } }, "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -8957,24 +9512,23 @@ "license": "MIT" }, "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", "deprecated": "This package is no longer supported.", "license": "ISC", "dependencies": { "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", + "signal-exit": "^3.0.7", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" + "wide-align": "^1.1.5" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/gauge/node_modules/signal-exit": { @@ -9007,16 +9561,21 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -9124,6 +9683,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", @@ -9138,15 +9710,15 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -9155,6 +9727,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/git-raw-commits": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", @@ -9494,9 +10079,9 @@ "license": "ISC" }, "node_modules/glob": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", - "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.2.tgz", + "integrity": "sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==", "dev": true, "license": "ISC", "dependencies": { @@ -9537,6 +10122,32 @@ "dev": true, "license": "BSD-2-Clause" }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/global-directory": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", @@ -9657,12 +10268,12 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9674,6 +10285,13 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -9707,11 +10325,14 @@ } }, "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9729,6 +10350,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -9738,10 +10360,14 @@ } }, "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -9750,9 +10376,9 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -9784,17 +10410,17 @@ "license": "ISC" }, "node_modules/hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" }, "engines": { - "node": ">=4" + "node": ">= 0.10" } }, "node_modules/hash.js": { @@ -9880,9 +10506,9 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "license": "BSD-2-Clause" }, "node_modules/http-errors": { @@ -10001,13 +10627,12 @@ "license": "MIT" }, "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "license": "MIT", "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { @@ -10053,6 +10678,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" @@ -10112,6 +10738,16 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/ignore-walk/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/ignore-walk/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -10129,9 +10765,9 @@ } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10323,15 +10959,15 @@ } }, "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -10379,14 +11015,14 @@ } }, "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10396,14 +11032,15 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -10419,41 +11056,51 @@ "dev": true, "license": "MIT" }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, "license": "MIT", "dependencies": { - "has-bigints": "^1.0.1" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "has-bigints": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10489,9 +11136,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, "license": "MIT", "dependencies": { @@ -10505,12 +11152,14 @@ } }, "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, "license": "MIT", "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" }, "engines": { @@ -10521,13 +11170,14 @@ } }, "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10562,6 +11212,22 @@ "node": ">=0.10.0" } }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", @@ -10576,13 +11242,16 @@ } }, "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -10620,6 +11289,19 @@ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "license": "MIT" }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", @@ -10668,13 +11350,14 @@ } }, "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10710,25 +11393,49 @@ } }, "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, "engines": { "node": ">=0.10.0" } }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -10737,13 +11444,13 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -10753,9 +11460,9 @@ } }, "node_modules/is-ssh": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", - "integrity": "sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.1.tgz", + "integrity": "sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==", "dev": true, "license": "MIT", "dependencies": { @@ -10773,13 +11480,14 @@ } }, "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10789,13 +11497,15 @@ } }, "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -10818,13 +11528,13 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -10853,14 +11563,47 @@ "dev": true, "license": "MIT" }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10919,10 +11662,20 @@ "node": ">=0.10.0" } }, + "node_modules/isomorphic-timers-promises": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-timers-promises/-/isomorphic-timers-promises-1.0.1.tgz", + "integrity": "sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/jackspeak": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", - "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -10970,17 +11723,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jake/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/jake/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -10998,19 +11740,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jake/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -11102,13 +11831,13 @@ } }, "node_modules/jiti": { - "version": "1.21.6", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", - "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", "dev": true, "license": "MIT", "bin": { - "jiti": "bin/jiti.js" + "jiti": "lib/jiti-cli.mjs" } }, "node_modules/js-tokens": { @@ -11287,19 +12016,19 @@ } }, "node_modules/lerna": { - "version": "8.1.9", - "resolved": "https://registry.npmjs.org/lerna/-/lerna-8.1.9.tgz", - "integrity": "sha512-ZRFlRUBB2obm+GkbTR7EbgTMuAdni6iwtTQTMy7LIrQ4UInG44LyfRepljtgUxh4HA0ltzsvWfPkd5J1DKGCeQ==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/lerna/-/lerna-8.2.2.tgz", + "integrity": "sha512-GkqBELTG4k7rfzAwRok2pKBvhNo046Hfwcj7TuhDah3q58/BBBAqvIFLfqEI5fglnNOs6maMSn6/MWjccQE55A==", "dev": true, "license": "MIT", "dependencies": { - "@lerna/create": "8.1.9", + "@lerna/create": "8.2.2", "@npmcli/arborist": "7.5.4", "@npmcli/package-json": "5.2.0", "@npmcli/run-script": "8.1.0", "@nx/devkit": ">=17.1.2 < 21", "@octokit/plugin-enterprise-rest": "6.0.1", - "@octokit/rest": "19.0.11", + "@octokit/rest": "20.1.2", "aproba": "2.0.0", "byte-size": "8.1.1", "chalk": "4.1.0", @@ -11360,7 +12089,6 @@ "slash": "3.0.0", "ssri": "^10.0.6", "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", "strong-log-transformer": "2.1.0", "tar": "6.2.1", "temp-dir": "1.0.0", @@ -11398,17 +12126,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/lerna/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/lerna/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -11442,9 +12159,9 @@ } }, "node_modules/lerna/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", "dev": true, "license": "MIT", "dependencies": { @@ -11616,6 +12333,7 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/level-js/-/level-js-2.2.4.tgz", "integrity": "sha512-lZtjt4ZwHE00UMC1vAb271p9qzg8vKlnDeXfIesH3zL0KxhHRDjClQLGLWhyR0nK4XARnd4wc/9eD1ffd4PshQ==", + "deprecated": "Superseded by browser-level (https://github.com/Level/community#faq)", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -11719,6 +12437,7 @@ "version": "0.18.6", "resolved": "https://registry.npmjs.org/levelup/-/levelup-0.18.6.tgz", "integrity": "sha512-uB0auyRqIVXx+hrpIUtol4VAPhLRcnxcOsd2i2m6rbFIDarO5dnrupLOStYYpEcu8ZT087Z9HEuYw1wjr6RL6Q==", + "deprecated": "Superseded by abstract-level (https://github.com/Level/community#faq)", "dev": true, "license": "MIT", "dependencies": { @@ -11843,9 +12562,9 @@ } }, "node_modules/libnpmpublish/node_modules/ci-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz", - "integrity": "sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.2.0.tgz", + "integrity": "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==", "dev": true, "funding": [ { @@ -11859,9 +12578,9 @@ } }, "node_modules/lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", "dev": true, "license": "MIT", "engines": { @@ -11882,168 +12601,37 @@ } }, "node_modules/lint-staged": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", - "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.1.0.tgz", + "integrity": "sha512-HkpQh69XHxgCjObjejBT3s2ILwNjFx8M3nw+tJ/ssBauDlIpkx2RpqWSi1fBgkXLSSXnbR3iEq1NkVtpvV+FLQ==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "~5.3.0", - "commander": "~12.1.0", - "debug": "~4.3.6", - "execa": "~8.0.1", - "lilconfig": "~3.1.2", - "listr2": "~8.2.4", - "micromatch": "~4.0.8", - "pidtree": "~0.6.0", - "string-argv": "~0.3.2", - "yaml": "~2.5.0" + "chalk": "^5.4.1", + "commander": "^14.0.0", + "debug": "^4.4.1", + "lilconfig": "^3.1.3", + "listr2": "^8.3.3", + "micromatch": "^4.0.8", + "nano-spawn": "^1.0.2", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.8.0" }, "bin": { "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": ">=18.12.0" + "node": ">=20.17" }, "funding": { "url": "https://opencollective.com/lint-staged" } }, - "node_modules/lint-staged/node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/lint-staged/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/lint-staged/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/listr2": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", - "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", + "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12199,6 +12787,7 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, "license": "MIT" }, "node_modules/lodash.camelcase": { @@ -12625,6 +13214,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -12638,12 +13236,12 @@ } }, "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/meow": { @@ -12667,10 +13265,13 @@ "license": "MIT" }, "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "license": "MIT", + "engines": { + "node": ">=18" + }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -12692,15 +13293,6 @@ "node": ">= 8" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -12730,9 +13322,9 @@ } }, "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", "dev": true, "license": "MIT" }, @@ -12752,6 +13344,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -12761,6 +13354,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -12817,19 +13411,15 @@ "license": "MIT" }, "node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", - "dev": true, + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "*" } }, "node_modules/minimist": { @@ -12870,7 +13460,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" @@ -13017,31 +13606,31 @@ } }, "node_modules/mocha": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", - "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.5.0.tgz", + "integrity": "sha512-VKDjhy6LMTKm0WgNEdlY77YVsD49LZnPSXJAaPNL9NRYQADxvORsyG1DIQY6v53BKTnlNbEE2MbVCDbnxr4K3w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-colors": "^4.1.3", "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", + "chokidar": "^4.0.1", "debug": "^4.3.5", - "diff": "^5.2.0", + "diff": "^7.0.0", "escape-string-regexp": "^4.0.0", "find-up": "^5.0.0", - "glob": "^8.1.0", + "glob": "^10.4.5", "he": "^1.2.0", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", + "minimatch": "^9.0.5", "ms": "^2.1.3", + "picocolors": "^1.1.1", "serialize-javascript": "^6.0.2", "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" }, "bin": { @@ -13049,27 +13638,29 @@ "mocha": "bin/mocha.js" }, "engines": { - "node": ">= 14.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "balanced-match": "^1.0.0" } }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/mocha/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { "node": ">=10" }, @@ -13077,42 +13668,41 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/mocha/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": ">=10" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/mocha/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" + "@isaacs/cliui": "^8.0.2" }, "funding": { "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/mocha/node_modules/locate-path": { @@ -13132,16 +13722,19 @@ } }, "node_modules/mocha/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/mocha/node_modules/p-limit": { @@ -13186,49 +13779,37 @@ "node": ">=8" } }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/mocha/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "has-flag": "^4.0.0" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.18" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "has-flag": "^4.0.0" }, "engines": { "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/mocha/node_modules/yocto-queue": { @@ -13280,30 +13861,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/multimatch/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/multimatch/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -13311,6 +13868,19 @@ "dev": true, "license": "ISC" }, + "node_modules/nano-spawn": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-1.0.2.tgz", + "integrity": "sha512-21t+ozMQDAL/UGgQVBbZ/xXvNO10++ZPuTmKRO8k9V3AClVRht49ahtDjfY8l1q6nSHOrE5ASfthzH3ol6R/hg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/nano-spawn?sponsor=1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -13361,9 +13931,9 @@ } }, "node_modules/node-gyp": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.2.0.tgz", - "integrity": "sha512-sp3FonBAaFe4aYTcFdZUn2NYkbP7xroPGYvQmP4Nl5PxamznItBnNCgjrVTKrEfQynInMsJvZrdmqUnysCJ8rw==", + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.3.1.tgz", + "integrity": "sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13385,6 +13955,16 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/node-gyp/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/node-gyp/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -13489,106 +14069,189 @@ "license": "MIT" }, "node_modules/node-polyfill-webpack-plugin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/node-polyfill-webpack-plugin/-/node-polyfill-webpack-plugin-4.0.0.tgz", - "integrity": "sha512-WLk77vLpbcpmTekRj6s6vYxk30XoyaY5MDZ4+9g8OaKoG3Ij+TjOqhpQjVUlfDZBPBgpNATDltaQkzuXSnnkwg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/node-polyfill-webpack-plugin/-/node-polyfill-webpack-plugin-4.1.0.tgz", + "integrity": "sha512-b4ei444EKkOagG/yFqojrD3QTYM5IOU1f8tn9o6uwrG4qL+brI7oVhjPVd0ZL2xy+Z6CP5bu9w8XTvlWgiXHcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-stdlib-browser": "^1.3.0", + "type-fest": "^4.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "webpack": ">=5" + } + }, + "node_modules/node-polyfill-webpack-plugin/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-stdlib-browser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-stdlib-browser/-/node-stdlib-browser-1.3.1.tgz", + "integrity": "sha512-X75ZN8DCLftGM5iKwoYLA3rjnrAEs97MkzvSd4q2746Tgpg8b8XWiBGiBG4ZpgcAqBgtgPHTiAc8ZMCvZuikDw==", "dev": true, "license": "MIT", "dependencies": { - "assert": "^2.1.0", + "assert": "^2.0.0", + "browser-resolve": "^2.0.0", "browserify-zlib": "^0.2.0", - "buffer": "^6.0.3", - "console-browserify": "^1.2.0", + "buffer": "^5.7.1", + "console-browserify": "^1.1.0", "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.12.0", - "domain-browser": "^5.7.0", - "events": "^3.3.0", + "create-require": "^1.1.1", + "crypto-browserify": "^3.12.1", + "domain-browser": "4.22.0", + "events": "^3.0.0", "https-browserify": "^1.0.0", + "isomorphic-timers-promises": "^1.0.1", "os-browserify": "^0.3.0", "path-browserify": "^1.0.1", + "pkg-dir": "^5.0.0", "process": "^0.11.10", - "punycode": "^2.3.1", + "punycode": "^1.4.1", "querystring-es3": "^0.2.1", - "readable-stream": "^4.5.2", + "readable-stream": "^3.6.0", "stream-browserify": "^3.0.0", "stream-http": "^3.2.0", - "string_decoder": "^1.3.0", - "timers-browserify": "^2.0.12", - "tty-browserify": "^0.0.1", - "type-fest": "^4.18.2", - "url": "^0.11.3", - "util": "^0.12.5", - "vm-browserify": "^1.1.2" + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.1", + "url": "^0.11.4", + "util": "^0.12.4", + "vm-browserify": "^1.0.1" }, "engines": { - "node": ">=14" + "node": ">=10" + } + }, + "node_modules/node-stdlib-browser/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, - "peerDependencies": { - "webpack": ">=5" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-polyfill-webpack-plugin/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "node_modules/node-stdlib-browser/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-polyfill-webpack-plugin/node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "node_modules/node-stdlib-browser/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-polyfill-webpack-plugin/node_modules/type-fest": { - "version": "4.27.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.27.0.tgz", - "integrity": "sha512-3IMSWgP7C5KSQqmo1wjhKrwsvXAtF33jO3QY+Uy++ia7hqvgSK6iXbbg5PbDBc1P2ZbNEDgejOrN4YooXvhwCw==", + "node_modules/node-stdlib-browser/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/node-stdlib-browser/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-stdlib-browser/node_modules/pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-stdlib-browser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-stdlib-browser/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", "engines": { - "node": ">=16" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true, - "license": "MIT" - }, "node_modules/nopt": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", @@ -13620,16 +14283,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/npm-bundled": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.1.tgz", @@ -13745,22 +14398,25 @@ } }, "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", "deprecated": "This package is no longer supported.", "license": "ISC", "dependencies": { - "are-we-there-yet": "^2.0.0", + "are-we-there-yet": "^3.0.0", "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", + "gauge": "^4.0.3", "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/nx": { - "version": "20.1.2", - "resolved": "https://registry.npmjs.org/nx/-/nx-20.1.2.tgz", - "integrity": "sha512-CvjmuQmI0RWLYZxRSIgQZmzsQv6dPp9oI0YZE3L1dagBPfTf5Cun65I0GLt7bdkDnVx2PGYkDbIoJSv2/V+83Q==", + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/nx/-/nx-20.8.2.tgz", + "integrity": "sha512-mDKpbH3vEpUFDx0rrLh+tTqLq1PYU8KiD/R7OVZGd1FxQxghx2HOl32MiqNsfPcw6AvKlXhslbwIESV+N55FLQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -13769,7 +14425,7 @@ "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "3.0.2", "@zkochan/js-yaml": "0.0.7", - "axios": "^1.7.4", + "axios": "^1.8.3", "chalk": "^4.1.0", "cli-cursor": "3.1.0", "cli-spinners": "2.6.1", @@ -13789,12 +14445,14 @@ "npm-run-path": "^4.0.1", "open": "^8.4.0", "ora": "5.3.0", + "resolve.exports": "2.0.3", "semver": "^7.5.3", "string-width": "^4.2.3", "tar-stream": "~2.2.0", "tmp": "~0.2.1", "tsconfig-paths": "^4.1.2", "tslib": "^2.3.0", + "yaml": "^2.6.0", "yargs": "^17.6.2", "yargs-parser": "21.1.1" }, @@ -13803,16 +14461,16 @@ "nx-cloud": "bin/nx-cloud.js" }, "optionalDependencies": { - "@nx/nx-darwin-arm64": "20.1.2", - "@nx/nx-darwin-x64": "20.1.2", - "@nx/nx-freebsd-x64": "20.1.2", - "@nx/nx-linux-arm-gnueabihf": "20.1.2", - "@nx/nx-linux-arm64-gnu": "20.1.2", - "@nx/nx-linux-arm64-musl": "20.1.2", - "@nx/nx-linux-x64-gnu": "20.1.2", - "@nx/nx-linux-x64-musl": "20.1.2", - "@nx/nx-win32-arm64-msvc": "20.1.2", - "@nx/nx-win32-x64-msvc": "20.1.2" + "@nx/nx-darwin-arm64": "20.8.2", + "@nx/nx-darwin-x64": "20.8.2", + "@nx/nx-freebsd-x64": "20.8.2", + "@nx/nx-linux-arm-gnueabihf": "20.8.2", + "@nx/nx-linux-arm64-gnu": "20.8.2", + "@nx/nx-linux-arm64-musl": "20.8.2", + "@nx/nx-linux-x64-gnu": "20.8.2", + "@nx/nx-linux-x64-musl": "20.8.2", + "@nx/nx-win32-arm64-msvc": "20.8.2", + "@nx/nx-win32-x64-msvc": "20.8.2" }, "peerDependencies": { "@swc-node/register": "^1.8.0", @@ -13843,6 +14501,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/nx/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/nx/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -13909,19 +14577,10 @@ "node": ">=14.14" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -13958,15 +14617,17 @@ } }, "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, "engines": { @@ -13977,15 +14638,16 @@ } }, "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "es-object-atoms": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -14026,13 +14688,14 @@ } }, "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, @@ -14206,6 +14869,24 @@ "node": ">=0.10.0" } }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -14511,9 +15192,9 @@ } }, "node_modules/parse-path": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", - "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.1.0.tgz", + "integrity": "sha512-EuCycjZtfPcjWk7KTksnJ5xPMvWGA/6i4zrLYhRG0hGvC3GPU/jGUj3Cy+ZR0v30duV3e23R95T1lE2+lsndSw==", "dev": true, "license": "MIT", "dependencies": { @@ -14600,9 +15281,9 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", - "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", + "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", "dev": true, "license": "ISC", "engines": { @@ -14610,10 +15291,13 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", - "license": "MIT" + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } }, "node_modules/path-type": { "version": "4.0.0", @@ -14768,53 +15452,22 @@ } }, "node_modules/portfinder": { - "version": "1.0.32", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", - "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", + "version": "1.0.37", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.37.tgz", + "integrity": "sha512-yuGIEjDAYnnOex9ddMnKZEMFE0CcGo6zbfzDklkmT1m5z734ss6JMzN9rNB3+RR7iS+F10D4/BVIaXOyh8PQKw==", "license": "MIT", "dependencies": { - "async": "^2.6.4", - "debug": "^3.2.7", - "mkdirp": "^0.5.6" + "async": "^3.2.6", + "debug": "^4.3.6" }, "engines": { - "node": ">= 0.12.0" - } - }, - "node_modules/portfinder/node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "license": "MIT", - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/portfinder/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/portfinder/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" + "node": ">= 10.12" } }, "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, "license": "MIT", "engines": { @@ -14846,9 +15499,9 @@ } }, "node_modules/prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "dev": true, "license": "MIT", "bin": { @@ -14986,9 +15639,9 @@ } }, "node_modules/protocols": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", - "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.2.tgz", + "integrity": "sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==", "dev": true, "license": "MIT" }, @@ -15035,9 +15688,9 @@ } }, "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", "dev": true, "license": "MIT" }, @@ -15052,12 +15705,12 @@ } }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -15106,13 +15759,6 @@ "node": ">=8" } }, - "node_modules/rambda": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/rambda/-/rambda-7.5.0.tgz", - "integrity": "sha512-y/M9weqWAH4iopRd7EHDEQQvpFPHj1AA3oHozE9tfITHUtTR7Z9PSlIRRG2l1GuW7sefC1cXFfIcF+cgnShdBA==", - "dev": true, - "license": "MIT" - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -15144,20 +15790,32 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", - "iconv-lite": "0.4.24", + "iconv-lite": "0.6.3", "unpipe": "1.0.0" }, "engines": { "node": ">= 0.8" } }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -15422,16 +16080,17 @@ } }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, "engines": { - "node": ">=8.10.0" + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/rechoir": { @@ -15461,16 +16120,41 @@ "node": ">=8" } }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regexp.prototype.flags": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", - "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "set-function-name": "^2.0.2" }, "engines": { @@ -15507,19 +16191,22 @@ "license": "MIT" }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -15561,6 +16248,26 @@ "node": ">=8" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -15592,9 +16299,9 @@ } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", "engines": { @@ -15628,6 +16335,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/rimraf/node_modules/glob": { "version": "9.3.5", "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", @@ -15712,13 +16429,13 @@ } }, "node_modules/rollup": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.3.tgz", - "integrity": "sha512-SLsCOnlmGt9VoZ9Ek8yBK8tAdmPHeppkw+Xa7yDlCEhDTvwYei03JlWo1fdc7YTfLZ4tD8riJCUyAgTbszk1fQ==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.1.tgz", + "integrity": "sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.6" + "@types/estree": "1.0.7" }, "bin": { "rollup": "dist/bin/rollup" @@ -15728,24 +16445,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.27.3", - "@rollup/rollup-android-arm64": "4.27.3", - "@rollup/rollup-darwin-arm64": "4.27.3", - "@rollup/rollup-darwin-x64": "4.27.3", - "@rollup/rollup-freebsd-arm64": "4.27.3", - "@rollup/rollup-freebsd-x64": "4.27.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.27.3", - "@rollup/rollup-linux-arm-musleabihf": "4.27.3", - "@rollup/rollup-linux-arm64-gnu": "4.27.3", - "@rollup/rollup-linux-arm64-musl": "4.27.3", - "@rollup/rollup-linux-powerpc64le-gnu": "4.27.3", - "@rollup/rollup-linux-riscv64-gnu": "4.27.3", - "@rollup/rollup-linux-s390x-gnu": "4.27.3", - "@rollup/rollup-linux-x64-gnu": "4.27.3", - "@rollup/rollup-linux-x64-musl": "4.27.3", - "@rollup/rollup-win32-arm64-msvc": "4.27.3", - "@rollup/rollup-win32-ia32-msvc": "4.27.3", - "@rollup/rollup-win32-x64-msvc": "4.27.3", + "@rollup/rollup-android-arm-eabi": "4.41.1", + "@rollup/rollup-android-arm64": "4.41.1", + "@rollup/rollup-darwin-arm64": "4.41.1", + "@rollup/rollup-darwin-x64": "4.41.1", + "@rollup/rollup-freebsd-arm64": "4.41.1", + "@rollup/rollup-freebsd-x64": "4.41.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.41.1", + "@rollup/rollup-linux-arm-musleabihf": "4.41.1", + "@rollup/rollup-linux-arm64-gnu": "4.41.1", + "@rollup/rollup-linux-arm64-musl": "4.41.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.41.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.41.1", + "@rollup/rollup-linux-riscv64-gnu": "4.41.1", + "@rollup/rollup-linux-riscv64-musl": "4.41.1", + "@rollup/rollup-linux-s390x-gnu": "4.41.1", + "@rollup/rollup-linux-x64-gnu": "4.41.1", + "@rollup/rollup-linux-x64-musl": "4.41.1", + "@rollup/rollup-win32-arm64-msvc": "4.41.1", + "@rollup/rollup-win32-ia32-msvc": "4.41.1", + "@rollup/rollup-win32-x64-msvc": "4.41.1", "fsevents": "~2.3.2" } }, @@ -15815,9 +16534,9 @@ "license": "MIT" }, "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.3.tgz", - "integrity": "sha512-/6bn6pp1fsCGEY5n3yajmzZQAh+mW4QPItbiWxs69zskBzJuheb3tNynEjL+mKOsUSFK11X4LYF2BwwXnzWleA==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz", + "integrity": "sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==", "cpu": [ "x64" ], @@ -15828,6 +16547,29 @@ "linux" ] }, + "node_modules/rollup/node_modules/@types/estree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -15863,9 +16605,9 @@ } }, "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -15873,15 +16615,16 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, "engines": { @@ -15918,16 +16661,40 @@ ], "license": "MIT" }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "is-regex": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -15943,15 +16710,16 @@ "license": "MIT" }, "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" }, "engines": { "node": ">= 10.13.0" @@ -15961,30 +16729,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/schema-utils/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, "node_modules/secure-compare": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", @@ -15992,9 +16736,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -16004,51 +16748,46 @@ } }, "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 18" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/send/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">= 0.6" } }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "node_modules/send/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.6" } }, "node_modules/serialize-javascript": { @@ -16062,18 +16801,18 @@ } }, "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", "license": "MIT", "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 18" } }, "node_modules/set-blocking": { @@ -16086,6 +16825,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -16115,6 +16855,21 @@ "node": ">= 0.4" } }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -16239,15 +16994,69 @@ "license": "MIT" }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -16338,9 +17147,9 @@ } }, "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", + "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", "license": "MIT", "dependencies": { "ip-address": "^9.0.5", @@ -16352,13 +17161,13 @@ } }, "node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.1", + "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" }, @@ -16430,9 +17239,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", - "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", + "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", "dev": true, "license": "CC0-1.0" }, @@ -16487,6 +17296,20 @@ "node": ">= 0.8" } }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -16590,16 +17413,19 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -16609,16 +17435,20 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -16757,26 +17587,25 @@ } }, "node_modules/synckit": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", - "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz", + "integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" + "@pkgr/core": "^0.2.4" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/synckit" } }, "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", "dev": true, "license": "MIT", "engines": { @@ -16861,14 +17690,14 @@ } }, "node_modules/terser": { - "version": "5.36.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", - "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", + "version": "5.41.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.41.0.tgz", + "integrity": "sha512-H406eLPXpZbAX14+B8psIuvIr8+3c+2hkuYzpMkoE0ij+NdsVATbA78vb8neA/eqrj7rywa2pIkdmWRsXW6wmw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", + "acorn": "^8.14.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -16880,17 +17709,17 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "version": "5.3.14", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", + "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", + "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" }, "engines": { "node": ">= 10.13.0" @@ -17010,9 +17839,9 @@ } }, "node_modules/tinyexec": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", - "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", "dev": true, "license": "MIT" }, @@ -17077,10 +17906,23 @@ "node": ">=8" } }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, "node_modules/ts-loader": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", - "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.2.tgz", + "integrity": "sha512-Qo4piXvOTWcMGIgRiuFa6nHNm+54HbYaZCKqc9eeZCLRy3XqafQgwX2F7mofrbJG3g7EEb+lkiR+z2Lic2s3Zw==", "dev": true, "license": "MIT", "dependencies": { @@ -17227,6 +18069,26 @@ "dev": true, "license": "0BSD" }, + "node_modules/tsx": { + "version": "4.19.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.4.tgz", + "integrity": "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, "node_modules/tty-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", @@ -17276,45 +18138,67 @@ } }, "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "mime-db": "^1.54.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -17324,18 +18208,19 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" @@ -17345,18 +18230,18 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -17380,9 +18265,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -17393,6 +18278,29 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.33.1.tgz", + "integrity": "sha512-AgRnV4sKkWOiZ0Kjbnf5ytTJXMUZQ0qhSVdQtDNYLPLnjsATEYhaO94GlRQwi4t4gO8FfjM6NnikHeKjUm8D7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.33.1", + "@typescript-eslint/parser": "8.33.1", + "@typescript-eslint/utils": "8.33.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, "node_modules/uglify-js": { "version": "3.19.3", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", @@ -17408,25 +18316,28 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, @@ -17518,9 +18429,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "funding": [ { @@ -17539,7 +18450,7 @@ "license": "MIT", "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -17605,15 +18516,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", @@ -17687,9 +18589,9 @@ "license": "ISC" }, "node_modules/watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", + "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", "dev": true, "license": "MIT", "dependencies": { @@ -17717,17 +18619,18 @@ "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.96.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", - "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", + "version": "5.99.9", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.9.tgz", + "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==", "dev": true, "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.14.0", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", @@ -17741,9 +18644,9 @@ "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", + "schema-utils": "^4.3.2", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", + "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, @@ -17764,43 +18667,40 @@ } }, "node_modules/webpack-cli": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", - "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz", + "integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==", "dev": true, "license": "MIT", "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^2.1.1", - "@webpack-cli/info": "^2.0.2", - "@webpack-cli/serve": "^2.0.5", + "@discoveryjs/json-ext": "^0.6.1", + "@webpack-cli/configtest": "^3.0.1", + "@webpack-cli/info": "^3.0.1", + "@webpack-cli/serve": "^3.0.1", "colorette": "^2.0.14", - "commander": "^10.0.1", + "commander": "^12.1.0", "cross-spawn": "^7.0.3", - "envinfo": "^7.7.3", + "envinfo": "^7.14.0", "fastest-levenshtein": "^1.0.12", "import-local": "^3.0.2", "interpret": "^3.1.1", "rechoir": "^0.8.0", - "webpack-merge": "^5.7.3" + "webpack-merge": "^6.0.1" }, "bin": { "webpack-cli": "bin/cli.js" }, "engines": { - "node": ">=14.15.0" + "node": ">=18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "5.x.x" + "webpack": "^5.82.0" }, "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, "webpack-bundle-analyzer": { "optional": true }, @@ -17810,34 +18710,47 @@ } }, "node_modules/webpack-cli/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, "license": "MIT", "engines": { - "node": ">=14" + "node": ">=18" + } + }, + "node_modules/webpack-cli/node_modules/envinfo": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", + "dev": true, + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" } }, "node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", "dev": true, "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", "flat": "^5.0.2", - "wildcard": "^2.0.0" + "wildcard": "^2.0.1" }, "engines": { - "node": ">=10.0.0" + "node": ">=18.0.0" } }, "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.2.tgz", + "integrity": "sha512-ykKKus8lqlgXX/1WjudpIEjqsafjOTcOJqxnAbMLAu/KCsDCJ6GBtvscewvTkrn24HsnvFwrSCbenFrhtcCsAA==", "dev": true, "license": "MIT", "engines": { @@ -17925,33 +18838,92 @@ } }, "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/which-collection": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "license": "MIT", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, "engines": { @@ -18223,16 +19195,16 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", "dev": true, "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { - "node": ">= 14" + "node": ">= 14.6" } }, "node_modules/yargs": { @@ -18327,9 +19299,9 @@ } }, "node_modules/yocto-queue": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", - "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", + "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", "dev": true, "license": "MIT", "engines": { @@ -18340,140 +19312,153 @@ } }, "packages/csv": { - "version": "6.3.11", + "version": "6.4.1", "license": "MIT", "dependencies": { - "csv-generate": "^4.4.2", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2", - "stream-transform": "^3.3.3" + "csv-generate": "^4.5.0", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0", + "stream-transform": "^3.4.0" }, "devDependencies": { - "@eslint/js": "^9.15.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@types/mocha": "^10.0.9", - "@types/node": "^22.9.1", - "coffeescript": "~2.7.0", + "@rollup/plugin-node-resolve": "^16.0.1", + "@types/mocha": "^10.0.10", + "@types/node": "^22.15.30", "each": "^2.7.2", - "eslint": "^9.15.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-mocha": "^10.5.0", - "eslint-plugin-prettier": "^5.2.1", - "mocha": "~10.8.2", - "prettier": "^3.3.3", - "rollup": "^4.27.3", + "mocha": "~11.5.0", + "prettier": "^3.5.3", + "rollup": "^4.41.1", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "should": "~13.2.3", "ts-node": "^10.9.2", - "typescript": "^5.6.3" + "typescript": "^5.8.3" }, "engines": { "node": ">= 0.1.90" } }, "packages/csv-generate": { - "version": "4.4.2", + "version": "4.5.0", "license": "MIT", "devDependencies": { - "@eslint/js": "^9.15.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@types/mocha": "^10.0.9", - "@types/node": "^22.9.1", - "coffeescript": "~2.7.0", + "@rollup/plugin-node-resolve": "^16.0.1", + "@types/mocha": "^10.0.10", + "@types/node": "^22.15.30", + "dedent": "^1.6.0", "each": "^2.7.2", - "eslint": "^9.15.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-mocha": "^10.5.0", - "eslint-plugin-prettier": "^5.2.1", - "mocha": "~10.8.2", - "prettier": "^3.3.3", - "rollup": "^4.27.3", + "mocha": "~11.5.0", + "prettier": "^3.5.3", + "rollup": "^4.41.1", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "should": "~13.2.3", "ts-node": "^10.9.2", - "typescript": "^5.6.3" + "typescript": "^5.8.3" + } + }, + "packages/csv-generate/node_modules/dedent": { + "version": "1.6.0", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } } }, "packages/csv-parse": { - "version": "5.6.0", + "version": "6.1.0", "license": "MIT", "devDependencies": { - "@eslint/js": "^9.15.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@types/mocha": "^10.0.9", - "@types/node": "^22.9.1", - "coffeescript": "^2.7.0", - "csv-generate": "^4.4.2", + "@rollup/plugin-node-resolve": "^16.0.1", + "@types/mocha": "^10.0.10", + "@types/node": "^22.15.30", + "csv-generate": "^4.5.0", "csv-spectrum": "^2.0.0", + "dedent": "^1.6.0", "each": "^2.7.2", - "eslint": "^9.15.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-mocha": "^10.5.0", - "eslint-plugin-prettier": "^5.2.1", - "mocha": "^10.8.2", + "mocha": "^11.5.0", "pad": "^3.3.0", - "prettier": "^3.3.3", - "rollup": "^4.27.3", + "prettier": "^3.5.3", + "rollup": "^4.41.1", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "should": "^13.2.3", - "stream-transform": "^3.3.3", + "stream-transform": "^3.4.0", "ts-node": "^10.9.2", - "typescript": "^5.6.3" + "typescript": "^5.8.3" + } + }, + "packages/csv-parse/node_modules/dedent": { + "version": "1.6.0", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } } }, "packages/csv-stringify": { - "version": "6.5.2", + "version": "6.6.0", "license": "MIT", "devDependencies": { - "@eslint/js": "^9.15.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@types/mocha": "^10.0.9", - "@types/node": "^22.9.1", - "coffeescript": "~2.7.0", - "csv-generate": "^4.4.2", + "@rollup/plugin-node-resolve": "^16.0.1", + "@types/mocha": "^10.0.10", + "@types/node": "^22.15.30", + "csv-generate": "^4.5.0", + "dedent": "^1.6.0", "each": "^2.7.2", - "eslint": "^9.15.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-mocha": "^10.5.0", - "eslint-plugin-prettier": "^5.2.1", - "express": "^4.21.1", - "mocha": "~10.8.2", - "prettier": "^3.3.3", - "rollup": "^4.27.3", + "express": "^5.1.0", + "mocha": "~11.5.0", + "prettier": "^3.5.3", + "rollup": "^4.41.1", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "should": "~13.2.3", "ts-node": "^10.9.2", - "typescript": "^5.6.3" + "typescript": "^5.8.3" + } + }, + "packages/csv-stringify/node_modules/dedent": { + "version": "1.6.0", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } } }, "packages/stream-transform": { - "version": "3.3.3", + "version": "3.4.0", "license": "MIT", "devDependencies": { - "@eslint/js": "^9.15.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@types/mocha": "^10.0.9", - "@types/node": "^22.9.1", - "coffeescript": "~2.7.0", - "csv-generate": "^4.4.2", + "@rollup/plugin-node-resolve": "^16.0.1", + "@types/mocha": "^10.0.10", + "@types/node": "^22.15.30", + "csv-generate": "^4.5.0", "each": "^2.7.2", - "eslint": "^9.15.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-mocha": "^10.5.0", - "eslint-plugin-prettier": "^5.2.1", - "mocha": "~10.8.2", + "mocha": "~11.5.0", "pad": "~3.3.0", - "prettier": "^3.3.3", - "rollup": "^4.27.3", + "prettier": "^3.5.3", + "rollup": "^4.41.1", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "should": "~13.2.3", "ts-node": "^10.9.2", - "typescript": "^5.6.3" + "tsx": "^4.19.4", + "typescript": "^5.8.3" } } } diff --git a/package.json b/package.json index 31d44aed9..8af0ae7ea 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,19 @@ { "private": true, "devDependencies": { - "@commitlint/cli": "^19.6.0", - "@commitlint/config-conventional": "^19.6.0", + "@commitlint/cli": "^19.8.1", + "@commitlint/config-conventional": "^19.8.1", + "@eslint/js": "^9.28.0", "cz-conventional-changelog": "^3.3.0", - "glob": "^11.0.0", + "eslint": "^9.28.0", + "eslint-config-prettier": "^10.1.5", + "eslint-plugin-mocha": "^11.1.0", + "eslint-plugin-prettier": "^5.4.1", + "glob": "^11.0.2", "husky": "^9.1.7", - "lerna": "^8.1.9", - "lint-staged": "^15.2.10" + "lerna": "^8.2.2", + "lint-staged": "^16.1.0", + "typescript-eslint": "^8.33.1" }, "lint-staged": { "*.js": "npm run lint:fix", @@ -19,9 +25,9 @@ }, "scripts": { "build": "lerna run build", - "postinstall": "husky install", + "prepare": "husky", "publish": "lerna publish from-git --yes", - "lint:check": "lerna run lint:check", + "lint:check": "eslint", "lint:fix": "eslint --fix", "lint:staged": "npx lint-staged", "test": "lerna run test", diff --git a/packages/csv-generate/CHANGELOG.md b/packages/csv-generate/CHANGELOG.md index 2294a55b1..c08a6640a 100644 --- a/packages/csv-generate/CHANGELOG.md +++ b/packages/csv-generate/CHANGELOG.md @@ -3,6 +3,42 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 4.5.0 (2025-07-10) + +### Features + +- backport support for node 14 ([dbfeb78](https://github.com/adaltas/node-csv/commit/dbfeb78f61ed36f02936d63a53345708ca213e45)) +- backward support for node 8 ([496231d](https://github.com/adaltas/node-csv/commit/496231dfd838f0a6a72269a5a2390a4c637cef95)) +- **csv-generate:** breathe between async reads ([b1da5a1](https://github.com/adaltas/node-csv/commit/b1da5a13cf4dbbf0dd62f2e28e5dee8767ad0151)) +- **csv-generate:** set highWaterMark to default ([8e758cf](https://github.com/adaltas/node-csv/commit/8e758cf79ab8b089e9a6a80a1f06be524a208f35)) +- **csv-generate:** ts extends options with stream.ReadableOptions ([ef84fb2](https://github.com/adaltas/node-csv/commit/ef84fb2f980b5d39e2df2b61d012769119f31001)) +- **csv-generate:** types column option defined as an udf (fix [#417](https://github.com/adaltas/node-csv/issues/417)) ([65f1ace](https://github.com/adaltas/node-csv/commit/65f1aceede14e9136b347e8ef9e2019a81a51010)) +- esm migration ([b5c0d4b](https://github.com/adaltas/node-csv/commit/b5c0d4b191c8b57397808c0922a3f08248506a9f)) +- export ts types in sync ([890bf8d](https://github.com/adaltas/node-csv/commit/890bf8d950c18a05cab5e35a461d0847d9425156)) +- replace ts types with typesVersions ([acb41d5](https://github.com/adaltas/node-csv/commit/acb41d5031669f2d582e40da1c80f5fd4738fee4)) +- ts module Node16 and type declaration to exports field ([#341](https://github.com/adaltas/node-csv/issues/341)) ([4b0283d](https://github.com/adaltas/node-csv/commit/4b0283d17b7fa46daa1f87380759ba72c71ec79b)) +- wg stream api ([8a5eb7d](https://github.com/adaltas/node-csv/commit/8a5eb7dfd31b22217db4fbbc832d707221850785)) + +### Bug Fixes + +- commonjs types, run tsc and lint to validate changes ([#397](https://github.com/adaltas/node-csv/issues/397)) ([e6870fe](https://github.com/adaltas/node-csv/commit/e6870fe272c119e273196522c9771d12ff8b2a35)) +- correct exports in package.json with webpack ([154eafb](https://github.com/adaltas/node-csv/commit/154eafbac866eb4499a0d392f8dcd057695c2586)) +- **csv-demo-ts-cjs-node16:** upgrade module definition after latest typescript ([87fe919](https://github.com/adaltas/node-csv/commit/87fe91996fb2a8895c252177fca4f0cb59a518f9)) +- **csv-demo-webpack-ts:** remove polyfill ([47a99bd](https://github.com/adaltas/node-csv/commit/47a99bd944d1d943e6374227dbc4e20aaa2c8c7f)) +- **csv-demo-webpack-ts:** simplify export paths ([8d63a14](https://github.com/adaltas/node-csv/commit/8d63a14313bb6b26f13fafb740cc686f1dfaa65f)) +- **csv-generate:** catch invalid value error ([f031542](https://github.com/adaltas/node-csv/commit/f0315423ba576551f2bd08f3e1c3bc85e9003926)) +- **csv-generate:** coffee migration in sync incompatible with node < 14, fix [#289](https://github.com/adaltas/node-csv/issues/289) ([a5e14d8](https://github.com/adaltas/node-csv/commit/a5e14d82562e87c650af561ed7058bf91ef7d7f4)) +- **csv-generate:** record emited after end with sleep ([6632e63](https://github.com/adaltas/node-csv/commit/6632e63a7aff7d33f47aae91347a39649d5248c6)) +- **csv-generate:** stream.push after EOF ([97a3f58](https://github.com/adaltas/node-csv/commit/97a3f58dd73b6452b32cc39511b3ec145fe23c00)) +- dont insert polyfills in cjs [#303](https://github.com/adaltas/node-csv/issues/303) ([9baf334](https://github.com/adaltas/node-csv/commit/9baf334044dab90b4a0d096a7e456d0fd5807d5b)) +- esm exports in package.json files ([c48fe47](https://github.com/adaltas/node-csv/commit/c48fe478ced7560aa078fbc36ec33d6007111e2b)), closes [#308](https://github.com/adaltas/node-csv/issues/308) +- export original lib esm modules ([be25349](https://github.com/adaltas/node-csv/commit/be2534928ba21156e9cde1e15d2e8593d62ffe71)) +- expose browser esm modules ([eb87355](https://github.com/adaltas/node-csv/commit/eb873557c65912f065d2581d30a17a96b0bfd2d6)) +- refer to esm files in dist ([b780fbd](https://github.com/adaltas/node-csv/commit/b780fbd26f5e54494e511eb2e004d3cdedee3593)) +- remove samples from publicatgion ([12c221d](https://github.com/adaltas/node-csv/commit/12c221dc37add26f094e3bb7f94b50ee06ff5be6)) +- support ts node16 resolution in cjs ([#354](https://github.com/adaltas/node-csv/issues/354)) ([fa09d03](https://github.com/adaltas/node-csv/commit/fa09d03aaf0008b2790656871ca6b2c4be12d14c)) +- support TypeScript moduleResolution node16 ([#368](https://github.com/adaltas/node-csv/issues/368)) ([f4d7c97](https://github.com/adaltas/node-csv/commit/f4d7c97f39fb73e9d248eee21e61e7dc48015c78)) + ## [4.4.2](https://github.com/adaltas/node-csv/compare/csv-generate@4.4.1...csv-generate@4.4.2) (2024-11-21) **Note:** Version bump only for package csv-generate diff --git a/packages/csv-generate/dist/cjs/index.d.cts b/packages/csv-generate/dist/cjs/index.d.cts index c5528cfc6..86f126884 100644 --- a/packages/csv-generate/dist/cjs/index.d.cts +++ b/packages/csv-generate/dist/cjs/index.d.cts @@ -1,4 +1,3 @@ - /// import * as stream from "stream"; @@ -6,89 +5,89 @@ import * as stream from "stream"; type Callback = (err?: Error, records?: any) => void; export class Generator extends stream.Readable { - constructor(options?: Options); - - readonly options: Options; + constructor(options?: Options); + + readonly options: Options; } export type ColumnsFunctionArgs = { - options: Options; - state: State; + options: Options; + state: State; }; export type ColumnsFunction = (args: ColumnsFunctionArgs) => string; export type State = { - start_time: number, - fixed_size_buffer: number, - count_written: number, - count_created: number, -} + start_time: number; + fixed_size_buffer: number; + count_written: number; + count_created: number; +}; export interface Options extends stream.ReadableOptions { - /** - * Define the number of generated fields and the generation method. - */ - columns?: number | (string | ColumnsFunction)[]; - /** - * Set the field delimiter. - */ - delimiter?: string; - /** - * Period to run in milliseconds. - */ - duration?: number; - /** - * If specified, then buffers will be decoded to strings using the specified encoding. - */ - encoding?: BufferEncoding | undefined; - /** - * When to stop the generation. - */ - end?: number | Date; - /** - * One or multiple characters to print at the end of the file; only apply when objectMode is disabled. - */ - eof?: boolean | string; - /** - * Generate buffers equals length as defined by the `highWaterMark` option. - */ - fixed_size?: boolean; - fixedSize?: boolean; - /** - * The maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource. - */ - high_water_mark?: number; - highWaterMark?: number; - /** - * Number of lines or records to generate. - */ - length?: number; - /** - * Maximum number of characters per word. - */ - max_word_length?: number; - maxWordLength?: number; - /** - * Whether this stream should behave as a stream of objects. - */ - object_mode?: boolean - objectMode?: boolean; - /** - * One or multiple characters used to delimit records. - */ - row_delimiter?: string; - /** - * Generate idempotent random characters if a number provided. - */ - seed?: boolean | number; - /** - * The time to wait between the generation of each records - */ - sleep?: number; + /** + * Define the number of generated fields and the generation method. + */ + columns?: number | (string | ColumnsFunction)[]; + /** + * Set the field delimiter. + */ + delimiter?: string; + /** + * Period to run in milliseconds. + */ + duration?: number; + /** + * If specified, then buffers will be decoded to strings using the specified encoding. + */ + encoding?: BufferEncoding | undefined; + /** + * When to stop the generation. + */ + end?: number | Date; + /** + * One or multiple characters to print at the end of the file; only apply when objectMode is disabled. + */ + eof?: boolean | string; + /** + * Generate buffers equals length as defined by the `highWaterMark` option. + */ + fixed_size?: boolean; + fixedSize?: boolean; + /** + * The maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource. + */ + high_water_mark?: number; + highWaterMark?: number; + /** + * Number of lines or records to generate. + */ + length?: number; + /** + * Maximum number of characters per word. + */ + max_word_length?: number; + maxWordLength?: number; + /** + * Whether this stream should behave as a stream of objects. + */ + object_mode?: boolean; + objectMode?: boolean; + /** + * One or multiple characters used to delimit records. + */ + row_delimiter?: string; + /** + * Generate idempotent random characters if a number provided. + */ + seed?: boolean | number; + /** + * The time to wait between the generation of each records + */ + sleep?: number; } declare function generate(options?: Options, callback?: Callback): Generator; declare function generate(callback?: Callback): Generator; // export default generate; -export {generate}; +export { generate }; diff --git a/packages/csv-generate/dist/cjs/stream.d.cts b/packages/csv-generate/dist/cjs/stream.d.cts index d577d3d34..92fbf4b67 100644 --- a/packages/csv-generate/dist/cjs/stream.d.cts +++ b/packages/csv-generate/dist/cjs/stream.d.cts @@ -1,5 +1,4 @@ - -import { Options } from './index.cjs'; +import { Options } from "./index.cjs"; declare function generate(options?: Options): ReadableStream; // export default generate; diff --git a/packages/csv-generate/dist/cjs/sync.d.cts b/packages/csv-generate/dist/cjs/sync.d.cts index 3a415acae..591f87dc3 100644 --- a/packages/csv-generate/dist/cjs/sync.d.cts +++ b/packages/csv-generate/dist/cjs/sync.d.cts @@ -1,6 +1,7 @@ +import { Options } from "./index.cjs"; -import { Options } from './index.cjs'; - -declare function generate(options: number | Options): string & Array; +declare function generate( + options: number | Options, +): string & Array; // export default generate; export { generate, Options }; diff --git a/packages/csv-generate/dist/esm/index.d.ts b/packages/csv-generate/dist/esm/index.d.ts index c5528cfc6..86f126884 100644 --- a/packages/csv-generate/dist/esm/index.d.ts +++ b/packages/csv-generate/dist/esm/index.d.ts @@ -1,4 +1,3 @@ - /// import * as stream from "stream"; @@ -6,89 +5,89 @@ import * as stream from "stream"; type Callback = (err?: Error, records?: any) => void; export class Generator extends stream.Readable { - constructor(options?: Options); - - readonly options: Options; + constructor(options?: Options); + + readonly options: Options; } export type ColumnsFunctionArgs = { - options: Options; - state: State; + options: Options; + state: State; }; export type ColumnsFunction = (args: ColumnsFunctionArgs) => string; export type State = { - start_time: number, - fixed_size_buffer: number, - count_written: number, - count_created: number, -} + start_time: number; + fixed_size_buffer: number; + count_written: number; + count_created: number; +}; export interface Options extends stream.ReadableOptions { - /** - * Define the number of generated fields and the generation method. - */ - columns?: number | (string | ColumnsFunction)[]; - /** - * Set the field delimiter. - */ - delimiter?: string; - /** - * Period to run in milliseconds. - */ - duration?: number; - /** - * If specified, then buffers will be decoded to strings using the specified encoding. - */ - encoding?: BufferEncoding | undefined; - /** - * When to stop the generation. - */ - end?: number | Date; - /** - * One or multiple characters to print at the end of the file; only apply when objectMode is disabled. - */ - eof?: boolean | string; - /** - * Generate buffers equals length as defined by the `highWaterMark` option. - */ - fixed_size?: boolean; - fixedSize?: boolean; - /** - * The maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource. - */ - high_water_mark?: number; - highWaterMark?: number; - /** - * Number of lines or records to generate. - */ - length?: number; - /** - * Maximum number of characters per word. - */ - max_word_length?: number; - maxWordLength?: number; - /** - * Whether this stream should behave as a stream of objects. - */ - object_mode?: boolean - objectMode?: boolean; - /** - * One or multiple characters used to delimit records. - */ - row_delimiter?: string; - /** - * Generate idempotent random characters if a number provided. - */ - seed?: boolean | number; - /** - * The time to wait between the generation of each records - */ - sleep?: number; + /** + * Define the number of generated fields and the generation method. + */ + columns?: number | (string | ColumnsFunction)[]; + /** + * Set the field delimiter. + */ + delimiter?: string; + /** + * Period to run in milliseconds. + */ + duration?: number; + /** + * If specified, then buffers will be decoded to strings using the specified encoding. + */ + encoding?: BufferEncoding | undefined; + /** + * When to stop the generation. + */ + end?: number | Date; + /** + * One or multiple characters to print at the end of the file; only apply when objectMode is disabled. + */ + eof?: boolean | string; + /** + * Generate buffers equals length as defined by the `highWaterMark` option. + */ + fixed_size?: boolean; + fixedSize?: boolean; + /** + * The maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource. + */ + high_water_mark?: number; + highWaterMark?: number; + /** + * Number of lines or records to generate. + */ + length?: number; + /** + * Maximum number of characters per word. + */ + max_word_length?: number; + maxWordLength?: number; + /** + * Whether this stream should behave as a stream of objects. + */ + object_mode?: boolean; + objectMode?: boolean; + /** + * One or multiple characters used to delimit records. + */ + row_delimiter?: string; + /** + * Generate idempotent random characters if a number provided. + */ + seed?: boolean | number; + /** + * The time to wait between the generation of each records + */ + sleep?: number; } declare function generate(options?: Options, callback?: Callback): Generator; declare function generate(callback?: Callback): Generator; // export default generate; -export {generate}; +export { generate }; diff --git a/packages/csv-generate/dist/esm/index.js b/packages/csv-generate/dist/esm/index.js index 79c042d6a..4b097d02e 100644 --- a/packages/csv-generate/dist/esm/index.js +++ b/packages/csv-generate/dist/esm/index.js @@ -831,8 +831,8 @@ function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1591,7 +1591,7 @@ Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, no Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1601,7 +1601,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1614,7 +1614,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1627,7 +1627,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1642,7 +1642,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2000,7 +2000,9 @@ EventEmitter.init = function() { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2569,94 +2571,19 @@ function Item(fun, array) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; -var title = 'browser'; -var platform = 'browser'; -var browser = true; var env = {}; -var argv = []; -var version = ''; // empty string to avoid regexp issues -var versions = {}; -var release = {}; -var config = {}; - -function noop() {} - -var on = noop; -var addListener = noop; -var once = noop; -var off = noop; -var removeListener = noop; -var removeAllListeners = noop; -var emit = noop; - -function binding(name) { - throw new Error('process.binding is not supported'); -} - -function cwd () { return '/' } -function chdir (dir) { - throw new Error('process.chdir is not supported'); -}function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; -var performanceNow = - performance.now || +performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; -// generate timestamp or delta -// see http://nodejs.org/api/process.html#process_process_hrtime -function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] -} - -var startTime = new Date(); -function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; -} - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime -}; + env: env}; var inherits; if (typeof Object.create === 'function'){ diff --git a/packages/csv-generate/dist/esm/stream.d.ts b/packages/csv-generate/dist/esm/stream.d.ts index d53894a79..79188667a 100644 --- a/packages/csv-generate/dist/esm/stream.d.ts +++ b/packages/csv-generate/dist/esm/stream.d.ts @@ -1,5 +1,4 @@ - -import { Options } from './index.js'; +import { Options } from "./index.js"; declare function generate(options?: Options): ReadableStream; // export default generate; diff --git a/packages/csv-generate/dist/esm/sync.d.ts b/packages/csv-generate/dist/esm/sync.d.ts index 965ad6347..a93ff8c4a 100644 --- a/packages/csv-generate/dist/esm/sync.d.ts +++ b/packages/csv-generate/dist/esm/sync.d.ts @@ -1,6 +1,7 @@ +import { Options } from "./index.js"; -import { Options } from './index.js'; - -declare function generate(options: number | Options): string & Array; +declare function generate( + options: number | Options, +): string & Array; // export default generate; export { generate, Options }; diff --git a/packages/csv-generate/dist/esm/sync.js b/packages/csv-generate/dist/esm/sync.js index 6c0f32d1c..099a9e2f3 100644 --- a/packages/csv-generate/dist/esm/sync.js +++ b/packages/csv-generate/dist/esm/sync.js @@ -831,8 +831,8 @@ function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1591,7 +1591,7 @@ Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, no Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1601,7 +1601,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1614,7 +1614,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1627,7 +1627,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1642,7 +1642,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2000,7 +2000,9 @@ EventEmitter.init = function() { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2569,94 +2571,19 @@ function Item(fun, array) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; -var title = 'browser'; -var platform = 'browser'; -var browser = true; var env = {}; -var argv = []; -var version = ''; // empty string to avoid regexp issues -var versions = {}; -var release = {}; -var config = {}; - -function noop() {} - -var on = noop; -var addListener = noop; -var once = noop; -var off = noop; -var removeListener = noop; -var removeAllListeners = noop; -var emit = noop; - -function binding(name) { - throw new Error('process.binding is not supported'); -} - -function cwd () { return '/' } -function chdir (dir) { - throw new Error('process.chdir is not supported'); -}function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; -var performanceNow = - performance.now || +performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; -// generate timestamp or delta -// see http://nodejs.org/api/process.html#process_process_hrtime -function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] -} - -var startTime = new Date(); -function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; -} - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime -}; + env: env}; var inherits; if (typeof Object.create === 'function'){ diff --git a/packages/csv-generate/dist/iife/index.js b/packages/csv-generate/dist/iife/index.js index 2301b7b21..1b2b03a8d 100644 --- a/packages/csv-generate/dist/iife/index.js +++ b/packages/csv-generate/dist/iife/index.js @@ -834,8 +834,8 @@ var csv_generate = (function (exports) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1594,7 +1594,7 @@ var csv_generate = (function (exports) { Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1604,7 +1604,7 @@ var csv_generate = (function (exports) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1617,7 +1617,7 @@ var csv_generate = (function (exports) { Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1630,7 +1630,7 @@ var csv_generate = (function (exports) { Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1645,7 +1645,7 @@ var csv_generate = (function (exports) { Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2003,7 +2003,9 @@ var csv_generate = (function (exports) { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2572,94 +2574,19 @@ var csv_generate = (function (exports) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ diff --git a/packages/csv-generate/dist/iife/sync.js b/packages/csv-generate/dist/iife/sync.js index 9b1463a18..3ac7ad9f5 100644 --- a/packages/csv-generate/dist/iife/sync.js +++ b/packages/csv-generate/dist/iife/sync.js @@ -834,8 +834,8 @@ var csv_generate_sync = (function (exports) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1594,7 +1594,7 @@ var csv_generate_sync = (function (exports) { Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1604,7 +1604,7 @@ var csv_generate_sync = (function (exports) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1617,7 +1617,7 @@ var csv_generate_sync = (function (exports) { Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1630,7 +1630,7 @@ var csv_generate_sync = (function (exports) { Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1645,7 +1645,7 @@ var csv_generate_sync = (function (exports) { Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2003,7 +2003,9 @@ var csv_generate_sync = (function (exports) { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2572,94 +2574,19 @@ var csv_generate_sync = (function (exports) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ diff --git a/packages/csv-generate/dist/umd/index.js b/packages/csv-generate/dist/umd/index.js index 09d7900b5..4ec027e5c 100644 --- a/packages/csv-generate/dist/umd/index.js +++ b/packages/csv-generate/dist/umd/index.js @@ -837,8 +837,8 @@ byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1597,7 +1597,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1607,7 +1607,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1620,7 +1620,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1633,7 +1633,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1648,7 +1648,7 @@ Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2006,7 +2006,9 @@ this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2575,94 +2577,19 @@ Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ diff --git a/packages/csv-generate/dist/umd/sync.js b/packages/csv-generate/dist/umd/sync.js index e1d938dd5..d10aa6aac 100644 --- a/packages/csv-generate/dist/umd/sync.js +++ b/packages/csv-generate/dist/umd/sync.js @@ -837,8 +837,8 @@ byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1597,7 +1597,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1607,7 +1607,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1620,7 +1620,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1633,7 +1633,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1648,7 +1648,7 @@ Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2006,7 +2006,9 @@ this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2575,94 +2577,19 @@ Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ diff --git a/packages/csv-generate/lib/index.d.ts b/packages/csv-generate/lib/index.d.ts index c5528cfc6..86f126884 100644 --- a/packages/csv-generate/lib/index.d.ts +++ b/packages/csv-generate/lib/index.d.ts @@ -1,4 +1,3 @@ - /// import * as stream from "stream"; @@ -6,89 +5,89 @@ import * as stream from "stream"; type Callback = (err?: Error, records?: any) => void; export class Generator extends stream.Readable { - constructor(options?: Options); - - readonly options: Options; + constructor(options?: Options); + + readonly options: Options; } export type ColumnsFunctionArgs = { - options: Options; - state: State; + options: Options; + state: State; }; export type ColumnsFunction = (args: ColumnsFunctionArgs) => string; export type State = { - start_time: number, - fixed_size_buffer: number, - count_written: number, - count_created: number, -} + start_time: number; + fixed_size_buffer: number; + count_written: number; + count_created: number; +}; export interface Options extends stream.ReadableOptions { - /** - * Define the number of generated fields and the generation method. - */ - columns?: number | (string | ColumnsFunction)[]; - /** - * Set the field delimiter. - */ - delimiter?: string; - /** - * Period to run in milliseconds. - */ - duration?: number; - /** - * If specified, then buffers will be decoded to strings using the specified encoding. - */ - encoding?: BufferEncoding | undefined; - /** - * When to stop the generation. - */ - end?: number | Date; - /** - * One or multiple characters to print at the end of the file; only apply when objectMode is disabled. - */ - eof?: boolean | string; - /** - * Generate buffers equals length as defined by the `highWaterMark` option. - */ - fixed_size?: boolean; - fixedSize?: boolean; - /** - * The maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource. - */ - high_water_mark?: number; - highWaterMark?: number; - /** - * Number of lines or records to generate. - */ - length?: number; - /** - * Maximum number of characters per word. - */ - max_word_length?: number; - maxWordLength?: number; - /** - * Whether this stream should behave as a stream of objects. - */ - object_mode?: boolean - objectMode?: boolean; - /** - * One or multiple characters used to delimit records. - */ - row_delimiter?: string; - /** - * Generate idempotent random characters if a number provided. - */ - seed?: boolean | number; - /** - * The time to wait between the generation of each records - */ - sleep?: number; + /** + * Define the number of generated fields and the generation method. + */ + columns?: number | (string | ColumnsFunction)[]; + /** + * Set the field delimiter. + */ + delimiter?: string; + /** + * Period to run in milliseconds. + */ + duration?: number; + /** + * If specified, then buffers will be decoded to strings using the specified encoding. + */ + encoding?: BufferEncoding | undefined; + /** + * When to stop the generation. + */ + end?: number | Date; + /** + * One or multiple characters to print at the end of the file; only apply when objectMode is disabled. + */ + eof?: boolean | string; + /** + * Generate buffers equals length as defined by the `highWaterMark` option. + */ + fixed_size?: boolean; + fixedSize?: boolean; + /** + * The maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource. + */ + high_water_mark?: number; + highWaterMark?: number; + /** + * Number of lines or records to generate. + */ + length?: number; + /** + * Maximum number of characters per word. + */ + max_word_length?: number; + maxWordLength?: number; + /** + * Whether this stream should behave as a stream of objects. + */ + object_mode?: boolean; + objectMode?: boolean; + /** + * One or multiple characters used to delimit records. + */ + row_delimiter?: string; + /** + * Generate idempotent random characters if a number provided. + */ + seed?: boolean | number; + /** + * The time to wait between the generation of each records + */ + sleep?: number; } declare function generate(options?: Options, callback?: Callback): Generator; declare function generate(callback?: Callback): Generator; // export default generate; -export {generate}; +export { generate }; diff --git a/packages/csv-generate/lib/stream.d.ts b/packages/csv-generate/lib/stream.d.ts index d53894a79..79188667a 100644 --- a/packages/csv-generate/lib/stream.d.ts +++ b/packages/csv-generate/lib/stream.d.ts @@ -1,5 +1,4 @@ - -import { Options } from './index.js'; +import { Options } from "./index.js"; declare function generate(options?: Options): ReadableStream; // export default generate; diff --git a/packages/csv-generate/lib/sync.d.ts b/packages/csv-generate/lib/sync.d.ts index 965ad6347..a93ff8c4a 100644 --- a/packages/csv-generate/lib/sync.d.ts +++ b/packages/csv-generate/lib/sync.d.ts @@ -1,6 +1,7 @@ +import { Options } from "./index.js"; -import { Options } from './index.js'; - -declare function generate(options: number | Options): string & Array; +declare function generate( + options: number | Options, +): string & Array; // export default generate; export { generate, Options }; diff --git a/packages/csv-generate/package.json b/packages/csv-generate/package.json index cf9a0e295..91d520f45 100644 --- a/packages/csv-generate/package.json +++ b/packages/csv-generate/package.json @@ -1,5 +1,5 @@ { - "version": "4.4.2", + "version": "4.5.0", "name": "csv-generate", "description": "CSV and object generation implementing the Node.js `stream.Readable` API", "keywords": [ @@ -13,24 +13,19 @@ "bugs": "https://github.com/adaltas/node-csv-generate/issues", "author": "David Worms (https://www.adaltas.com)", "devDependencies": { - "@eslint/js": "^9.15.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@types/mocha": "^10.0.9", - "@types/node": "^22.9.1", - "coffeescript": "~2.7.0", + "@rollup/plugin-node-resolve": "^16.0.1", + "@types/mocha": "^10.0.10", + "@types/node": "^22.15.30", + "dedent": "^1.6.0", "each": "^2.7.2", - "eslint": "^9.15.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-mocha": "^10.5.0", - "eslint-plugin-prettier": "^5.2.1", - "mocha": "~10.8.2", - "prettier": "^3.3.3", - "rollup": "^4.27.3", + "mocha": "~11.5.0", + "prettier": "^3.5.3", + "rollup": "^4.41.1", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "should": "~13.2.3", "ts-node": "^10.9.2", - "typescript": "^5.6.3" + "typescript": "^5.8.3" }, "exports": { ".": { @@ -81,19 +76,12 @@ "main": "./dist/cjs/index.cjs", "mocha": { "inline-diffs": true, - "loader": "./test/loaders/all.js", + "loader": "ts-node/esm", "recursive": true, "reporter": "spec", - "require": [ - "should" - ], "throw-deprecation": false, "timeout": 40000 }, - "lint-staged": { - "*.js": "npm run lint:fix", - "*.md": "prettier -w" - }, "repository": { "type": "git", "url": "https://github.com/adaltas/node-csv.git", @@ -108,8 +96,8 @@ "lint:fix": "eslint --fix", "lint:ts": "tsc --noEmit true", "preversion": "npm run build && git add dist", - "test": "mocha 'test/**/*.{coffee,ts}'", - "test:legacy": "mocha --ignore test/api.web_stream.coffee --loader=./test/loaders/legacy/all.js 'test/**/*.{coffee,ts}'" + "test": "mocha 'test/**/*.{js,ts}'", + "test:legacy": "mocha --ignore test/api.web_stream.js 'test/**/*.{js,ts}'" }, "type": "module", "types": "dist/esm/index.d.ts", diff --git a/packages/csv-generate/test/api.callback.coffee b/packages/csv-generate/test/api.callback.coffee deleted file mode 100644 index 349016aad..000000000 --- a/packages/csv-generate/test/api.callback.coffee +++ /dev/null @@ -1,18 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'api callback', -> - - it 'receive a buffer', (next) -> - count = 0 - ended = false - generate length: 3, (err, data) -> - Buffer.isBuffer(data).should.be.true() unless err - next() - - it 'receive a string if encoding is defined', (next) -> - count = 0 - ended = false - generate length: 3, encoding: 'utf8', (err, data) -> - (typeof data is 'string').should.be.true() unless err - next() diff --git a/packages/csv-generate/test/api.callback.js b/packages/csv-generate/test/api.callback.js new file mode 100644 index 000000000..7894fb0c9 --- /dev/null +++ b/packages/csv-generate/test/api.callback.js @@ -0,0 +1,18 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("api callback", function () { + it("receive a buffer", function (next) { + generate({ length: 3 }, (err, data) => { + if (!err) Buffer.isBuffer(data).should.be.true(); + next(); + }); + }); + + it("receive a string if encoding is defined", function (next) { + generate({ length: 3, encoding: "utf8" }, (err, data) => { + if (!err) (typeof data === "string").should.be.true(); + next(); + }); + }); +}); diff --git a/packages/csv-generate/test/api.end.coffee b/packages/csv-generate/test/api.end.coffee deleted file mode 100644 index 93421cb60..000000000 --- a/packages/csv-generate/test/api.end.coffee +++ /dev/null @@ -1,48 +0,0 @@ - -import { generate } from '../lib/index.js' -import { Writable } from 'stream' - -describe 'api end', -> - - it 'no chunk generated after end', (next) -> - count = 0 - generator = generate() - generator.on 'readable', -> - while(generator.read()) - if end - generator.emit 'error', Error 'Record emited after end' - if count++ is 5 - end = true - generator.end() - generator.on 'error', next - generator.on 'end', next - - it 'no record generated after end', (next) -> - count = 0 - generator = generate objectMode: true - generator.on 'readable', -> - while(generator.read()) - if end - generator.emit 'error', Error 'Record emited after end' - if count++ is 5 - end = true - generator.end() - generator.on 'error', next - generator.on 'end', next - - it 'sync read text', (next) -> - # This bug is only reproduced in objectMode, message is - # `Uncaught Error [ERR_STREAM_PUSH_AFTER_EOF]: stream.push() after EOF` - # when the internal data stack contains more than one element - # and the internal `end` property was set before the latest record were send - myReadable = new Writable - objectMode: true - write: (chunk, encoding, callback) -> - callback() - generator = generate length: 2, objectMode: true, highWaterMark: 10, columns: [ - (g) -> 'value' - ] - # generator = generate length: 2, objectMode: true, highWaterMark: 10 - # body... - generator.pipe(myReadable).on 'finish', -> - setTimeout next, 1000 diff --git a/packages/csv-generate/test/api.end.js b/packages/csv-generate/test/api.end.js new file mode 100644 index 000000000..86a65e039 --- /dev/null +++ b/packages/csv-generate/test/api.end.js @@ -0,0 +1,61 @@ +import "should"; +import { generate } from "../lib/index.js"; +import { Writable } from "stream"; + +describe("api end", function () { + it("no chunk generated after end", function (next) { + let count = 0; + let end; + const generator = generate(); + generator.on("readable", () => { + while (generator.read()) { + if (end) { + generator.emit("error", Error("Record emited after end")); + } + if (count++ === 5) { + end = true; + generator.end(); + } + } + }); + generator.on("error", next); + generator.on("end", next); + }); + + it("no record generated after end", function (next) { + let count = 0; + let end; + const generator = generate({ objectMode: true }); + generator.on("readable", () => { + while (generator.read()) { + if (end) { + generator.emit("error", Error("Record emited after end")); + } + if (count++ === 5) { + end = true; + generator.end(); + } + } + }); + generator.on("error", next); + generator.on("end", next); + }); + + it("sync read text", function (next) { + const myReadable = new Writable({ + objectMode: true, + write: (chunk, encoding, callback) => { + callback(); + }, + }); + const generator = generate({ + length: 2, + objectMode: true, + highWaterMark: 10, + columns: [() => "value"], + }); + generator.pipe(myReadable).on("finish", () => { + setTimeout(next, 1000); + }); + }); +}); diff --git a/packages/csv-generate/test/api.highWaterMark.coffee b/packages/csv-generate/test/api.highWaterMark.coffee deleted file mode 100644 index d7c6a292f..000000000 --- a/packages/csv-generate/test/api.highWaterMark.coffee +++ /dev/null @@ -1,20 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'api highWaterMark', -> - - it 'honors option', (next) -> - values = [] - generator = generate length: 100, highWaterMark: 100 - generator.on 'readable', -> - while row = generator.read() - values.push row.length - generator.on 'error', next - generator.on 'end', -> - # we dont test first and last values: - # First time, length is twice the highWaterMark - # Last time, length is only what's left - values.shift() - values.pop() - for value in values then value.should.be.within 100, 250 - next() diff --git a/packages/csv-generate/test/api.highWaterMark.js b/packages/csv-generate/test/api.highWaterMark.js new file mode 100644 index 000000000..add1a5acd --- /dev/null +++ b/packages/csv-generate/test/api.highWaterMark.js @@ -0,0 +1,24 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("api highWaterMark", function () { + it("honors option", function (next) { + const values = []; + const generator = generate({ length: 100, highWaterMark: 100 }); + generator.on("readable", () => { + let row; + while ((row = generator.read())) { + values.push(row.length); + } + }); + generator.on("error", next); + generator.on("end", () => { + values.shift(); + values.pop(); + for (const value of values) { + value.should.be.within(100, 250); + } + next(); + }); + }); +}); diff --git a/packages/csv-generate/test/api.pipe.coffee b/packages/csv-generate/test/api.pipe.coffee deleted file mode 100644 index c4fec26d5..000000000 --- a/packages/csv-generate/test/api.pipe.coffee +++ /dev/null @@ -1,25 +0,0 @@ - -import stream from 'stream' -import util from 'util' -import { generate } from '../lib/index.js' - -describe 'api pipe', -> - - it 'to a custom writer', (next) -> - @timeout 1000000 - Writer = -> - stream.Writable.call @ - @_data = '' - @ - util.inherits Writer, stream.Writable - Writer.prototype._write = (chunk, encoding, callback) -> - @_data += chunk.toString() - callback() - writer = new Writer - writer.on 'finish', -> - writer - ._data.split('\n') - .length.should.eql 3 - next() - generator = generate length: 3 - generator.pipe writer diff --git a/packages/csv-generate/test/api.pipe.js b/packages/csv-generate/test/api.pipe.js new file mode 100644 index 000000000..9c453eb3d --- /dev/null +++ b/packages/csv-generate/test/api.pipe.js @@ -0,0 +1,27 @@ +import "should"; +import stream from "stream"; +import util from "util"; +import { generate } from "../lib/index.js"; + +describe("api pipe", function () { + it("to a custom writer", function (next) { + this.timeout(1000000); + const Writer = function () { + stream.Writable.call(this); + this._data = ""; + return this; + }; + util.inherits(Writer, stream.Writable); + Writer.prototype._write = function (chunk, encoding, callback) { + this._data += chunk.toString(); + callback(); + }; + const writer = new Writer(); + writer.on("finish", () => { + writer._data.split("\n").length.should.eql(3); + next(); + }); + const generator = generate({ length: 3 }); + generator.pipe(writer); + }); +}); diff --git a/packages/csv-generate/test/api.read.coffee b/packages/csv-generate/test/api.read.coffee deleted file mode 100644 index f4a969f5d..000000000 --- a/packages/csv-generate/test/api.read.coffee +++ /dev/null @@ -1,63 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'api read', -> - - it 'sync read text', (next) -> - buffers = [] - generator = generate length: 5, seed: 1, columns: 2 - generator.on 'readable', -> - while buffer = generator.read() - Buffer.isBuffer buffer - buffers.push buffer - generator.on 'error', next - generator.on 'end', -> - Buffer.concat(buffers).toString().should.eql """ - OMH,ONKCHhJmjadoA - D,GeACHiN - nnmiN,CGfDKB - NIl,JnnmjadnmiNL - KB,dmiM - """ - next() - - it 'sync read objects', (next) -> - rows = [] - generator = generate length: 5, objectMode: true, seed: 1, columns: 2 - generator.on 'readable', -> - while row = generator.read() - rows.push row - generator.on 'error', next - generator.on 'end', -> - rows.should.eql [ - [ 'OMH', 'ONKCHhJmjadoA' ] - [ 'D', 'GeACHiN' ] - [ 'nnmiN', 'CGfDKB' ] - [ 'NIl', 'JnnmjadnmiNL' ] - [ 'KB', 'dmiM' ] - ] - next() - - it 'async read', (next) -> - @timeout 0 - rows = [] - generator = generate length: 5, objectMode: true, seed: 1, columns: 2 - generator.on 'readable', -> - length = 0 - run = -> - row = generator.read() - return unless row - length += row.join('').length - rows.push row - setTimeout run, 10 - run() - generator.on 'error', next - generator.on 'end', -> - rows.should.eql [ - [ 'OMH', 'ONKCHhJmjadoA' ] - [ 'D', 'GeACHiN' ] - [ 'nnmiN', 'CGfDKB' ] - [ 'NIl', 'JnnmjadnmiNL' ] - [ 'KB', 'dmiM' ] - ] - next() diff --git a/packages/csv-generate/test/api.read.js b/packages/csv-generate/test/api.read.js new file mode 100644 index 000000000..e8700ec9c --- /dev/null +++ b/packages/csv-generate/test/api.read.js @@ -0,0 +1,90 @@ +import "should"; +import dedent from "dedent"; +import { generate } from "../lib/index.js"; + +describe("api read", function () { + it("sync read text", function (next) { + const buffers = []; + const generator = generate({ length: 5, seed: 1, columns: 2 }); + generator.on("readable", () => { + let buffer; + while ((buffer = generator.read())) { + Buffer.isBuffer(buffer); + buffers.push(buffer); + } + }); + generator.on("error", next); + generator.on("end", () => { + Buffer.concat(buffers) + .toString() + .should.eql( + dedent` + OMH,ONKCHhJmjadoA + D,GeACHiN + nnmiN,CGfDKB + NIl,JnnmjadnmiNL + KB,dmiM + `, + ); + next(); + }); + }); + + it("sync read objects", function (next) { + const rows = []; + const generator = generate({ + length: 5, + objectMode: true, + seed: 1, + columns: 2, + }); + generator.on("readable", () => { + let row; + while ((row = generator.read())) { + rows.push(row); + } + }); + generator.on("error", next); + generator.on("end", () => { + rows.should.eql([ + ["OMH", "ONKCHhJmjadoA"], + ["D", "GeACHiN"], + ["nnmiN", "CGfDKB"], + ["NIl", "JnnmjadnmiNL"], + ["KB", "dmiM"], + ]); + next(); + }); + }); + + it("async read", function (next) { + this.timeout(0); + const rows = []; + const generator = generate({ + length: 5, + objectMode: true, + seed: 1, + columns: 2, + }); + generator.on("readable", () => { + const run = () => { + const row = generator.read(); + if (!row) return; + rows.push(row); + setTimeout(run, 10); + }; + run(); + }); + generator.on("error", next); + generator.on("end", () => { + rows.should.eql([ + ["OMH", "ONKCHhJmjadoA"], + ["D", "GeACHiN"], + ["nnmiN", "CGfDKB"], + ["NIl", "JnnmjadnmiNL"], + ["KB", "dmiM"], + ]); + next(); + }); + }); +}); diff --git a/packages/csv-generate/test/api.sync.coffee b/packages/csv-generate/test/api.sync.coffee deleted file mode 100644 index 264b42d9f..000000000 --- a/packages/csv-generate/test/api.sync.coffee +++ /dev/null @@ -1,23 +0,0 @@ - -import {generate} from '../lib/sync.js' - -describe 'api sync', -> - - it 'throw error if options isnt provided', -> - (-> generate()).should.throw 'Invalid Argument: options must be an object or an integer' - (-> generate 3.14).should.throw 'Invalid Argument: options must be an object or an integer' - - it 'throw error if length isnt provided', -> - (-> generate({})).should.throw 'Invalid Argument: length is not defined' - - it 'accept length as an integer', -> - data = generate 1000 - data.split(/\n/).length.should.eql 1000 - - it 'accept length as a string integer', -> - data = generate '1000' - data.split(/\n/).length.should.eql 1000 - - it 'honors objectMode', -> - data = generate length: 1000, objectMode: true - data.length.should.eql 1000 diff --git a/packages/csv-generate/test/api.sync.js b/packages/csv-generate/test/api.sync.js new file mode 100644 index 000000000..c7caf64ba --- /dev/null +++ b/packages/csv-generate/test/api.sync.js @@ -0,0 +1,34 @@ +import "should"; +import { generate } from "../lib/sync.js"; + +describe("api sync", function () { + it("throw error if options isnt provided", function () { + (() => generate()).should.throw( + "Invalid Argument: options must be an object or an integer", + ); + (() => generate(3.14)).should.throw( + "Invalid Argument: options must be an object or an integer", + ); + }); + + it("throw error if length isnt provided", function () { + (() => generate({})).should.throw( + "Invalid Argument: length is not defined", + ); + }); + + it("accept length as an integer", function () { + const data = generate(1000); + data.split(/\n/).length.should.eql(1000); + }); + + it("accept length as a string integer", function () { + const data = generate("1000"); + data.split(/\n/).length.should.eql(1000); + }); + + it("honors objectMode", function () { + const data = generate({ length: 1000, objectMode: true }); + data.length.should.eql(1000); + }); +}); diff --git a/packages/csv-generate/test/api.types.sync.ts b/packages/csv-generate/test/api.types.sync.ts index 6c1fc9ac7..900a2df17 100644 --- a/packages/csv-generate/test/api.types.sync.ts +++ b/packages/csv-generate/test/api.types.sync.ts @@ -1,38 +1,38 @@ +import "should"; +import { generate, Options } from "../lib/sync.js"; -import 'should' -import { generate, Options } from '../lib/sync.js' +describe("API Types", function () { + describe("usage", function () { + it("sync with options as number", function () { + const generator: string = generate(1); + generator.should.be.a.String(); + }); -describe('API Types', () => { - - describe('usage', () => { - - it('sync with options as number', () => { - const generator: string = generate(1) - generator.should.be.a.String() - }) - - it('sync with options in string mode', () => { - const generator: string = generate({length: 1}) - generator.should.be.a.String() - }) - - it('sync with options in object mode', () => { - const generator: Array> = generate({length: 1, objectMode: true}) - generator.should.be.an.Array() - }) - }) + it("sync with options in string mode", function () { + const generator: string = generate({ length: 1 }); + generator.should.be.a.String(); + }); - describe('types', () => { - it('generate', () => { - const generator: string = generate(1) + it("sync with options in object mode", function () { + const generator: Array> = generate({ + length: 1, + objectMode: true, + }); + generator.should.be.an.Array(); + }); + }); + + describe("types", function () { + it("generate", function () { + const generator: string = generate(1); return generator; - }) - it('Options', () => { + }); + + it("Options", function () { const options: Options = { - columns: 1 - } + columns: 1, + }; return options; - }) - }) - -}) + }); + }); +}); diff --git a/packages/csv-generate/test/api.types.ts b/packages/csv-generate/test/api.types.ts index 661ab80da..b70ab344c 100644 --- a/packages/csv-generate/test/api.types.ts +++ b/packages/csv-generate/test/api.types.ts @@ -1,128 +1,130 @@ +import "should"; +import { generate, Options, Generator } from "../lib/index.js"; -import 'should' -import { generate, Options, Generator } from '../lib/index.js' - -describe('API Types', () => { - - describe('Initialisation', () => { - - it('stream', () => { +describe("API Types", function () { + describe("Initialisation", function () { + it("stream", function () { // With callback - const generator: Generator = generate() - generator.destroy() - generator.should.be.an.Object() + const generator: Generator = generate(); + generator.destroy(); + generator.should.be.an.Object(); // With callback - generate( (err, records) => err || records ).destroy() + generate((err, records) => err || records).destroy(); // With options + callback - generate( {length: 1}, (err, records) => err || records ) - }) - - }) - - describe('Generator', () => { - - it('Expose options', () => { - const generator: Generator = generate() - const options: Options = generator.options - const keys: any = Object.keys(options) - keys.sort().should.eql([ - 'columns', 'delimiter', 'duration', 'encoding', 'end', 'eof', - 'fixedSize', 'length', 'maxWordLength', - 'rowDelimiter', 'seed', 'sleep' - ]) - }) - - it('Receive Callback', (next) => { - generate({length: 3}, function(err: Error | undefined, data: object){ - if(err !== undefined){ - data.should.be.an.Object() + generate({ length: 1 }, (err, records) => err || records); + }); + }); + + describe("Generator", function () { + it("Expose options", function () { + const generator: Generator = generate(); + const options: Options = generator.options; + const keys = Object.keys(options); + keys + .sort() + .should.eql([ + "columns", + "delimiter", + "duration", + "encoding", + "end", + "eof", + "fixedSize", + "length", + "maxWordLength", + "rowDelimiter", + "seed", + "sleep", + ]); + }); + + it("Receive Callback", function (next) { + generate({ length: 3 }, function (err: Error | undefined, data: object) { + if (err !== undefined) { + data.should.be.an.Object(); } - next(err) - }) - }) - - }) - - describe('Options', () => { - - it('columns', () => { - const options: Options = {} - options.columns = 8 + next(err); + }); + }); + }); + + describe("Options", function () { + it("columns", function () { + const options: Options = {}; + options.columns = 8; options.columns = [ "ascii", "bool", "int", ({ options, state }) => options.delimiter + "ok" + state.start_time, ]; - }) - - it('delimiter', () => { - const options: Options = {} - options.delimiter = '|' - }) - - it('duration', () => { - const options: Options = {} - options.duration = 1000 - }) - - it('encoding', () => { - const options: Options = {} - options.encoding = 'utf8' - }) - - it('end', () => { - const options: Options = {} - options.end = 1000 - options.end = new Date() - }) - - it('eof', () => { - const options: Options = {} - options.eof = true - options.eof = '\n' - }) - - it('fixed_size', () => { - const options: Options = {} - options.fixed_size = true - }) - - it('high_water_mark', () => { - const options: Options = {} - options.high_water_mark = 1024 - }) - - it('length', () => { - const options: Options = {} - options.length = 100 - }) - - it('max_word_length', () => { - const options: Options = {} - options.length = 10 - }) - - it('object_mode', () => { - const options: Options = {} - options.object_mode = true - }) - - it('row_delimiter', () => { - const options: Options = {} - options.row_delimiter = ';' - }) - - it('seed', () => { - const options: Options = {} - options.seed = 10 - }) - - it('sleep', () => { - const options: Options = {} - options.sleep = 1000 - }) - - }) - -}) + }); + + it("delimiter", function () { + const options: Options = {}; + options.delimiter = "|"; + }); + + it("duration", function () { + const options: Options = {}; + options.duration = 1000; + }); + + it("encoding", function () { + const options: Options = {}; + options.encoding = "utf8"; + }); + + it("end", function () { + const options: Options = {}; + options.end = 1000; + options.end = new Date(); + }); + + it("eof", function () { + const options: Options = {}; + options.eof = true; + options.eof = "\n"; + }); + + it("fixed_size", function () { + const options: Options = {}; + options.fixed_size = true; + }); + + it("high_water_mark", function () { + const options: Options = {}; + options.high_water_mark = 1024; + }); + + it("length", function () { + const options: Options = {}; + options.length = 100; + }); + + it("max_word_length", function () { + const options: Options = {}; + options.length = 10; + }); + + it("object_mode", function () { + const options: Options = {}; + options.object_mode = true; + }); + + it("row_delimiter", function () { + const options: Options = {}; + options.row_delimiter = ";"; + }); + + it("seed", function () { + const options: Options = {}; + options.seed = 10; + }); + + it("sleep", function () { + const options: Options = {}; + options.sleep = 1000; + }); + }); +}); diff --git a/packages/csv-generate/test/api.web_stream.coffee b/packages/csv-generate/test/api.web_stream.coffee deleted file mode 100644 index 5a0d979f6..000000000 --- a/packages/csv-generate/test/api.web_stream.coffee +++ /dev/null @@ -1,52 +0,0 @@ - -import {generate as generateStream} from '../lib/stream.js' -import {generate as generateClassic} from '../lib/index.js' - -describe 'api stream', -> - - it.skip 'perf classic', -> - console.time('classic') - generator = generateClassic({ - objectMode: true, - length: 10000000 - }) - for await record from generator - continue - console.timeEnd('classic') - - it.skip 'perf stream', -> - console.time('stream') - generator = generateStream({ - objectMode: true, - length: 10000000 - }) - reader = generator.getReader() - while true - { done, value } = await reader.read() - break if done - # for await chunk from generator.getReader().read() - # console.log(Buffer.from(chunk).toString()); - console.timeEnd('stream') - - it 'perf stream with iterator', -> - generator = generateStream({ - objectMode: true, - length: 10 - }) - records = [] - for await record from generator - records.push record - records.length.should.eql 10 - - it 'perf stream with reader', -> - generator = generateStream({ - objectMode: true, - length: 10 - }) - records = [] - reader = generator.getReader() - while true - { done, record } = await reader.read() - break if done - records.push record - records.length.should.eql 10 diff --git a/packages/csv-generate/test/api.web_stream.js b/packages/csv-generate/test/api.web_stream.js new file mode 100644 index 000000000..df49f5db6 --- /dev/null +++ b/packages/csv-generate/test/api.web_stream.js @@ -0,0 +1,59 @@ +import "should"; +import { generate as generateStream } from "../lib/stream.js"; +import { generate as generateClassic } from "../lib/index.js"; + +describe("api stream", function () { + it.skip("perf classic", async function () { + console.time("classic"); + const generator = generateClassic({ + objectMode: true, + length: 10000000, + }); + for await (const record of generator) { + record; + continue; + } + console.timeEnd("classic"); + }); + + it.skip("perf stream", async function () { + console.time("stream"); + const generator = generateStream({ + objectMode: true, + length: 10000000, + }); + const reader = generator.getReader(); + while (true) { + const { done } = await reader.read(); + if (done) break; + } + console.timeEnd("stream"); + }); + + it("perf stream with iterator", async function () { + const generator = generateStream({ + objectMode: true, + length: 10, + }); + const records = []; + for await (const record of generator) { + records.push(record); + } + records.length.should.eql(10); + }); + + it("perf stream with reader", async function () { + const generator = generateStream({ + objectMode: true, + length: 10, + }); + const records = []; + const reader = generator.getReader(); + while (true) { + const { done, record } = await reader.read(); + if (done) break; + records.push(record); + } + records.length.should.eql(10); + }); +}); diff --git a/packages/csv-generate/test/event.end.coffee b/packages/csv-generate/test/event.end.coffee deleted file mode 100644 index 543417f17..000000000 --- a/packages/csv-generate/test/event.end.coffee +++ /dev/null @@ -1,17 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'event end', -> - - it 'with fixed_size', (next) -> - count = 0 - ended = false - generator = generate() - generator.on 'readable', -> - while(data = generator.read()) - ended.should.be.false() - if count++ is 100 - ended = true - generator.end() - generator.on 'error', next - generator.on 'end', next diff --git a/packages/csv-generate/test/event.end.js b/packages/csv-generate/test/event.end.js new file mode 100644 index 000000000..18ce58716 --- /dev/null +++ b/packages/csv-generate/test/event.end.js @@ -0,0 +1,21 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("event end", function () { + it("with fixed_size", function (next) { + let count = 0; + let ended = false; + const generator = generate(); + generator.on("readable", () => { + while (generator.read()) { + ended.should.be.false(); + if (count++ === 100) { + ended = true; + generator.end(); + } + } + }); + generator.on("error", next); + generator.on("end", next); + }); +}); diff --git a/packages/csv-generate/test/loaders/all.js b/packages/csv-generate/test/loaders/all.js deleted file mode 100644 index 4e81c3449..000000000 --- a/packages/csv-generate/test/loaders/all.js +++ /dev/null @@ -1,15 +0,0 @@ -import * as coffee from "./coffee.js"; -import * as ts from "ts-node/esm"; - -const coffeeRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; -const tsRegex = /\.ts$/; - -export function load(url, context, next) { - if (coffeeRegex.test(url)) { - return coffee.load.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.load.apply(this, arguments); - } - return next(url, context, next); -} diff --git a/packages/csv-generate/test/loaders/coffee.js b/packages/csv-generate/test/loaders/coffee.js deleted file mode 100644 index 75b15abe0..000000000 --- a/packages/csv-generate/test/loaders/coffee.js +++ /dev/null @@ -1,20 +0,0 @@ -import CoffeeScript from "coffeescript"; - -// See https://github.com/nodejs/node/issues/36396 -const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; - -export async function load(url, context, next) { - if (extensionsRegex.test(url)) { - const format = "module"; - const { source: rawSource } = await next(url, { format }); - const source = CoffeeScript.compile(rawSource.toString(), { - bare: true, - inlineMap: true, - filename: url, - header: false, - sourceMap: false, - }); - return { format, source }; - } - return next(url, context); -} diff --git a/packages/csv-generate/test/loaders/legacy/all.js b/packages/csv-generate/test/loaders/legacy/all.js deleted file mode 100644 index f5e57e542..000000000 --- a/packages/csv-generate/test/loaders/legacy/all.js +++ /dev/null @@ -1,36 +0,0 @@ -import * as coffee from "./coffee.js"; -import * as ts from "ts-node/esm"; - -const coffeeRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; -const tsRegex = /\.ts$/; - -export function resolve(specifier) { - if (coffeeRegex.test(specifier)) { - return coffee.resolve.apply(this, arguments); - } - if (tsRegex.test(specifier)) { - return ts.resolve.apply(this, arguments); - } - return ts.resolve.apply(this, arguments); -} - -export function getFormat(url) { - if (coffeeRegex.test(url)) { - return coffee.getFormat.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.getFormat.apply(this, arguments); - } - return ts.getFormat.apply(this, arguments); -} - -export function transformSource(source, context) { - const { url } = context; - if (coffeeRegex.test(url)) { - return coffee.transformSource.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.transformSource.apply(this, arguments); - } - return ts.transformSource.apply(this, arguments); -} diff --git a/packages/csv-generate/test/loaders/legacy/coffee.js b/packages/csv-generate/test/loaders/legacy/coffee.js deleted file mode 100644 index 6a9975db9..000000000 --- a/packages/csv-generate/test/loaders/legacy/coffee.js +++ /dev/null @@ -1,50 +0,0 @@ -// coffeescript-loader.mjs -import { URL, pathToFileURL } from "url"; -import CoffeeScript from "coffeescript"; -import { cwd } from "process"; - -const baseURL = pathToFileURL(`${cwd()}/`).href; - -// CoffeeScript files end in .coffee, .litcoffee or .coffee.md. -const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; - -export function resolve(specifier, context, defaultResolve) { - const { parentURL = baseURL } = context; - // Node.js normally errors on unknown file extensions, so return a URL for - // specifiers ending in the CoffeeScript file extensions. - if (extensionsRegex.test(specifier)) { - return { - url: new URL(specifier, parentURL).href, - stop: true, - }; - } - // Let Node.js handle all other specifiers. - return defaultResolve(specifier, context, defaultResolve); -} - -export function getFormat(url, context, defaultGetFormat) { - // Now that we patched resolve to let CoffeeScript URLs through, we need to - // tell Node.js what format such URLs should be interpreted as. For the - // purposes of this loader, all CoffeeScript URLs are ES modules. - if (extensionsRegex.test(url)) { - return { - format: "module", - stop: true, - }; - } - // Let Node.js handle all other URLs. - return defaultGetFormat(url, context, defaultGetFormat); -} - -export function transformSource(source, context, defaultTransformSource) { - const { url } = context; - - if (extensionsRegex.test(url)) { - return { - source: CoffeeScript.compile(String(source), { bare: true }), - }; - } - - // Let Node.js handle all other sources. - return defaultTransformSource(source, context, defaultTransformSource); -} diff --git a/packages/csv-generate/test/options.coffee b/packages/csv-generate/test/options.coffee deleted file mode 100644 index 3e1330f0f..000000000 --- a/packages/csv-generate/test/options.coffee +++ /dev/null @@ -1,14 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'Options', -> - - it 'no options with default', (next) -> - @timeout 1000000 - count = 0 - generator = generate() - generator.on 'readable', -> - while d = generator.read() - generator.end() if count++ is 100 - generator.on 'error', next - generator.on 'end', next diff --git a/packages/csv-generate/test/options.columns.coffee b/packages/csv-generate/test/options.columns.coffee deleted file mode 100644 index c654dd7d6..000000000 --- a/packages/csv-generate/test/options.columns.coffee +++ /dev/null @@ -1,114 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'Option `columns`', -> - - it 'as number', (next) -> - @timeout 1000000 - count = 0 - data = [] - generator = generate columns: 3 - generator.on 'readable', -> - while d = generator.read() - data.push d - if count++ is 2 - generator.end() - generator.on 'error', next - generator.on 'end', -> - data - .join('').split('\n')[1].split(',') - .length.should.eql 3 - next() - - it 'as types', (next) -> - @timeout 1000000 - count = 0 - data = [] - generator = generate columns: ['int', 'bool'], seed: 1 - generator.on 'readable', -> - while d = generator.read() - data.push d - if count++ is 2 - generator.end() - generator.on 'error', next - generator.on 'end', -> - data - .join('').split('\n')[1].split(',') - .should.eql ['1790016367053545', '0'] - next() - - it 'validate types', (next) -> - try - generate columns: ['int', 'bool', 'invalid'] - catch err - err.message.should.eql 'Invalid column type: got "invalid", default values are ["ascii","int","bool"]' - next() - - describe 'user function', -> - - it 'accept string or null or number', (next) -> - @timeout 1000000 - data = [] - generator = generate length: 1, columns: [ - -> 'a' - -> null - -> 1 - ] - generator.on 'readable', -> - while d = generator.read() - data.push d.toString() - generator.on 'error', next - generator.on 'end', -> - data.should.eql ['a,,1'] - next() - - it 'validate return argument', (next) -> - @timeout 1000000 - generator = generate objectMode: true, columns: [ - -> {} - ] - generator.on 'readable', -> - while d = generator.read() then true - generator.on 'error', (err) -> - err.message.should.eql [ - 'INVALID_VALUE:' - 'values returned by column function must be' - 'a string, a number or null,' - 'got {}' - ].join ' ' - next() - generator.on 'end', -> next Error('Oh no') - - it 'validate arguments in objectMode', (next) -> - @timeout 1000000 - data = [] - generator = generate objectMode: true, length: 1, columns: [ - ({options}) -> JSON.stringify(options) - ({state}) -> JSON.stringify(state) - ] - generator.on 'readable', -> - while d = generator.read() - data.push JSON.parse(d[0]), JSON.parse(d[1]) - generator.on 'error', next - generator.on 'end', -> - data.should.eql [ - columns: [ null, null ] - delimiter: ',' - duration: null - encoding: null - end: null - eof: false - fixedSize: false - length: 1 - maxWordLength: 16 - objectMode: true - rowDelimiter: '\n' - seed: false - sleep: 0 - , - start_time: null - fixed_size_buffer: '' - count_written: 0 - count_created: 0 - ] - next() diff --git a/packages/csv-generate/test/options.columns.js b/packages/csv-generate/test/options.columns.js new file mode 100644 index 000000000..ccc8e8c42 --- /dev/null +++ b/packages/csv-generate/test/options.columns.js @@ -0,0 +1,152 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("Option `columns`", function () { + it("as number", function (next) { + this.timeout(1000000); + let count = 0; + const data = []; + const generator = generate({ columns: 3 }); + generator.on("readable", () => { + let d; + while ((d = generator.read())) { + data.push(d); + if (count++ === 2) { + generator.end(); + } + } + }); + generator.on("error", next); + generator.on("end", () => { + data.join("").split("\n")[1].split(",").length.should.eql(3); + next(); + }); + }); + + it("as types", function (next) { + this.timeout(1000000); + let count = 0; + const data = []; + const generator = generate({ columns: ["int", "bool"], seed: 1 }); + generator.on("readable", () => { + let d; + while ((d = generator.read())) { + data.push(d); + if (count++ === 2) { + generator.end(); + } + } + }); + generator.on("error", next); + generator.on("end", () => { + data + .join("") + .split("\n")[1] + .split(",") + .should.eql(["1790016367053545", "0"]); + next(); + }); + }); + + it("validate types", function (next) { + try { + generate({ columns: ["int", "bool", "invalid"] }); + } catch (err) { + err.message.should.eql( + 'Invalid column type: got "invalid", default values are ["ascii","int","bool"]', + ); + next(); + } + }); + + describe("user function", function () { + it("accept string or null or number", function (next) { + this.timeout(1000000); + const data = []; + const generator = generate({ + length: 1, + columns: [() => "a", () => null, () => 1], + }); + generator.on("readable", () => { + let d; + while ((d = generator.read())) { + data.push(d.toString()); + } + }); + generator.on("error", next); + generator.on("end", () => { + data.should.eql(["a,,1"]); + next(); + }); + }); + + it("validate return argument", function (next) { + this.timeout(1000000); + const generator = generate({ + objectMode: true, + columns: [() => ({})], + }); + generator.on("readable", () => { + while (generator.read()) true; + }); + generator.on("error", (err) => { + err.message.should.eql( + [ + "INVALID_VALUE:", + "values returned by column function must be", + "a string, a number or null,", + "got {}", + ].join(" "), + ); + next(); + }); + generator.on("end", () => next(Error("Oh no"))); + }); + + it("validate arguments in objectMode", function (next) { + this.timeout(1000000); + const data = []; + const generator = generate({ + objectMode: true, + length: 1, + columns: [ + ({ options }) => JSON.stringify(options), + ({ state }) => JSON.stringify(state), + ], + }); + generator.on("readable", () => { + let d; + while ((d = generator.read())) { + data.push(JSON.parse(d[0]), JSON.parse(d[1])); + } + }); + generator.on("error", next); + generator.on("end", () => { + data.should.eql([ + { + columns: [null, null], + delimiter: ",", + duration: null, + encoding: null, + end: null, + eof: false, + fixedSize: false, + length: 1, + maxWordLength: 16, + objectMode: true, + rowDelimiter: "\n", + seed: false, + sleep: 0, + }, + { + start_time: null, + fixed_size_buffer: "", + count_written: 0, + count_created: 0, + }, + ]); + next(); + }); + }); + }); +}); diff --git a/packages/csv-generate/test/options.delimiter.coffee b/packages/csv-generate/test/options.delimiter.coffee deleted file mode 100644 index 94e22a7df..000000000 --- a/packages/csv-generate/test/options.delimiter.coffee +++ /dev/null @@ -1,24 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'Option `delimiter`', -> - - it 'one char', (next) -> - generate seed: 1, delimiter: '|', length: 4, encoding: 'ascii', (err, data) -> - return next err if err - data.should.eql """ - OMH|ONKCHhJmjadoA|D|GeACHiN|nnmiN|CGfDKB|NIl|JnnmjadnmiNL - KB|dmiM|fENL|Jn|opEMIkdmiOMFckep|MIj|bgIjadnn|fENLEOMIkbhLDK - B|LF|gGeBFaeAC|iLEO|IkdoAAC|hKpD|opENJ|opDLENLDJoAAABFP - iNJnmjPbhL|Ik|jPbhKCHhJn|fDKCHhIkeAABEM|kdnlh|DKACIl|HgGdoABEMIjP|adlhKCGf - """ - next() - - it 'multiple chars', (next) -> - generate seed: 1, columns: 3, delimiter: '||', length: 2, encoding: 'ascii', (err, data) -> - return next err if err - data.should.eql """ - OMH||ONKCHhJmjadoA||D - GeACHiN||nnmiN||CGfDKB - """ - next() diff --git a/packages/csv-generate/test/options.delimiter.js b/packages/csv-generate/test/options.delimiter.js new file mode 100644 index 000000000..ab8d4ff85 --- /dev/null +++ b/packages/csv-generate/test/options.delimiter.js @@ -0,0 +1,37 @@ +import "should"; +import dedent from "dedent"; +import { generate } from "../lib/index.js"; + +describe("Option `delimiter`", function () { + it("one char", function (next) { + generate( + { seed: 1, delimiter: "|", length: 4, encoding: "ascii" }, + (err, data) => { + if (err) return next(err); + data.should.eql( + dedent` + OMH|ONKCHhJmjadoA|D|GeACHiN|nnmiN|CGfDKB|NIl|JnnmjadnmiNL + KB|dmiM|fENL|Jn|opEMIkdmiOMFckep|MIj|bgIjadnn|fENLEOMIkbhLDK + B|LF|gGeBFaeAC|iLEO|IkdoAAC|hKpD|opENJ|opDLENLDJoAAABFP + iNJnmjPbhL|Ik|jPbhKCHhJn|fDKCHhIkeAABEM|kdnlh|DKACIl|HgGdoABEMIjP|adlhKCGf + `, + ); + next(); + }, + ); + }); + + it("multiple chars", function (next) { + generate( + { seed: 1, columns: 3, delimiter: "||", length: 2, encoding: "ascii" }, + (err, data) => { + if (err) return next(err); + data.should.eql(dedent` + OMH||ONKCHhJmjadoA||D + GeACHiN||nnmiN||CGfDKB + `); + next(); + }, + ); + }); +}); diff --git a/packages/csv-generate/test/options.duration.coffee b/packages/csv-generate/test/options.duration.coffee deleted file mode 100644 index 9d2350b1f..000000000 --- a/packages/csv-generate/test/options.duration.coffee +++ /dev/null @@ -1,13 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'option `duration`', -> - - it 'as millisecond', (next) -> - @timeout 1000000 - start = Date.now() - generate duration: 1000, encoding: 'ascii', (err, data) -> - end = Date.now() - (end - start).should.be.within(1000, 1100) unless err - data.split('\n').length.should.be.above 10000 unless err - next err diff --git a/packages/csv-generate/test/options.duration.js b/packages/csv-generate/test/options.duration.js new file mode 100644 index 000000000..11aa7ac13 --- /dev/null +++ b/packages/csv-generate/test/options.duration.js @@ -0,0 +1,17 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("option `duration`", function () { + it("as millisecond", function (next) { + this.timeout(1000000); + const start = Date.now(); + generate({ duration: 1000, encoding: "ascii" }, (err, data) => { + const end = Date.now(); + if (!err) { + (end - start).should.be.within(1000, 1100); + data.split("\n").length.should.be.above(10000); + } + next(err); + }); + }); +}); diff --git a/packages/csv-generate/test/options.encoding.coffee b/packages/csv-generate/test/options.encoding.coffee deleted file mode 100644 index 521619975..000000000 --- a/packages/csv-generate/test/options.encoding.coffee +++ /dev/null @@ -1,14 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'Option `encoding`', -> - - it 'generate buffer by default', (next) -> - generate length: 1, (err, data) -> - Buffer.isBuffer(data).should.be.true() unless err - next err - - it 'generate string if defined', (next) -> - generate length: 1, encoding: 'ascii', (err, data) -> - data.should.be.a.String() unless err - next err diff --git a/packages/csv-generate/test/options.encoding.js b/packages/csv-generate/test/options.encoding.js new file mode 100644 index 000000000..a3da97918 --- /dev/null +++ b/packages/csv-generate/test/options.encoding.js @@ -0,0 +1,22 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("Option `encoding`", function () { + it("generate buffer by default", function (next) { + generate({ length: 1 }, (err, data) => { + if (!err) { + Buffer.isBuffer(data).should.be.true(); + } + next(err); + }); + }); + + it("generate string if defined", function (next) { + generate({ length: 1, encoding: "ascii" }, (err, data) => { + if (!err) { + data.should.be.a.String(); + } + next(err); + }); + }); +}); diff --git a/packages/csv-generate/test/options.end.coffee b/packages/csv-generate/test/options.end.coffee deleted file mode 100644 index c3985c778..000000000 --- a/packages/csv-generate/test/options.end.coffee +++ /dev/null @@ -1,25 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'Option `end`', -> - - it 'as millisecond', (next) -> - @timeout 1000000 - generate end: Date.now() + 1000, encoding: 'ascii', (err, data) -> - return next err if err - data.split('\n').length.should.be.above 10000 - next() - - it 'as millisecond dont generate record if inferior to now', (next) -> - @timeout 1000000 - generate end: Date.now()-1, encoding: 'ascii', (err, data) -> - return next err if err - data.should.eql "" - next() - - it 'as date', (next) -> - @timeout 1000000 - generate end: new Date(Date.now() + 1000), encoding: 'ascii', (err, data) -> - return next err if err - data.split('\n').length.should.be.above 10000 - next() diff --git a/packages/csv-generate/test/options.end.js b/packages/csv-generate/test/options.end.js new file mode 100644 index 000000000..dc813c528 --- /dev/null +++ b/packages/csv-generate/test/options.end.js @@ -0,0 +1,34 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("Option `end`", function () { + it("as millisecond", function (next) { + this.timeout(1000000); + generate({ end: Date.now() + 1000, encoding: "ascii" }, (err, data) => { + if (err) return next(err); + data.split("\n").length.should.be.above(10000); + next(); + }); + }); + + it("as millisecond dont generate record if inferior to now", function (next) { + this.timeout(1000000); + generate({ end: Date.now() - 1, encoding: "ascii" }, (err, data) => { + if (err) return next(err); + data.should.eql(""); + next(); + }); + }); + + it("as date", function (next) { + this.timeout(1000000); + generate( + { end: new Date(Date.now() + 1000), encoding: "ascii" }, + (err, data) => { + if (err) return next(err); + data.split("\n").length.should.be.above(10000); + next(); + }, + ); + }); +}); diff --git a/packages/csv-generate/test/options.eof.coffee b/packages/csv-generate/test/options.eof.coffee deleted file mode 100644 index aac5d037b..000000000 --- a/packages/csv-generate/test/options.eof.coffee +++ /dev/null @@ -1,14 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'Option `eof`', -> - - it 'default to trailing newline character if true', (next) -> - generator = generate eof: true, length: 10, encoding: 'ascii', (err, data) -> - data.split('\n')[10].should.eql '' unless err - next err - - it 'accept any string', (next) -> - generator = generate eof: 'abcd', length: 10, encoding: 'ascii', (err, data) -> - data.split('abcd')[1].should.eql '' unless err - next err diff --git a/packages/csv-generate/test/options.eof.js b/packages/csv-generate/test/options.eof.js new file mode 100644 index 000000000..904c5e703 --- /dev/null +++ b/packages/csv-generate/test/options.eof.js @@ -0,0 +1,36 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("Option `eof`", function () { + it("default to trailing newline character if true", function (next) { + generate( + { + eof: true, + length: 10, + encoding: "ascii", + }, + (err, data) => { + if (!err) { + data.split("\n")[10].should.eql(""); + } + next(err); + }, + ); + }); + + it("accept any string", function (next) { + generate( + { + eof: "abcd", + length: 10, + encoding: "ascii", + }, + (err, data) => { + if (!err) { + data.split("abcd")[1].should.eql(""); + } + next(err); + }, + ); + }); +}); diff --git a/packages/csv-generate/test/options.fixed_size.coffee b/packages/csv-generate/test/options.fixed_size.coffee deleted file mode 100644 index facb14989..000000000 --- a/packages/csv-generate/test/options.fixed_size.coffee +++ /dev/null @@ -1,15 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'Option `fixed_size`', -> - - it 'with fixed_size', (next) -> - count = 0 - generator = generate fixed_size: true, highWaterMark: 1024 - generator.on 'readable', -> - while(data = generator.read()) - # First generated data is twice the high water mark, don't know why - data.length.should.eql 1024 - generator.end() if count++ is 100 - generator.on 'error', next - generator.on 'end', next diff --git a/packages/csv-generate/test/options.fixed_size.js b/packages/csv-generate/test/options.fixed_size.js new file mode 100644 index 000000000..16a08934b --- /dev/null +++ b/packages/csv-generate/test/options.fixed_size.js @@ -0,0 +1,24 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("Option `fixed_size`", function () { + it("with fixed_size", function (next) { + let count = 0; + const generator = generate({ + fixed_size: true, + highWaterMark: 1024, + }); + generator.on("readable", () => { + let data; + while ((data = generator.read())) { + // First generated data is twice the high water mark, don't know why + data.length.should.eql(1024); + if (count++ === 100) { + generator.end(); + } + } + }); + generator.on("error", next); + generator.on("end", next); + }); +}); diff --git a/packages/csv-generate/test/options.high_water_mark.coffee b/packages/csv-generate/test/options.high_water_mark.coffee deleted file mode 100644 index 595309989..000000000 --- a/packages/csv-generate/test/options.high_water_mark.coffee +++ /dev/null @@ -1,14 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'Option `high_water_mark`', -> - - it 'generate slightly larger buffer lengths', (next) -> - count = 0 - generator = generate fixed_size: true, highWaterMark: 64 - generator.on 'readable', -> - while(data = generator.read()) - data.length.should.be.within 64, 64*3 - generator.end() if count++ is 100 - generator.on 'error', next - generator.on 'end', next diff --git a/packages/csv-generate/test/options.high_water_mark.js b/packages/csv-generate/test/options.high_water_mark.js new file mode 100644 index 000000000..5314814a1 --- /dev/null +++ b/packages/csv-generate/test/options.high_water_mark.js @@ -0,0 +1,23 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("Option `high_water_mark`", function () { + it("generate slightly larger buffer lengths", function (next) { + let count = 0; + const generator = generate({ + fixed_size: true, + highWaterMark: 64, + }); + generator.on("readable", () => { + let data; + while ((data = generator.read())) { + data.length.should.be.within(64, 64 * 3); + if (count++ === 100) { + generator.end(); + } + } + }); + generator.on("error", next); + generator.on("end", next); + }); +}); diff --git a/packages/csv-generate/test/options.js b/packages/csv-generate/test/options.js new file mode 100644 index 000000000..2d3722498 --- /dev/null +++ b/packages/csv-generate/test/options.js @@ -0,0 +1,19 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("Options", function () { + it("no options with default", function (next) { + this.timeout(1000000); + let count = 0; + const generator = generate(); + generator.on("readable", () => { + while (generator.read()) { + if (count++ === 100) { + generator.end(); + } + } + }); + generator.on("error", next); + generator.on("end", next); + }); +}); diff --git a/packages/csv-generate/test/options.length.coffee b/packages/csv-generate/test/options.length.coffee deleted file mode 100644 index f0f20bf99..000000000 --- a/packages/csv-generate/test/options.length.coffee +++ /dev/null @@ -1,18 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'Option `length`', -> - - it 'raw text', (next) -> - @timeout 1000000 - generate length: 20, encoding: 'ascii', (err, data) -> - return next err if err - data.split('\n').length.should.eql 20 - next() - - it 'object', (next) -> - @timeout 1000000 - generate objectMode: true, length: 20, (err, data) -> - return next err if err - data.length.should.eql 20 - next() diff --git a/packages/csv-generate/test/options.length.js b/packages/csv-generate/test/options.length.js new file mode 100644 index 000000000..c1865f4e6 --- /dev/null +++ b/packages/csv-generate/test/options.length.js @@ -0,0 +1,34 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("Option `length`", function () { + it("raw text", function (next) { + this.timeout(1000000); + generate( + { + length: 20, + encoding: "ascii", + }, + (err, data) => { + if (err) return next(err); + data.split("\n").length.should.eql(20); + next(); + }, + ); + }); + + it("object", function (next) { + this.timeout(1000000); + generate( + { + objectMode: true, + length: 20, + }, + (err, data) => { + if (err) return next(err); + data.length.should.eql(20); + next(); + }, + ); + }); +}); diff --git a/packages/csv-generate/test/options.max_word_length.coffee b/packages/csv-generate/test/options.max_word_length.coffee deleted file mode 100644 index d72c86d59..000000000 --- a/packages/csv-generate/test/options.max_word_length.coffee +++ /dev/null @@ -1,22 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'Option `max_word_length', -> - - it 'default to 16', (next) -> - @timeout 1000000 - generate seed: 1, objectMode: true, length: 10, (err, records) -> - return next err if err - for record in records - for field in record - field.length.should.be.below 17 - next() - - it 'is set to 4', (next) -> - @timeout 1000000 - generate max_word_length: 4, seed: 1, objectMode: true, length: 10, (err, records) -> - return next err if err - for record in records - for field in record - field.length.should.be.below 5 - next() diff --git a/packages/csv-generate/test/options.max_word_length.js b/packages/csv-generate/test/options.max_word_length.js new file mode 100644 index 000000000..66308de19 --- /dev/null +++ b/packages/csv-generate/test/options.max_word_length.js @@ -0,0 +1,33 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("Option `max_word_length", function () { + it("default to 16", function (next) { + this.timeout(1000000); + generate({ seed: 1, objectMode: true, length: 10 }, (err, records) => { + if (err) return next(err); + for (const record of records) { + for (const field of record) { + field.length.should.be.below(17); + } + } + next(); + }); + }); + + it("is set to 4", function (next) { + this.timeout(1000000); + generate( + { max_word_length: 4, seed: 1, objectMode: true, length: 10 }, + (err, records) => { + if (err) return next(err); + for (const record of records) { + for (const field of record) { + field.length.should.be.below(5); + } + } + next(); + }, + ); + }); +}); diff --git a/packages/csv-generate/test/options.object_mode.coffee b/packages/csv-generate/test/options.object_mode.coffee deleted file mode 100644 index 2af25c649..000000000 --- a/packages/csv-generate/test/options.object_mode.coffee +++ /dev/null @@ -1,16 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'Option `objectMode`', -> - - it 'return an array of array', (next) -> - @timeout 1000000 - generate seed: 1, objectMode: true, length: 4, (err, data) -> - return next err if err - data.should.eql [ - [ 'OMH','ONKCHhJmjadoA','D','GeACHiN','nnmiN','CGfDKB','NIl','JnnmjadnmiNL' ] - [ 'KB','dmiM','fENL','Jn','opEMIkdmiOMFckep','MIj','bgIjadnn','fENLEOMIkbhLDK' ] - [ 'B','LF','gGeBFaeAC','iLEO','IkdoAAC','hKpD','opENJ','opDLENLDJoAAABFP' ] - [ 'iNJnmjPbhL','Ik','jPbhKCHhJn','fDKCHhIkeAABEM','kdnlh','DKACIl','HgGdoABEMIjP','adlhKCGf' ] - ] - next() diff --git a/packages/csv-generate/test/options.object_mode.js b/packages/csv-generate/test/options.object_mode.js new file mode 100644 index 000000000..267f8dc18 --- /dev/null +++ b/packages/csv-generate/test/options.object_mode.js @@ -0,0 +1,54 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("Option `objectMode`", function () { + it("return an array of array", function (next) { + this.timeout(1000000); + generate({ seed: 1, objectMode: true, length: 4 }, (err, data) => { + if (err) return next(err); + data.should.eql([ + [ + "OMH", + "ONKCHhJmjadoA", + "D", + "GeACHiN", + "nnmiN", + "CGfDKB", + "NIl", + "JnnmjadnmiNL", + ], + [ + "KB", + "dmiM", + "fENL", + "Jn", + "opEMIkdmiOMFckep", + "MIj", + "bgIjadnn", + "fENLEOMIkbhLDK", + ], + [ + "B", + "LF", + "gGeBFaeAC", + "iLEO", + "IkdoAAC", + "hKpD", + "opENJ", + "opDLENLDJoAAABFP", + ], + [ + "iNJnmjPbhL", + "Ik", + "jPbhKCHhJn", + "fDKCHhIkeAABEM", + "kdnlh", + "DKACIl", + "HgGdoABEMIjP", + "adlhKCGf", + ], + ]); + next(); + }); + }); +}); diff --git a/packages/csv-generate/test/options.row_delimiter.coffee b/packages/csv-generate/test/options.row_delimiter.coffee deleted file mode 100644 index c3b4634b1..000000000 --- a/packages/csv-generate/test/options.row_delimiter.coffee +++ /dev/null @@ -1,14 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'Option `row_delimiter`', -> - - it 'default to unix style', (next) -> - generator = generate length: 10, encoding: 'ascii', (err, data) -> - data.split('\n').length.should.eql 10 unless err - next err - - it 'accept multiple chars', (next) -> - generator = generate row_delimiter: 'abcd', length: 10, encoding: 'ascii', (err, data) -> - data.split('abcd').length.should.eql 10 unless err - next err diff --git a/packages/csv-generate/test/options.row_delimiter.js b/packages/csv-generate/test/options.row_delimiter.js new file mode 100644 index 000000000..7a84200d9 --- /dev/null +++ b/packages/csv-generate/test/options.row_delimiter.js @@ -0,0 +1,25 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("Option `row_delimiter`", function () { + it("default to unix style", function (next) { + generate({ length: 10, encoding: "ascii" }, (err, data) => { + if (!err) { + data.split("\n").length.should.eql(10); + } + next(err); + }); + }); + + it("accept multiple chars", function (next) { + generate( + { row_delimiter: "abcd", length: 10, encoding: "ascii" }, + (err, data) => { + if (!err) { + data.split("abcd").length.should.eql(10); + } + next(err); + }, + ); + }); +}); diff --git a/packages/csv-generate/test/options.seed.coffee b/packages/csv-generate/test/options.seed.coffee deleted file mode 100644 index 8628b70b2..000000000 --- a/packages/csv-generate/test/options.seed.coffee +++ /dev/null @@ -1,41 +0,0 @@ - -import { generate } from '../lib/index.js' -import { random } from '../lib/api/random.js' - -describe 'Option `seed`', -> - - describe 'without seed', -> - - it 'generate different values', -> - random(generate().options).should.not.equal random(generate().options) - - it 'generate between 0 and 1', -> - random(generate().options).should.be.above 0 - random(generate().options).should.be.below 1 - - describe 'with seed', -> - - it 'generate same values', -> - random(generate(seed: 1).options).should.equal random(generate(seed: 1).options) - - it 'generate between 0 and 1', -> - random(generate(seed: 1).options).should.be.above 0 - random(generate(seed: 1).options).should.be.below 1 - - it 'generate data with highWaterMark', (next) -> - @timeout 1000000 - count = 0 - data = [] - generator = generate seed: 1, highWaterMark: 32 - generator.on 'readable', -> - while d = generator.read() - data.push d - generator.end() if count++ is 2 - generator.on 'error', next - generator.on 'end', -> - data.join('').trim().should.eql """ - OMH,ONKCHhJmjadoA,D,GeACHiN,nnmiN,CGfDKB,NIl,JnnmjadnmiNL - KB,dmiM,fENL,Jn,opEMIkdmiOMFckep,MIj,bgIjadnn,fENLEOMIkbhLDK - B,LF,gGeBFaeAC,iLEO,IkdoAAC,hKpD,opENJ,opDLENLDJoAAABFP - """ - next() diff --git a/packages/csv-generate/test/options.seed.js b/packages/csv-generate/test/options.seed.js new file mode 100644 index 000000000..f68142ce9 --- /dev/null +++ b/packages/csv-generate/test/options.seed.js @@ -0,0 +1,57 @@ +import "should"; +import { generate } from "../lib/index.js"; +import { random } from "../lib/api/random.js"; + +describe("Option `seed`", function () { + describe("without seed", function () { + it("generate different values", function () { + random(generate().options).should.not.equal(random(generate().options)); + }); + + it("generate between 0 and 1", function () { + random(generate().options).should.be.above(0); + random(generate().options).should.be.below(1); + }); + }); + + describe("with seed", function () { + it("generate same values", function () { + random(generate({ seed: 1 }).options).should.equal( + random(generate({ seed: 1 }).options), + ); + }); + + it("generate between 0 and 1", function () { + random(generate({ seed: 1 }).options).should.be.above(0); + random(generate({ seed: 1 }).options).should.be.below(1); + }); + + it("generate data with highWaterMark", function (next) { + this.timeout(1000000); + let count = 0; + const data = []; + const generator = generate({ seed: 1, highWaterMark: 32 }); + generator.on("readable", () => { + let d; + while ((d = generator.read())) { + data.push(d); + if (count++ === 2) { + generator.end(); + } + } + }); + generator.on("error", next); + generator.on("end", () => { + data + .join("") + .trim() + .should.eql( + "OMH,ONKCHhJmjadoA,D,GeACHiN,nnmiN,CGfDKB,NIl,JnnmjadnmiNL\n" + + "KB,dmiM,fENL,Jn,opEMIkdmiOMFckep,MIj,bgIjadnn,fENLEOMIkbhLDK\n" + + "B,LF,gGeBFaeAC,iLEO,IkdoAAC,hKpD,opENJ,opDLENLDJoAAABFP", + ); + next(); + }); + }); + }); +}); diff --git a/packages/csv-generate/test/options.sleep.coffee b/packages/csv-generate/test/options.sleep.coffee deleted file mode 100644 index 533ba69ea..000000000 --- a/packages/csv-generate/test/options.sleep.coffee +++ /dev/null @@ -1,26 +0,0 @@ - -import { generate } from '../lib/index.js' - -describe 'Option `sleep`', -> - - it 'as integer above 0', (next) -> - @timeout 10000 - generate duration: 1000, sleep: 100, objectMode: true, (err, data) -> - data.length.should.be.within(8, 12) unless err - next err - - it 'sleep combined with length and objectMode false', (next) -> - # Fix bug where chuncks where emited after end when sleep is activated - @timeout 10000 - records = [] - generate - objectMode: false - length: 2 - sleep: 10 - .on 'readable', -> - while (record = this.read()) isnt null - records.push record.toString() - .on 'error', next - .on 'end', -> - records.join().split('\n').length.should.eql 2 - next() diff --git a/packages/csv-generate/test/options.sleep.js b/packages/csv-generate/test/options.sleep.js new file mode 100644 index 000000000..39676482f --- /dev/null +++ b/packages/csv-generate/test/options.sleep.js @@ -0,0 +1,36 @@ +import "should"; +import { generate } from "../lib/index.js"; + +describe("Option `sleep`", function () { + it("as integer above 0", function (next) { + this.timeout(10000); + generate({ duration: 1000, sleep: 100, objectMode: true }, (err, data) => { + if (!err) { + data.length.should.be.within(8, 12); + } + next(err); + }); + }); + + it("sleep combined with length and objectMode false", function (next) { + // Fix bug where chuncks where emited after end when sleep is activated + this.timeout(10000); + const records = []; + generate({ + objectMode: false, + length: 2, + sleep: 10, + }) + .on("readable", function () { + let record; + while ((record = this.read()) !== null) { + records.push(record.toString()); + } + }) + .on("error", next) + .on("end", () => { + records.join().split("\n").length.should.eql(2); + next(); + }); + }); +}); diff --git a/packages/csv-generate/test/samples.coffee b/packages/csv-generate/test/samples.coffee deleted file mode 100644 index 500e7525f..000000000 --- a/packages/csv-generate/test/samples.coffee +++ /dev/null @@ -1,30 +0,0 @@ - -import fs from 'node:fs/promises' -import path from 'node:path' -import { spawn } from 'node:child_process' - -__dirname = new URL( '.', import.meta.url).pathname -dir = path.resolve __dirname, '../samples' -samples = await fs.readdir dir - -describe 'Samples', -> - - samples - .filter (sample) -> - return false unless /\.(js|ts)?$/.test sample - true - .map (sample) -> - - it "Sample #{sample}", () -> - data = await fs.readFile path.resolve(dir, sample), 'utf8' - return if /^["|']skip test["|']/.test data - new Promise (resolve, reject) -> - ext = /\.(\w+)?$/.exec(sample)[0] - [cmd, ...args] = switch ext - when '.js' - ['node', path.resolve dir, sample] - when '.ts' - ['node', '--loader', 'ts-node/esm', path.resolve dir, sample] - spawn(cmd, args) - .on 'close', (code) -> if code is 0 then resolve() else reject(new Error 'Failure') - .stdout.on 'data', (->) diff --git a/packages/csv-generate/test/samples.js b/packages/csv-generate/test/samples.js new file mode 100644 index 000000000..5919a5514 --- /dev/null +++ b/packages/csv-generate/test/samples.js @@ -0,0 +1,44 @@ +import fs from "node:fs/promises"; +import path from "node:path"; +import { spawn } from "node:child_process"; + +const __dirname = new URL(".", import.meta.url).pathname; +const dir = path.resolve(__dirname, "../samples"); +const samples = await fs.readdir(dir); + +describe("Samples", function () { + /* eslint mocha/no-setup-in-describe: "off" */ + samples + .filter((sample) => { + if (!/\.(js|ts)?$/.test(sample)) return false; + return true; + }) + .map((sample) => { + it(`Sample ${sample}`, async function () { + const data = await fs.readFile(path.resolve(dir, sample), "utf8"); + if (/^["|']skip test["|']/.test(data)) return; + return new Promise((resolve, reject) => { + const ext = /\.(\w+)?$/.exec(sample)[0]; + let cmd, args; + switch (ext) { + case ".js": + [cmd, ...args] = ["node", path.resolve(dir, sample)]; + break; + case ".ts": + [cmd, ...args] = [ + "node", + "--loader", + "ts-node/esm", + path.resolve(dir, sample), + ]; + break; + } + spawn(cmd, args) + .on("close", (code) => + code === 0 ? resolve() : reject(new Error("Failure")), + ) + .stdout.on("data", () => {}); + }); + }); + }); +}); diff --git a/packages/csv-generate/tsconfig.json b/packages/csv-generate/tsconfig.json index 4db508a7c..5da38148b 100644 --- a/packages/csv-generate/tsconfig.json +++ b/packages/csv-generate/tsconfig.json @@ -4,6 +4,6 @@ "esModuleInterop": true, "module": "ES2020", "moduleResolution": "node", - "strict": true, + "strict": true } } diff --git a/packages/csv-parse/CHANGELOG.md b/packages/csv-parse/CHANGELOG.md index 14826337a..523400184 100644 --- a/packages/csv-parse/CHANGELOG.md +++ b/packages/csv-parse/CHANGELOG.md @@ -3,6 +3,107 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [6.1.0](https://github.com/adaltas/node-csv/compare/csv-parse@5.6.0...csv-parse@6.1.0) (2025-07-16) + +### Features + +- **csv-parse:** add generic type argument ([#457](https://github.com/adaltas/node-csv/issues/457)) ([ef71342](https://github.com/adaltas/node-csv/commit/ef713422d75812f2d4634c0c3f1d1f46a68ad186)), closes [#278](https://github.com/adaltas/node-csv/issues/278) [#407](https://github.com/adaltas/node-csv/issues/407) +- **csv-parse:** boolean and null comment type ([b9ac1f0](https://github.com/adaltas/node-csv/commit/b9ac1f0ce8d10a157d189ff4277a668ec2680b07)) +- **csv-parse:** callback records defined type ([3d4f225](https://github.com/adaltas/node-csv/commit/3d4f22549941766ecec87c962f4bb5058b996c24)) +- **csv-parse:** casting context raw export ([a26f5d7](https://github.com/adaltas/node-csv/commit/a26f5d71c82dcdda01037965330919344eedaf47)) +- **csv-parse:** input as Uint8Array (fix [#458](https://github.com/adaltas/node-csv/issues/458)) ([24af461](https://github.com/adaltas/node-csv/commit/24af4615343bf6f167adf2226d6906cf0e2cf89d)) +- **csv-parse:** normailzsed options type ([da7a62e](https://github.com/adaltas/node-csv/commit/da7a62e3b30fdc1fbd6293cbc9289a8ff6f5f64a)) +- **csv-parse:** normalize_options export ([9056293](https://github.com/adaltas/node-csv/commit/9056293960a2e0bdc0e4bae30d819ca794407fed)) +- **csv-parse:** null comment_no_infix type ([d8bf4fd](https://github.com/adaltas/node-csv/commit/d8bf4fd1fb813553a0e312b44374877b4dace52d)) +- **csv-parse:** on_skip catch thrown error ([987a3a9](https://github.com/adaltas/node-csv/commit/987a3a9a6873c06c7e2256a2bd83415b3fe0323b)) +- **csv-parse:** use ts unknown instead of any when possible ([a47badf](https://github.com/adaltas/node-csv/commit/a47badf599211ad12c4dd1ffac800adb3da393b7)) + +### Bug Fixes + +- **csv-parse:** normalized columns with auto-detected bom (fix [#460](https://github.com/adaltas/node-csv/issues/460)) ([4abcc44](https://github.com/adaltas/node-csv/commit/4abcc445ccdd566df8a3e827b6d6a881bebb6518)) + +## 6.0.0 (2025-07-10) + +### ⚠ BREAKING CHANGES + +- **csv-parse:** rename group_columns_by_name option +- **csv-parse:** rename RECORD_INCONSISTENT_FIELDS_LENGTH +- **csv-parse:** rename RECORD_DONT_MATCH_COLUMNS_LENGTH +- **csv-parse:** rename skip_records_with_error +- **csv-parse:** rename skip_records_with_empty_values +- **csv-parse:** rename relax to relax_quotes + +### Features + +- backport support for node 14 ([dbfeb78](https://github.com/adaltas/node-csv/commit/dbfeb78f61ed36f02936d63a53345708ca213e45)) +- backward support for node 8 ([496231d](https://github.com/adaltas/node-csv/commit/496231dfd838f0a6a72269a5a2390a4c637cef95)) +- **csv-parse:** add `columns` property in `Info` object type ([#390](https://github.com/adaltas/node-csv/issues/390)) ([2dd2a92](https://github.com/adaltas/node-csv/commit/2dd2a92d0376c3cee3a4a39334f9828874f422bd)) +- **csv-parse:** add generic type argument ([#457](https://github.com/adaltas/node-csv/issues/457)) ([ef71342](https://github.com/adaltas/node-csv/commit/ef713422d75812f2d4634c0c3f1d1f46a68ad186)), closes [#278](https://github.com/adaltas/node-csv/issues/278) [#407](https://github.com/adaltas/node-csv/issues/407) +- **csv-parse:** boolean and null comment type ([b9ac1f0](https://github.com/adaltas/node-csv/commit/b9ac1f0ce8d10a157d189ff4277a668ec2680b07)) +- **csv-parse:** callback records defined type ([3d4f225](https://github.com/adaltas/node-csv/commit/3d4f22549941766ecec87c962f4bb5058b996c24)) +- **csv-parse:** cast_date as a function (fix [#342](https://github.com/adaltas/node-csv/issues/342)) ([2807d29](https://github.com/adaltas/node-csv/commit/2807d292c8987f5dedde4f7fe0bd0ac7f75c8755)) +- **csv-parse:** casting context raw export ([a26f5d7](https://github.com/adaltas/node-csv/commit/a26f5d71c82dcdda01037965330919344eedaf47)) +- **csv-parse:** implement TransformStream ([#445](https://github.com/adaltas/node-csv/issues/445)) ([1213de8](https://github.com/adaltas/node-csv/commit/1213de8f032432ac09dd34861446b91ae85220ef)) +- **csv-parse:** improve record_delimiter validation ([67b7da8](https://github.com/adaltas/node-csv/commit/67b7da892db7f0f426b9f0fa12063e81eafe8a9b)) +- **csv-parse:** input as Uint8Array (fix [#458](https://github.com/adaltas/node-csv/issues/458)) ([24af461](https://github.com/adaltas/node-csv/commit/24af4615343bf6f167adf2226d6906cf0e2cf89d)) +- **csv-parse:** new comment_no_infix option (fix [#325](https://github.com/adaltas/node-csv/issues/325)) ([caca5c3](https://github.com/adaltas/node-csv/commit/caca5c3044541acfc9fe4a7f32167bb1179b6253)) +- **csv-parse:** normailzsed options type ([da7a62e](https://github.com/adaltas/node-csv/commit/da7a62e3b30fdc1fbd6293cbc9289a8ff6f5f64a)) +- **csv-parse:** normalize_options export ([9056293](https://github.com/adaltas/node-csv/commit/9056293960a2e0bdc0e4bae30d819ca794407fed)) +- **csv-parse:** null comment_no_infix type ([d8bf4fd](https://github.com/adaltas/node-csv/commit/d8bf4fd1fb813553a0e312b44374877b4dace52d)) +- **csv-parse:** objname index ([015b936](https://github.com/adaltas/node-csv/commit/015b936ea42026efa52263a7687f886463263ed8)) +- **csv-parse:** on_skip catch thrown error ([987a3a9](https://github.com/adaltas/node-csv/commit/987a3a9a6873c06c7e2256a2bd83415b3fe0323b)) +- **csv-parse:** skip_line_with_errors used with raw print current buffer (fix [#292](https://github.com/adaltas/node-csv/issues/292)) ([2741990](https://github.com/adaltas/node-csv/commit/27419908b9ce5319307bb6647335d5c07cd1e3a4)) +- **csv-parse:** ts type encoding with BufferEncoding ([39a4388](https://github.com/adaltas/node-csv/commit/39a43886904801d47a92a3cb5722409f36020534)) +- **csv-parse:** use ts unknown instead of any when possible ([a47badf](https://github.com/adaltas/node-csv/commit/a47badf599211ad12c4dd1ffac800adb3da393b7)) +- esm migration ([b5c0d4b](https://github.com/adaltas/node-csv/commit/b5c0d4b191c8b57397808c0922a3f08248506a9f)) +- export ts types in sync ([890bf8d](https://github.com/adaltas/node-csv/commit/890bf8d950c18a05cab5e35a461d0847d9425156)) +- replace ts types with typesVersions ([acb41d5](https://github.com/adaltas/node-csv/commit/acb41d5031669f2d582e40da1c80f5fd4738fee4)) +- ts module Node16 and type declaration to exports field ([#341](https://github.com/adaltas/node-csv/issues/341)) ([4b0283d](https://github.com/adaltas/node-csv/commit/4b0283d17b7fa46daa1f87380759ba72c71ec79b)) +- wg stream api ([8a5eb7d](https://github.com/adaltas/node-csv/commit/8a5eb7dfd31b22217db4fbbc832d707221850785)) + +### Bug Fixes + +- commonjs types, run tsc and lint to validate changes ([#397](https://github.com/adaltas/node-csv/issues/397)) ([e6870fe](https://github.com/adaltas/node-csv/commit/e6870fe272c119e273196522c9771d12ff8b2a35)) +- correct exports in package.json with webpack ([154eafb](https://github.com/adaltas/node-csv/commit/154eafbac866eb4499a0d392f8dcd057695c2586)) +- **csv-demo-ts-cjs-node16:** upgrade module definition after latest typescript ([87fe919](https://github.com/adaltas/node-csv/commit/87fe91996fb2a8895c252177fca4f0cb59a518f9)) +- **csv-demo-webpack-ts:** remove polyfill ([47a99bd](https://github.com/adaltas/node-csv/commit/47a99bd944d1d943e6374227dbc4e20aaa2c8c7f)) +- **csv-demo-webpack-ts:** simplify export paths ([8d63a14](https://github.com/adaltas/node-csv/commit/8d63a14313bb6b26f13fafb740cc686f1dfaa65f)) +- **csv-parse:** build from previus commit ([29a0916](https://github.com/adaltas/node-csv/commit/29a0916026429d648e8c515ada4a452036e0736d)) +- **csv-parse:** call destroy on end (fix [#410](https://github.com/adaltas/node-csv/issues/410)) ([0df32c6](https://github.com/adaltas/node-csv/commit/0df32c6a3500d2541451846c6a152ff991a2f2ff)) +- **csv-parse:** comment infix when comment first field char (fix [#415](https://github.com/adaltas/node-csv/issues/415)) ([8e0f8b8](https://github.com/adaltas/node-csv/commit/8e0f8b8e11736f1223b0bda4dd2a3b37506dd531)) +- **csv-parse:** destroy on end and call close event (fix [#333](https://github.com/adaltas/node-csv/issues/333)) ([ca3f55b](https://github.com/adaltas/node-csv/commit/ca3f55b7cf556b45377677428783608a2d9ebbb2)) +- **csv-parse:** encoding detection with bom ([#350](https://github.com/adaltas/node-csv/issues/350)) ([fd75e66](https://github.com/adaltas/node-csv/commit/fd75e6626c1c549936bf35a2247ebefa0f3d5ec3)) +- **csv-parse:** export csv error class in sync ([fc89380](https://github.com/adaltas/node-csv/commit/fc8938090141861dcbcae214f64e52a0aa6cc691)) +- **csv-parse:** improve INVALID_OPENING_QUOTE error message (fix adaltas/node-csv-docs[#120](https://github.com/adaltas/node-csv/issues/120)) ([3639780](https://github.com/adaltas/node-csv/commit/36397800a9b479658e6497bb521a27c037fc3abb)) +- **csv-parse:** premature close error ([c6473a9](https://github.com/adaltas/node-csv/commit/c6473a9cb6c5e4c94e42c30c2b9d15b049f16a6b)) +- **csv-parse:** record_delimiter and non default encoding (fix [#365](https://github.com/adaltas/node-csv/issues/365)) ([16fdb2d](https://github.com/adaltas/node-csv/commit/16fdb2dd2c3221d00568f28bed44106ffc0d49ef)) +- **csv-parse:** remove support for cast_date, no test ([5471985](https://github.com/adaltas/node-csv/commit/5471985e7e5f603ee1e3dd7bcf203415d94978f5)) +- **csv-parse:** rtrim encoding support (fix [#349](https://github.com/adaltas/node-csv/issues/349)) ([8bf52f0](https://github.com/adaltas/node-csv/commit/8bf52f0d5c25ee2423cb1629d3e9103534668c83)) +- **csv-parse:** skip event not raised with bom (fix [#411](https://github.com/adaltas/node-csv/issues/411)) ([1326351](https://github.com/adaltas/node-csv/commit/13263514ef6ec02000cf2da39ba6aa2ff92f00ae)) +- **csv-parse:** ts callback CsvError argument ([899dc67](https://github.com/adaltas/node-csv/commit/899dc67ed6256478e8eecbcc5b925f238ce367d5)) +- dont insert polyfills in cjs [#303](https://github.com/adaltas/node-csv/issues/303) ([9baf334](https://github.com/adaltas/node-csv/commit/9baf334044dab90b4a0d096a7e456d0fd5807d5b)) +- esm exports in package.json files ([c48fe47](https://github.com/adaltas/node-csv/commit/c48fe478ced7560aa078fbc36ec33d6007111e2b)), closes [#308](https://github.com/adaltas/node-csv/issues/308) +- export original lib esm modules ([be25349](https://github.com/adaltas/node-csv/commit/be2534928ba21156e9cde1e15d2e8593d62ffe71)) +- expose browser esm modules ([eb87355](https://github.com/adaltas/node-csv/commit/eb873557c65912f065d2581d30a17a96b0bfd2d6)) +- fallback to setTimeout is setImmediate is undefined ([3d6a2d0](https://github.com/adaltas/node-csv/commit/3d6a2d0a655af342f28456b46db7ccfe7ee9d664)) +- refer to esm files in dist ([b780fbd](https://github.com/adaltas/node-csv/commit/b780fbd26f5e54494e511eb2e004d3cdedee3593)) +- remove samples from publicatgion ([12c221d](https://github.com/adaltas/node-csv/commit/12c221dc37add26f094e3bb7f94b50ee06ff5be6)) +- support ts node16 resolution in cjs ([#354](https://github.com/adaltas/node-csv/issues/354)) ([fa09d03](https://github.com/adaltas/node-csv/commit/fa09d03aaf0008b2790656871ca6b2c4be12d14c)) +- support TypeScript moduleResolution node16 ([#368](https://github.com/adaltas/node-csv/issues/368)) ([f4d7c97](https://github.com/adaltas/node-csv/commit/f4d7c97f39fb73e9d248eee21e61e7dc48015c78)) + +### Performance Improvements + +- **csv-parse:** buffer unsafe allocation ([35c1f4a](https://github.com/adaltas/node-csv/commit/35c1f4a9dd806adc4de749c2e211bd436224d7f0)) + +### Code Refactoring + +- **csv-parse:** rename group_columns_by_name option ([74334cf](https://github.com/adaltas/node-csv/commit/74334cf0e85e005a878c0597b3300f4762116a0d)) +- **csv-parse:** rename RECORD_DONT_MATCH_COLUMNS_LENGTH ([fb391c9](https://github.com/adaltas/node-csv/commit/fb391c92fa248bda30b816930cac88a5d9026b04)) +- **csv-parse:** rename RECORD_INCONSISTENT_FIELDS_LENGTH ([7b55f05](https://github.com/adaltas/node-csv/commit/7b55f050df327939efcb65d4e76d27f98c89d925)) +- **csv-parse:** rename relax to relax_quotes ([9fffd50](https://github.com/adaltas/node-csv/commit/9fffd50762e10b3794883c6b3751ad209510f82e)) +- **csv-parse:** rename skip_records_with_empty_values ([aa432c1](https://github.com/adaltas/node-csv/commit/aa432c1251327b579ee7f71bd9fd776021ac1f1e)) +- **csv-parse:** rename skip_records_with_error ([0376af7](https://github.com/adaltas/node-csv/commit/0376af7984caa6726d12980edecccda1bbbbcacc)) + ## [5.6.0](https://github.com/adaltas/node-csv/compare/csv-parse@5.5.6...csv-parse@5.6.0) (2024-11-21) ### Features diff --git a/packages/csv-parse/dist/cjs/index.cjs b/packages/csv-parse/dist/cjs/index.cjs index df3086ab2..9060294a7 100644 --- a/packages/csv-parse/dist/cjs/index.cjs +++ b/packages/csv-parse/dist/cjs/index.cjs @@ -281,7 +281,7 @@ const normalize_options = function (opts) { ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -813,7 +813,7 @@ const normalize_options = function (opts) { // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -832,7 +832,7 @@ const normalize_options = function (opts) { // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -963,10 +963,14 @@ const transform = function (original_options = {}) { this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options({ + const options = normalize_options({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -1709,10 +1713,14 @@ const transform = function (original_options = {}) { if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -1886,4 +1894,5 @@ const parse = function () { exports.CsvError = CsvError; exports.Parser = Parser; +exports.normalize_options = normalize_options; exports.parse = parse; diff --git a/packages/csv-parse/dist/cjs/index.d.cts b/packages/csv-parse/dist/cjs/index.d.cts index ec8aa027e..403243a65 100644 --- a/packages/csv-parse/dist/cjs/index.d.cts +++ b/packages/csv-parse/dist/cjs/index.d.cts @@ -4,280 +4,504 @@ import * as stream from "stream"; -export type Callback = (err: CsvError | undefined, records: any | undefined, info: Info) => void; +export type Callback = ( + err: CsvError | undefined, + records: T[], + info?: Info, +) => void; -export interface Parser extends stream.Transform {} +// export interface Parser extends stream.Transform {} -export class Parser { - constructor(options: Options); - - __push(line: any): any; - - __write(chars: any, end: any, callback: any): any; - - readonly options: Options - - readonly info: Info; +// export class Parser extends stream.Transform { +export class Parser extends stream.Transform { + constructor(options: Options); + + // __push(line: T): CsvError | undefined; + __push(line: any): CsvError | undefined; + + // __write(chars: any, end: any, callback: any): any; + + readonly options: OptionsNormalized; + + readonly info: Info; +} + +export interface Info { + /** + * Count the number of lines being fully commented. + */ + readonly comment_lines: number; + /** + * Count the number of processed empty lines. + */ + readonly empty_lines: number; + /** + * The number of lines encountered in the source dataset, start at 1 for the first line. + */ + readonly lines: number; + /** + * Count the number of processed records. + */ + readonly records: number; + /** + * Count of the number of processed bytes. + */ + readonly bytes: number; + /** + * Number of non uniform records when `relax_column_count` is true. + */ + readonly invalid_field_length: number; + /** + * Normalized verion of `options.columns` when `options.columns` is true, boolean otherwise. + */ + readonly columns: boolean | { name: string }[] | { disabled: true }[]; } export interface CastingContext { - readonly column: number | string; - readonly empty_lines: number; - readonly error: CsvError; - readonly header: boolean; - readonly index: number; - readonly quoting: boolean; - readonly lines: number; - readonly records: number; - readonly invalid_field_length: number; + readonly column: number | string; + readonly empty_lines: number; + readonly error: CsvError; + readonly header: boolean; + readonly index: number; + readonly quoting: boolean; + readonly lines: number; + readonly raw: string | undefined; + readonly records: number; + readonly invalid_field_length: number; } -export type CastingFunction = (value: string, context: CastingContext) => any; +export type CastingFunction = ( + value: string, + context: CastingContext, +) => unknown; + +export type CastingDateFunction = ( + value: string, + context: CastingContext, +) => Date; -export type CastingDateFunction = (value: string, context: CastingContext) => Date; +export type ColumnOption = + | K + | undefined + | null + | false + | { name: K }; -export type ColumnOption = string | undefined | null | false | { name: string }; +export interface OptionsNormalized { + auto_parse?: boolean | CastingFunction; + auto_parse_date?: boolean | CastingDateFunction; + /** + * If true, detect and exclude the byte order mark (BOM) from the CSV input if present. + */ + bom?: boolean; + /** + * If true, the parser will attempt to convert input string to native types. + * If a function, receive the value as first argument, a context as second argument and return a new value. More information about the context properties is available below. + */ + cast?: boolean | CastingFunction; + /** + * If true, the parser will attempt to convert input string to dates. + * If a function, receive the value as argument and return a new value. It requires the "auto_parse" option. Be careful, it relies on Date.parse. + */ + cast_date?: boolean | CastingDateFunction; + /** + * Internal property string the function to + */ + cast_first_line_to_header?: ( + record: T, + ) => ColumnOption< + T extends string[] ? string : T extends unknown ? string : keyof T + >[]; + /** + * List of fields as an array, a user defined callback accepting the first + * line and returning the column names or true if autodiscovered in the first + * CSV line, default to null, affect the result data set in the sense that + * records will be objects instead of arrays. + */ + columns: + | boolean + | ColumnOption< + T extends string[] ? string : T extends unknown ? string : keyof T + >[]; + /** + * Convert values into an array of values when columns are activated and + * when multiple columns of the same name are found. + */ + group_columns_by_name: boolean; + /** + * Treat all the characters after this one as a comment, default to '' (disabled). + */ + comment: string | null; + /** + * Restrict the definition of comments to a full line. Comment characters + * defined in the middle of the line are not interpreted as such. The + * option require the activation of comments. + */ + comment_no_infix: boolean; + /** + * Set the field delimiter. One character only, defaults to comma. + */ + delimiter: Buffer[]; + /** + * Set the source and destination encoding, a value of `null` returns buffer instead of strings. + */ + encoding: BufferEncoding | null; + /** + * Set the escape character, one character only, defaults to double quotes. + */ + escape: null | Buffer; + /** + * Start handling records from the requested number of records. + */ + from: number; + /** + * Start handling records from the requested line number. + */ + from_line: number; + /** + * Don't interpret delimiters as such in the last field according to the number of fields calculated from the number of columns, the option require the presence of the `column` option when `true`. + */ + ignore_last_delimiters: boolean | number; + /** + * Generate two properties `info` and `record` where `info` is a snapshot of the info object at the time the record was created and `record` is the parsed array or object. + */ + info: boolean; + /** + * If true, ignore whitespace immediately following the delimiter (i.e. left-trim all fields), defaults to false. + * Does not remove whitespace in a quoted field. + */ + ltrim: boolean; + /** + * Maximum numer of characters to be contained in the field and line buffers before an exception is raised, + * used to guard against a wrong delimiter or record_delimiter, + * default to 128000 characters. + */ + max_record_size: number; + /** + * Name of header-record title to name objects by. + */ + objname: number | string | undefined; + /** + * Alter and filter records by executing a user defined function. + */ + on_record?: (record: T, context: CastingContext) => T | undefined; + /** + * Optional character surrounding a field, one character only, defaults to double quotes. + */ + quote?: Buffer | null; + /** + * Generate two properties raw and row where raw is the original CSV row content and row is the parsed array or object. + */ + raw: boolean; + /** + * Discard inconsistent columns count, default to false. + */ + relax_column_count: boolean; + /** + * Discard inconsistent columns count when the record contains less fields than expected, default to false. + */ + relax_column_count_less: boolean; + /** + * Discard inconsistent columns count when the record contains more fields than expected, default to false. + */ + relax_column_count_more: boolean; + /** + * Preserve quotes inside unquoted field. + */ + relax_quotes: boolean; + /** + * One or multiple characters used to delimit record rows; defaults to auto discovery if not provided. + * Supported auto discovery method are Linux ("\n"), Apple ("\r") and Windows ("\r\n") row delimiters. + */ + record_delimiter: Buffer[]; + /** + * If true, ignore whitespace immediately preceding the delimiter (i.e. right-trim all fields), defaults to false. + * Does not remove whitespace in a quoted field. + */ + rtrim: boolean; + /** + * Dont generate empty values for empty lines. + * Defaults to false + */ + skip_empty_lines: boolean; + /** + * Skip a line with error found inside and directly go process the next line. + */ + skip_records_with_error: boolean; + /** + * Don't generate records for lines containing empty column values (column matching /\s*\/), defaults to false. + */ + skip_records_with_empty_values: boolean; + /** + * Stop handling records after the requested number of records. + */ + to: number; + /** + * Stop handling records after the requested line number. + */ + to_line: number; + /** + * If true, ignore whitespace immediately around the delimiter, defaults to false. + * Does not remove whitespace in a quoted field. + */ + trim: boolean; +} /* Note, could not `extends stream.TransformOptions` because encoding can be BufferEncoding and undefined as well as null which is not defined in the extended type. */ -export interface Options { - /** - * If true, the parser will attempt to convert read data types to native types. - * @deprecated Use {@link cast} - */ - auto_parse?: boolean | CastingFunction; - autoParse?: boolean | CastingFunction; - /** - * If true, the parser will attempt to convert read data types to dates. It requires the "auto_parse" option. - * @deprecated Use {@link cast_date} - */ - auto_parse_date?: boolean | CastingDateFunction; - autoParseDate?: boolean | CastingDateFunction; - /** - * If true, detect and exclude the byte order mark (BOM) from the CSV input if present. - */ - bom?: boolean; - /** - * If true, the parser will attempt to convert input string to native types. - * If a function, receive the value as first argument, a context as second argument and return a new value. More information about the context properties is available below. - */ - cast?: boolean | CastingFunction; - /** - * If true, the parser will attempt to convert input string to dates. - * If a function, receive the value as argument and return a new value. It requires the "auto_parse" option. Be careful, it relies on Date.parse. - */ - cast_date?: boolean | CastingDateFunction; - castDate?: boolean | CastingDateFunction; - /** - * List of fields as an array, - * a user defined callback accepting the first line and returning the column names or true if autodiscovered in the first CSV line, - * default to null, - * affect the result data set in the sense that records will be objects instead of arrays. - */ - columns?: ColumnOption[] | boolean | ((record: any) => ColumnOption[]); - /** - * Convert values into an array of values when columns are activated and - * when multiple columns of the same name are found. - */ - group_columns_by_name?: boolean; - groupColumnsByName?: boolean; - /** - * Treat all the characters after this one as a comment, default to '' (disabled). - */ - comment?: string; - /** - * Restrict the definition of comments to a full line. Comment characters - * defined in the middle of the line are not interpreted as such. The - * option require the activation of comments. - */ - comment_no_infix?: boolean; - /** - * Set the field delimiter. One character only, defaults to comma. - */ - delimiter?: string | string[] | Buffer; - /** - * Set the source and destination encoding, a value of `null` returns buffer instead of strings. - */ - encoding?: BufferEncoding | undefined; - /** - * Set the escape character, one character only, defaults to double quotes. - */ - escape?: string | null | false | Buffer; - /** - * Start handling records from the requested number of records. - */ - from?: number; - /** - * Start handling records from the requested line number. - */ - from_line?: number; - fromLine?: number; - /** - * Don't interpret delimiters as such in the last field according to the number of fields calculated from the number of columns, the option require the presence of the `column` option when `true`. - */ - ignore_last_delimiters?: boolean | number; - /** - * Generate two properties `info` and `record` where `info` is a snapshot of the info object at the time the record was created and `record` is the parsed array or object. - */ - info?: boolean; - /** - * If true, ignore whitespace immediately following the delimiter (i.e. left-trim all fields), defaults to false. - * Does not remove whitespace in a quoted field. - */ - ltrim?: boolean; - /** - * Maximum numer of characters to be contained in the field and line buffers before an exception is raised, - * used to guard against a wrong delimiter or record_delimiter, - * default to 128000 characters. - */ - max_record_size?: number; - maxRecordSize?: number; - /** - * Name of header-record title to name objects by. - */ - objname?: string; - /** - * Alter and filter records by executing a user defined function. - */ - on_record?: (record: any, context: CastingContext) => any; - onRecord?: (record: any, context: CastingContext) => any; - /** - * Optional character surrounding a field, one character only, defaults to double quotes. - */ - quote?: string | boolean | Buffer | null; - /** - * Generate two properties raw and row where raw is the original CSV row content and row is the parsed array or object. - */ - raw?: boolean; - /** - * Discard inconsistent columns count, default to false. - */ - relax_column_count?: boolean; - relaxColumnCount?: boolean; - /** - * Discard inconsistent columns count when the record contains less fields than expected, default to false. - */ - relax_column_count_less?: boolean; - relaxColumnCountLess?: boolean; - /** - * Discard inconsistent columns count when the record contains more fields than expected, default to false. - */ - relax_column_count_more?: boolean; - relaxColumnCountMore?: boolean; - /** - * Preserve quotes inside unquoted field. - */ - relax_quotes?: boolean; - relaxQuotes?: boolean; - /** - * One or multiple characters used to delimit record rows; defaults to auto discovery if not provided. - * Supported auto discovery method are Linux ("\n"), Apple ("\r") and Windows ("\r\n") row delimiters. - */ - record_delimiter?: string | string[] | Buffer | Buffer[]; - recordDelimiter?: string | string[] | Buffer | Buffer[]; - /** - * If true, ignore whitespace immediately preceding the delimiter (i.e. right-trim all fields), defaults to false. - * Does not remove whitespace in a quoted field. - */ - rtrim?: boolean; - /** - * Dont generate empty values for empty lines. - * Defaults to false - */ - skip_empty_lines?: boolean; - skipEmptyLines?: boolean; - /** - * Skip a line with error found inside and directly go process the next line. - */ - skip_records_with_error?: boolean; - skipRecordsWithError?: boolean; - /** - * Don't generate records for lines containing empty column values (column matching /\s*\/), defaults to false. - */ - skip_records_with_empty_values?: boolean; - skipRecordsWithEmptyValues?: boolean; - /** - * Stop handling records after the requested number of records. - */ - to?: number; - /** - * Stop handling records after the requested line number. - */ - to_line?: number; - toLine?: number; - /** - * If true, ignore whitespace immediately around the delimiter, defaults to false. - * Does not remove whitespace in a quoted field. - */ - trim?: boolean; -} - -export interface Info { - /** - * Count the number of lines being fully commented. - */ - readonly comment_lines: number; - /** - * Count the number of processed empty lines. - */ - readonly empty_lines: number; - /** - * The number of lines encountered in the source dataset, start at 1 for the first line. - */ - readonly lines: number; - /** - * Count the number of processed records. - */ - readonly records: number; - /** - * Count of the number of processed bytes. - */ - readonly bytes: number; - /** - * Number of non uniform records when `relax_column_count` is true. - */ - readonly invalid_field_length: number; - /** - * Normalized verion of `options.columns` when `options.columns` is true, boolean otherwise. - */ - readonly columns: boolean | { name: string }[] | { disabled: true }[]; +export interface Options { + /** + * If true, the parser will attempt to convert read data types to native types. + * @deprecated Use {@link cast} + */ + auto_parse?: boolean | CastingFunction; + autoParse?: boolean | CastingFunction; + /** + * If true, the parser will attempt to convert read data types to dates. It requires the "auto_parse" option. + * @deprecated Use {@link cast_date} + */ + auto_parse_date?: boolean | CastingDateFunction; + autoParseDate?: boolean | CastingDateFunction; + /** + * If true, detect and exclude the byte order mark (BOM) from the CSV input if present. + */ + bom?: boolean; + /** + * If true, the parser will attempt to convert input string to native types. + * If a function, receive the value as first argument, a context as second argument and return a new value. More information about the context properties is available below. + */ + cast?: boolean | CastingFunction; + /** + * If true, the parser will attempt to convert input string to dates. + * If a function, receive the value as argument and return a new value. It requires the "auto_parse" option. Be careful, it relies on Date.parse. + */ + cast_date?: boolean | CastingDateFunction; + castDate?: boolean | CastingDateFunction; + /** + * List of fields as an array, + * a user defined callback accepting the first line and returning the column names or true if autodiscovered in the first CSV line, + * default to null, + * affect the result data set in the sense that records will be objects instead of arrays. + */ + columns?: + | boolean + | ColumnOption< + T extends string[] ? string : T extends unknown ? string : keyof T + >[] + | (( + record: T, + ) => ColumnOption< + T extends string[] ? string : T extends unknown ? string : keyof T + >[]); + /** + * Convert values into an array of values when columns are activated and + * when multiple columns of the same name are found. + */ + group_columns_by_name?: boolean; + groupColumnsByName?: boolean; + /** + * Treat all the characters after this one as a comment, default to '' (disabled). + */ + comment?: string | boolean | null; + /** + * Restrict the definition of comments to a full line. Comment characters + * defined in the middle of the line are not interpreted as such. The + * option require the activation of comments. + */ + comment_no_infix?: boolean | null; + /** + * Set the field delimiter. One character only, defaults to comma. + */ + delimiter?: string | string[] | Buffer; + /** + * Set the source and destination encoding, a value of `null` returns buffer instead of strings. + */ + encoding?: BufferEncoding | boolean | null | undefined; + /** + * Set the escape character, one character only, defaults to double quotes. + */ + escape?: string | null | boolean | Buffer; + /** + * Start handling records from the requested number of records. + */ + from?: number | string; + /** + * Start handling records from the requested line number. + */ + from_line?: null | number | string; + fromLine?: null | number | string; + /** + * Don't interpret delimiters as such in the last field according to the number of fields calculated from the number of columns, the option require the presence of the `column` option when `true`. + */ + ignore_last_delimiters?: boolean | number; + /** + * Generate two properties `info` and `record` where `info` is a snapshot of the info object at the time the record was created and `record` is the parsed array or object. + */ + info?: boolean; + /** + * If true, ignore whitespace immediately following the delimiter (i.e. left-trim all fields), defaults to false. + * Does not remove whitespace in a quoted field. + */ + ltrim?: boolean | null; + /** + * Maximum numer of characters to be contained in the field and line buffers before an exception is raised, + * used to guard against a wrong delimiter or record_delimiter, + * default to 128000 characters. + */ + max_record_size?: number | null | string; + maxRecordSize?: number; + /** + * Name of header-record title to name objects by. + */ + objname?: Buffer | null | number | string; + /** + * Alter and filter records by executing a user defined function. + */ + on_record?: (record: T, context: CastingContext) => T | null | undefined; + onRecord?: (record: T, context: CastingContext) => T | null | undefined; + /** + * Function called when an error occured if the `skip_records_with_error` + * option is activated. + */ + on_skip?: (err: CsvError | undefined, raw: string | undefined) => undefined; + onSkip?: (err: CsvError | undefined, raw: string | undefined) => undefined; + /** + * Optional character surrounding a field, one character only, defaults to double quotes. + */ + quote?: string | boolean | Buffer | null; + /** + * Generate two properties raw and row where raw is the original CSV row content and row is the parsed array or object. + */ + raw?: boolean | null; + /** + * One or multiple characters used to delimit record rows; defaults to auto discovery if not provided. + * Supported auto discovery method are Linux ("\n"), Apple ("\r") and Windows ("\r\n") row delimiters. + */ + record_delimiter?: string | Buffer | null | (string | Buffer | null)[]; + recordDelimiter?: string | Buffer | null | (string | Buffer | null)[]; + /** + * Discard inconsistent columns count, default to false. + */ + relax_column_count?: boolean | null; + relaxColumnCount?: boolean | null; + /** + * Discard inconsistent columns count when the record contains less fields than expected, default to false. + */ + relax_column_count_less?: boolean | null; + relaxColumnCountLess?: boolean | null; + /** + * Discard inconsistent columns count when the record contains more fields than expected, default to false. + */ + relax_column_count_more?: boolean | null; + relaxColumnCountMore?: boolean | null; + /** + * Preserve quotes inside unquoted field. + */ + relax_quotes?: boolean | null; + relaxQuotes?: boolean | null; + /** + * If true, ignore whitespace immediately preceding the delimiter (i.e. right-trim all fields), defaults to false. + * Does not remove whitespace in a quoted field. + */ + rtrim?: boolean | null; + /** + * Dont generate empty values for empty lines. + * Defaults to false + */ + skip_empty_lines?: boolean | null; + skipEmptyLines?: boolean | null; + /** + * Don't generate records for lines containing empty column values (column matching /\s*\/), defaults to false. + */ + skip_records_with_empty_values?: boolean | null; + skipRecordsWithEmptyValues?: boolean | null; + /** + * Skip a line with error found inside and directly go process the next line. + */ + skip_records_with_error?: boolean | null; + skipRecordsWithError?: boolean | null; + /** + * Stop handling records after the requested number of records. + */ + to?: null | number | string; + /** + * Stop handling records after the requested line number. + */ + to_line?: null | number | string; + toLine?: null | number | string; + /** + * If true, ignore whitespace immediately around the delimiter, defaults to false. + * Does not remove whitespace in a quoted field. + */ + trim?: boolean | null; } -export type CsvErrorCode = - 'CSV_INVALID_OPTION_BOM' - | 'CSV_INVALID_OPTION_CAST' - | 'CSV_INVALID_OPTION_CAST_DATE' - | 'CSV_INVALID_OPTION_COLUMNS' - | 'CSV_INVALID_OPTION_GROUP_COLUMNS_BY_NAME' - | 'CSV_INVALID_OPTION_COMMENT' - | 'CSV_INVALID_OPTION_DELIMITER' - | 'CSV_INVALID_OPTION_ON_RECORD' - | 'CSV_INVALID_CLOSING_QUOTE' - | 'INVALID_OPENING_QUOTE' - | 'CSV_INVALID_COLUMN_MAPPING' - | 'CSV_INVALID_ARGUMENT' - | 'CSV_INVALID_COLUMN_DEFINITION' - | 'CSV_MAX_RECORD_SIZE' - | 'CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE' - | 'CSV_QUOTE_NOT_CLOSED' - | 'CSV_RECORD_INCONSISTENT_FIELDS_LENGTH' - | 'CSV_RECORD_INCONSISTENT_COLUMNS' - | 'CSV_OPTION_COLUMNS_MISSING_NAME' +export type CsvErrorCode = + | "CSV_INVALID_ARGUMENT" + | "CSV_INVALID_CLOSING_QUOTE" + | "CSV_INVALID_COLUMN_DEFINITION" + | "CSV_INVALID_COLUMN_MAPPING" + | "CSV_INVALID_OPTION_BOM" + | "CSV_INVALID_OPTION_CAST" + | "CSV_INVALID_OPTION_CAST_DATE" + | "CSV_INVALID_OPTION_COLUMNS" + | "CSV_INVALID_OPTION_COMMENT" + | "CSV_INVALID_OPTION_DELIMITER" + | "CSV_INVALID_OPTION_GROUP_COLUMNS_BY_NAME" + | "CSV_INVALID_OPTION_ON_RECORD" + | "CSV_MAX_RECORD_SIZE" + | "CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE" + | "CSV_OPTION_COLUMNS_MISSING_NAME" + | "CSV_QUOTE_NOT_CLOSED" + | "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH" + | "CSV_RECORD_INCONSISTENT_COLUMNS" + | "CSV_UNKNOWN_ERROR" + | "INVALID_OPENING_QUOTE"; export class CsvError extends Error { - readonly code: CsvErrorCode; - [key: string]: any; + readonly code: CsvErrorCode; + [key: string]: any; - constructor(code: CsvErrorCode, message: string | string[], options?: Options, ...contexts: any[]); + constructor( + code: CsvErrorCode, + message: string | string[], + options?: OptionsNormalized, + ...contexts: unknown[] + ); } -declare function parse(input: Buffer | string, options?: Options, callback?: Callback): Parser; -declare function parse(input: Buffer | string, callback?: Callback): Parser; -declare function parse(options?: Options, callback?: Callback): Parser; +type OptionsWithColumns = Omit, "columns"> & { + columns: Exclude; +}; + +declare function parse( + input: string | Buffer | Uint8Array, + options: OptionsWithColumns, + callback?: Callback, +): Parser; +declare function parse( + input: string | Buffer | Uint8Array, + options: Options, + callback?: Callback, +): Parser; + +declare function parse( + options: OptionsWithColumns, + callback?: Callback, +): Parser; +declare function parse(options: Options, callback?: Callback): Parser; + +declare function parse( + input: string | Buffer | Uint8Array, + callback?: Callback, +): Parser; declare function parse(callback?: Callback): Parser; // export default parse; -export { parse } +export { parse }; + +declare function normalize_options(opts: Options): OptionsNormalized; +export { normalize_options }; diff --git a/packages/csv-parse/dist/cjs/sync.cjs b/packages/csv-parse/dist/cjs/sync.cjs index dc6113ad3..7ba901d3d 100644 --- a/packages/csv-parse/dist/cjs/sync.cjs +++ b/packages/csv-parse/dist/cjs/sync.cjs @@ -279,7 +279,7 @@ const normalize_options = function (opts) { ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -811,7 +811,7 @@ const normalize_options = function (opts) { // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -830,7 +830,7 @@ const normalize_options = function (opts) { // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -961,10 +961,14 @@ const transform = function (original_options = {}) { this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options({ + const options = normalize_options({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -1707,10 +1711,14 @@ const transform = function (original_options = {}) { if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -1764,10 +1772,13 @@ const parse = function (data, opts = {}) { } }; const close = () => {}; - const err1 = parser.parse(data, false, push, close); - if (err1 !== undefined) throw err1; - const err2 = parser.parse(undefined, true, push, close); - if (err2 !== undefined) throw err2; + const error = parser.parse(data, true, push, close); + if (error !== undefined) throw error; + // 250606: `parser.parse` was implemented as 2 calls: + // const err1 = parser.parse(data, false, push, close); + // if (err1 !== undefined) throw err1; + // const err2 = parser.parse(undefined, true, push, close); + // if (err2 !== undefined) throw err2; return records; }; diff --git a/packages/csv-parse/dist/cjs/sync.d.cts b/packages/csv-parse/dist/cjs/sync.d.cts index 835666e55..ff2e55c14 100644 --- a/packages/csv-parse/dist/cjs/sync.d.cts +++ b/packages/csv-parse/dist/cjs/sync.d.cts @@ -1,11 +1,30 @@ +import { Options } from "./index.cjs"; -import { Options } from './index.cjs'; +type OptionsWithColumns = Omit, "columns"> & { + columns: Exclude; +}; + +declare function parse( + input: Buffer | string | Uint8Array, + options: OptionsWithColumns, +): T[]; +declare function parse( + input: Buffer | string | Uint8Array, + options: Options, +): string[][]; +declare function parse(input: Buffer | string | Uint8Array): string[][]; -declare function parse(input: Buffer | string, options?: Options): any; // export default parse; export { parse }; export { - CastingContext, CastingFunction, CastingDateFunction, - ColumnOption, Options, Info, CsvErrorCode, CsvError -} from './index.cjs'; + CastingContext, + CastingFunction, + CastingDateFunction, + ColumnOption, + Options, + OptionsNormalized, + Info, + CsvErrorCode, + CsvError, +} from "./index.cjs"; diff --git a/packages/csv-parse/dist/esm/index.d.ts b/packages/csv-parse/dist/esm/index.d.ts index ec8aa027e..403243a65 100644 --- a/packages/csv-parse/dist/esm/index.d.ts +++ b/packages/csv-parse/dist/esm/index.d.ts @@ -4,280 +4,504 @@ import * as stream from "stream"; -export type Callback = (err: CsvError | undefined, records: any | undefined, info: Info) => void; +export type Callback = ( + err: CsvError | undefined, + records: T[], + info?: Info, +) => void; -export interface Parser extends stream.Transform {} +// export interface Parser extends stream.Transform {} -export class Parser { - constructor(options: Options); - - __push(line: any): any; - - __write(chars: any, end: any, callback: any): any; - - readonly options: Options - - readonly info: Info; +// export class Parser extends stream.Transform { +export class Parser extends stream.Transform { + constructor(options: Options); + + // __push(line: T): CsvError | undefined; + __push(line: any): CsvError | undefined; + + // __write(chars: any, end: any, callback: any): any; + + readonly options: OptionsNormalized; + + readonly info: Info; +} + +export interface Info { + /** + * Count the number of lines being fully commented. + */ + readonly comment_lines: number; + /** + * Count the number of processed empty lines. + */ + readonly empty_lines: number; + /** + * The number of lines encountered in the source dataset, start at 1 for the first line. + */ + readonly lines: number; + /** + * Count the number of processed records. + */ + readonly records: number; + /** + * Count of the number of processed bytes. + */ + readonly bytes: number; + /** + * Number of non uniform records when `relax_column_count` is true. + */ + readonly invalid_field_length: number; + /** + * Normalized verion of `options.columns` when `options.columns` is true, boolean otherwise. + */ + readonly columns: boolean | { name: string }[] | { disabled: true }[]; } export interface CastingContext { - readonly column: number | string; - readonly empty_lines: number; - readonly error: CsvError; - readonly header: boolean; - readonly index: number; - readonly quoting: boolean; - readonly lines: number; - readonly records: number; - readonly invalid_field_length: number; + readonly column: number | string; + readonly empty_lines: number; + readonly error: CsvError; + readonly header: boolean; + readonly index: number; + readonly quoting: boolean; + readonly lines: number; + readonly raw: string | undefined; + readonly records: number; + readonly invalid_field_length: number; } -export type CastingFunction = (value: string, context: CastingContext) => any; +export type CastingFunction = ( + value: string, + context: CastingContext, +) => unknown; + +export type CastingDateFunction = ( + value: string, + context: CastingContext, +) => Date; -export type CastingDateFunction = (value: string, context: CastingContext) => Date; +export type ColumnOption = + | K + | undefined + | null + | false + | { name: K }; -export type ColumnOption = string | undefined | null | false | { name: string }; +export interface OptionsNormalized { + auto_parse?: boolean | CastingFunction; + auto_parse_date?: boolean | CastingDateFunction; + /** + * If true, detect and exclude the byte order mark (BOM) from the CSV input if present. + */ + bom?: boolean; + /** + * If true, the parser will attempt to convert input string to native types. + * If a function, receive the value as first argument, a context as second argument and return a new value. More information about the context properties is available below. + */ + cast?: boolean | CastingFunction; + /** + * If true, the parser will attempt to convert input string to dates. + * If a function, receive the value as argument and return a new value. It requires the "auto_parse" option. Be careful, it relies on Date.parse. + */ + cast_date?: boolean | CastingDateFunction; + /** + * Internal property string the function to + */ + cast_first_line_to_header?: ( + record: T, + ) => ColumnOption< + T extends string[] ? string : T extends unknown ? string : keyof T + >[]; + /** + * List of fields as an array, a user defined callback accepting the first + * line and returning the column names or true if autodiscovered in the first + * CSV line, default to null, affect the result data set in the sense that + * records will be objects instead of arrays. + */ + columns: + | boolean + | ColumnOption< + T extends string[] ? string : T extends unknown ? string : keyof T + >[]; + /** + * Convert values into an array of values when columns are activated and + * when multiple columns of the same name are found. + */ + group_columns_by_name: boolean; + /** + * Treat all the characters after this one as a comment, default to '' (disabled). + */ + comment: string | null; + /** + * Restrict the definition of comments to a full line. Comment characters + * defined in the middle of the line are not interpreted as such. The + * option require the activation of comments. + */ + comment_no_infix: boolean; + /** + * Set the field delimiter. One character only, defaults to comma. + */ + delimiter: Buffer[]; + /** + * Set the source and destination encoding, a value of `null` returns buffer instead of strings. + */ + encoding: BufferEncoding | null; + /** + * Set the escape character, one character only, defaults to double quotes. + */ + escape: null | Buffer; + /** + * Start handling records from the requested number of records. + */ + from: number; + /** + * Start handling records from the requested line number. + */ + from_line: number; + /** + * Don't interpret delimiters as such in the last field according to the number of fields calculated from the number of columns, the option require the presence of the `column` option when `true`. + */ + ignore_last_delimiters: boolean | number; + /** + * Generate two properties `info` and `record` where `info` is a snapshot of the info object at the time the record was created and `record` is the parsed array or object. + */ + info: boolean; + /** + * If true, ignore whitespace immediately following the delimiter (i.e. left-trim all fields), defaults to false. + * Does not remove whitespace in a quoted field. + */ + ltrim: boolean; + /** + * Maximum numer of characters to be contained in the field and line buffers before an exception is raised, + * used to guard against a wrong delimiter or record_delimiter, + * default to 128000 characters. + */ + max_record_size: number; + /** + * Name of header-record title to name objects by. + */ + objname: number | string | undefined; + /** + * Alter and filter records by executing a user defined function. + */ + on_record?: (record: T, context: CastingContext) => T | undefined; + /** + * Optional character surrounding a field, one character only, defaults to double quotes. + */ + quote?: Buffer | null; + /** + * Generate two properties raw and row where raw is the original CSV row content and row is the parsed array or object. + */ + raw: boolean; + /** + * Discard inconsistent columns count, default to false. + */ + relax_column_count: boolean; + /** + * Discard inconsistent columns count when the record contains less fields than expected, default to false. + */ + relax_column_count_less: boolean; + /** + * Discard inconsistent columns count when the record contains more fields than expected, default to false. + */ + relax_column_count_more: boolean; + /** + * Preserve quotes inside unquoted field. + */ + relax_quotes: boolean; + /** + * One or multiple characters used to delimit record rows; defaults to auto discovery if not provided. + * Supported auto discovery method are Linux ("\n"), Apple ("\r") and Windows ("\r\n") row delimiters. + */ + record_delimiter: Buffer[]; + /** + * If true, ignore whitespace immediately preceding the delimiter (i.e. right-trim all fields), defaults to false. + * Does not remove whitespace in a quoted field. + */ + rtrim: boolean; + /** + * Dont generate empty values for empty lines. + * Defaults to false + */ + skip_empty_lines: boolean; + /** + * Skip a line with error found inside and directly go process the next line. + */ + skip_records_with_error: boolean; + /** + * Don't generate records for lines containing empty column values (column matching /\s*\/), defaults to false. + */ + skip_records_with_empty_values: boolean; + /** + * Stop handling records after the requested number of records. + */ + to: number; + /** + * Stop handling records after the requested line number. + */ + to_line: number; + /** + * If true, ignore whitespace immediately around the delimiter, defaults to false. + * Does not remove whitespace in a quoted field. + */ + trim: boolean; +} /* Note, could not `extends stream.TransformOptions` because encoding can be BufferEncoding and undefined as well as null which is not defined in the extended type. */ -export interface Options { - /** - * If true, the parser will attempt to convert read data types to native types. - * @deprecated Use {@link cast} - */ - auto_parse?: boolean | CastingFunction; - autoParse?: boolean | CastingFunction; - /** - * If true, the parser will attempt to convert read data types to dates. It requires the "auto_parse" option. - * @deprecated Use {@link cast_date} - */ - auto_parse_date?: boolean | CastingDateFunction; - autoParseDate?: boolean | CastingDateFunction; - /** - * If true, detect and exclude the byte order mark (BOM) from the CSV input if present. - */ - bom?: boolean; - /** - * If true, the parser will attempt to convert input string to native types. - * If a function, receive the value as first argument, a context as second argument and return a new value. More information about the context properties is available below. - */ - cast?: boolean | CastingFunction; - /** - * If true, the parser will attempt to convert input string to dates. - * If a function, receive the value as argument and return a new value. It requires the "auto_parse" option. Be careful, it relies on Date.parse. - */ - cast_date?: boolean | CastingDateFunction; - castDate?: boolean | CastingDateFunction; - /** - * List of fields as an array, - * a user defined callback accepting the first line and returning the column names or true if autodiscovered in the first CSV line, - * default to null, - * affect the result data set in the sense that records will be objects instead of arrays. - */ - columns?: ColumnOption[] | boolean | ((record: any) => ColumnOption[]); - /** - * Convert values into an array of values when columns are activated and - * when multiple columns of the same name are found. - */ - group_columns_by_name?: boolean; - groupColumnsByName?: boolean; - /** - * Treat all the characters after this one as a comment, default to '' (disabled). - */ - comment?: string; - /** - * Restrict the definition of comments to a full line. Comment characters - * defined in the middle of the line are not interpreted as such. The - * option require the activation of comments. - */ - comment_no_infix?: boolean; - /** - * Set the field delimiter. One character only, defaults to comma. - */ - delimiter?: string | string[] | Buffer; - /** - * Set the source and destination encoding, a value of `null` returns buffer instead of strings. - */ - encoding?: BufferEncoding | undefined; - /** - * Set the escape character, one character only, defaults to double quotes. - */ - escape?: string | null | false | Buffer; - /** - * Start handling records from the requested number of records. - */ - from?: number; - /** - * Start handling records from the requested line number. - */ - from_line?: number; - fromLine?: number; - /** - * Don't interpret delimiters as such in the last field according to the number of fields calculated from the number of columns, the option require the presence of the `column` option when `true`. - */ - ignore_last_delimiters?: boolean | number; - /** - * Generate two properties `info` and `record` where `info` is a snapshot of the info object at the time the record was created and `record` is the parsed array or object. - */ - info?: boolean; - /** - * If true, ignore whitespace immediately following the delimiter (i.e. left-trim all fields), defaults to false. - * Does not remove whitespace in a quoted field. - */ - ltrim?: boolean; - /** - * Maximum numer of characters to be contained in the field and line buffers before an exception is raised, - * used to guard against a wrong delimiter or record_delimiter, - * default to 128000 characters. - */ - max_record_size?: number; - maxRecordSize?: number; - /** - * Name of header-record title to name objects by. - */ - objname?: string; - /** - * Alter and filter records by executing a user defined function. - */ - on_record?: (record: any, context: CastingContext) => any; - onRecord?: (record: any, context: CastingContext) => any; - /** - * Optional character surrounding a field, one character only, defaults to double quotes. - */ - quote?: string | boolean | Buffer | null; - /** - * Generate two properties raw and row where raw is the original CSV row content and row is the parsed array or object. - */ - raw?: boolean; - /** - * Discard inconsistent columns count, default to false. - */ - relax_column_count?: boolean; - relaxColumnCount?: boolean; - /** - * Discard inconsistent columns count when the record contains less fields than expected, default to false. - */ - relax_column_count_less?: boolean; - relaxColumnCountLess?: boolean; - /** - * Discard inconsistent columns count when the record contains more fields than expected, default to false. - */ - relax_column_count_more?: boolean; - relaxColumnCountMore?: boolean; - /** - * Preserve quotes inside unquoted field. - */ - relax_quotes?: boolean; - relaxQuotes?: boolean; - /** - * One or multiple characters used to delimit record rows; defaults to auto discovery if not provided. - * Supported auto discovery method are Linux ("\n"), Apple ("\r") and Windows ("\r\n") row delimiters. - */ - record_delimiter?: string | string[] | Buffer | Buffer[]; - recordDelimiter?: string | string[] | Buffer | Buffer[]; - /** - * If true, ignore whitespace immediately preceding the delimiter (i.e. right-trim all fields), defaults to false. - * Does not remove whitespace in a quoted field. - */ - rtrim?: boolean; - /** - * Dont generate empty values for empty lines. - * Defaults to false - */ - skip_empty_lines?: boolean; - skipEmptyLines?: boolean; - /** - * Skip a line with error found inside and directly go process the next line. - */ - skip_records_with_error?: boolean; - skipRecordsWithError?: boolean; - /** - * Don't generate records for lines containing empty column values (column matching /\s*\/), defaults to false. - */ - skip_records_with_empty_values?: boolean; - skipRecordsWithEmptyValues?: boolean; - /** - * Stop handling records after the requested number of records. - */ - to?: number; - /** - * Stop handling records after the requested line number. - */ - to_line?: number; - toLine?: number; - /** - * If true, ignore whitespace immediately around the delimiter, defaults to false. - * Does not remove whitespace in a quoted field. - */ - trim?: boolean; -} - -export interface Info { - /** - * Count the number of lines being fully commented. - */ - readonly comment_lines: number; - /** - * Count the number of processed empty lines. - */ - readonly empty_lines: number; - /** - * The number of lines encountered in the source dataset, start at 1 for the first line. - */ - readonly lines: number; - /** - * Count the number of processed records. - */ - readonly records: number; - /** - * Count of the number of processed bytes. - */ - readonly bytes: number; - /** - * Number of non uniform records when `relax_column_count` is true. - */ - readonly invalid_field_length: number; - /** - * Normalized verion of `options.columns` when `options.columns` is true, boolean otherwise. - */ - readonly columns: boolean | { name: string }[] | { disabled: true }[]; +export interface Options { + /** + * If true, the parser will attempt to convert read data types to native types. + * @deprecated Use {@link cast} + */ + auto_parse?: boolean | CastingFunction; + autoParse?: boolean | CastingFunction; + /** + * If true, the parser will attempt to convert read data types to dates. It requires the "auto_parse" option. + * @deprecated Use {@link cast_date} + */ + auto_parse_date?: boolean | CastingDateFunction; + autoParseDate?: boolean | CastingDateFunction; + /** + * If true, detect and exclude the byte order mark (BOM) from the CSV input if present. + */ + bom?: boolean; + /** + * If true, the parser will attempt to convert input string to native types. + * If a function, receive the value as first argument, a context as second argument and return a new value. More information about the context properties is available below. + */ + cast?: boolean | CastingFunction; + /** + * If true, the parser will attempt to convert input string to dates. + * If a function, receive the value as argument and return a new value. It requires the "auto_parse" option. Be careful, it relies on Date.parse. + */ + cast_date?: boolean | CastingDateFunction; + castDate?: boolean | CastingDateFunction; + /** + * List of fields as an array, + * a user defined callback accepting the first line and returning the column names or true if autodiscovered in the first CSV line, + * default to null, + * affect the result data set in the sense that records will be objects instead of arrays. + */ + columns?: + | boolean + | ColumnOption< + T extends string[] ? string : T extends unknown ? string : keyof T + >[] + | (( + record: T, + ) => ColumnOption< + T extends string[] ? string : T extends unknown ? string : keyof T + >[]); + /** + * Convert values into an array of values when columns are activated and + * when multiple columns of the same name are found. + */ + group_columns_by_name?: boolean; + groupColumnsByName?: boolean; + /** + * Treat all the characters after this one as a comment, default to '' (disabled). + */ + comment?: string | boolean | null; + /** + * Restrict the definition of comments to a full line. Comment characters + * defined in the middle of the line are not interpreted as such. The + * option require the activation of comments. + */ + comment_no_infix?: boolean | null; + /** + * Set the field delimiter. One character only, defaults to comma. + */ + delimiter?: string | string[] | Buffer; + /** + * Set the source and destination encoding, a value of `null` returns buffer instead of strings. + */ + encoding?: BufferEncoding | boolean | null | undefined; + /** + * Set the escape character, one character only, defaults to double quotes. + */ + escape?: string | null | boolean | Buffer; + /** + * Start handling records from the requested number of records. + */ + from?: number | string; + /** + * Start handling records from the requested line number. + */ + from_line?: null | number | string; + fromLine?: null | number | string; + /** + * Don't interpret delimiters as such in the last field according to the number of fields calculated from the number of columns, the option require the presence of the `column` option when `true`. + */ + ignore_last_delimiters?: boolean | number; + /** + * Generate two properties `info` and `record` where `info` is a snapshot of the info object at the time the record was created and `record` is the parsed array or object. + */ + info?: boolean; + /** + * If true, ignore whitespace immediately following the delimiter (i.e. left-trim all fields), defaults to false. + * Does not remove whitespace in a quoted field. + */ + ltrim?: boolean | null; + /** + * Maximum numer of characters to be contained in the field and line buffers before an exception is raised, + * used to guard against a wrong delimiter or record_delimiter, + * default to 128000 characters. + */ + max_record_size?: number | null | string; + maxRecordSize?: number; + /** + * Name of header-record title to name objects by. + */ + objname?: Buffer | null | number | string; + /** + * Alter and filter records by executing a user defined function. + */ + on_record?: (record: T, context: CastingContext) => T | null | undefined; + onRecord?: (record: T, context: CastingContext) => T | null | undefined; + /** + * Function called when an error occured if the `skip_records_with_error` + * option is activated. + */ + on_skip?: (err: CsvError | undefined, raw: string | undefined) => undefined; + onSkip?: (err: CsvError | undefined, raw: string | undefined) => undefined; + /** + * Optional character surrounding a field, one character only, defaults to double quotes. + */ + quote?: string | boolean | Buffer | null; + /** + * Generate two properties raw and row where raw is the original CSV row content and row is the parsed array or object. + */ + raw?: boolean | null; + /** + * One or multiple characters used to delimit record rows; defaults to auto discovery if not provided. + * Supported auto discovery method are Linux ("\n"), Apple ("\r") and Windows ("\r\n") row delimiters. + */ + record_delimiter?: string | Buffer | null | (string | Buffer | null)[]; + recordDelimiter?: string | Buffer | null | (string | Buffer | null)[]; + /** + * Discard inconsistent columns count, default to false. + */ + relax_column_count?: boolean | null; + relaxColumnCount?: boolean | null; + /** + * Discard inconsistent columns count when the record contains less fields than expected, default to false. + */ + relax_column_count_less?: boolean | null; + relaxColumnCountLess?: boolean | null; + /** + * Discard inconsistent columns count when the record contains more fields than expected, default to false. + */ + relax_column_count_more?: boolean | null; + relaxColumnCountMore?: boolean | null; + /** + * Preserve quotes inside unquoted field. + */ + relax_quotes?: boolean | null; + relaxQuotes?: boolean | null; + /** + * If true, ignore whitespace immediately preceding the delimiter (i.e. right-trim all fields), defaults to false. + * Does not remove whitespace in a quoted field. + */ + rtrim?: boolean | null; + /** + * Dont generate empty values for empty lines. + * Defaults to false + */ + skip_empty_lines?: boolean | null; + skipEmptyLines?: boolean | null; + /** + * Don't generate records for lines containing empty column values (column matching /\s*\/), defaults to false. + */ + skip_records_with_empty_values?: boolean | null; + skipRecordsWithEmptyValues?: boolean | null; + /** + * Skip a line with error found inside and directly go process the next line. + */ + skip_records_with_error?: boolean | null; + skipRecordsWithError?: boolean | null; + /** + * Stop handling records after the requested number of records. + */ + to?: null | number | string; + /** + * Stop handling records after the requested line number. + */ + to_line?: null | number | string; + toLine?: null | number | string; + /** + * If true, ignore whitespace immediately around the delimiter, defaults to false. + * Does not remove whitespace in a quoted field. + */ + trim?: boolean | null; } -export type CsvErrorCode = - 'CSV_INVALID_OPTION_BOM' - | 'CSV_INVALID_OPTION_CAST' - | 'CSV_INVALID_OPTION_CAST_DATE' - | 'CSV_INVALID_OPTION_COLUMNS' - | 'CSV_INVALID_OPTION_GROUP_COLUMNS_BY_NAME' - | 'CSV_INVALID_OPTION_COMMENT' - | 'CSV_INVALID_OPTION_DELIMITER' - | 'CSV_INVALID_OPTION_ON_RECORD' - | 'CSV_INVALID_CLOSING_QUOTE' - | 'INVALID_OPENING_QUOTE' - | 'CSV_INVALID_COLUMN_MAPPING' - | 'CSV_INVALID_ARGUMENT' - | 'CSV_INVALID_COLUMN_DEFINITION' - | 'CSV_MAX_RECORD_SIZE' - | 'CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE' - | 'CSV_QUOTE_NOT_CLOSED' - | 'CSV_RECORD_INCONSISTENT_FIELDS_LENGTH' - | 'CSV_RECORD_INCONSISTENT_COLUMNS' - | 'CSV_OPTION_COLUMNS_MISSING_NAME' +export type CsvErrorCode = + | "CSV_INVALID_ARGUMENT" + | "CSV_INVALID_CLOSING_QUOTE" + | "CSV_INVALID_COLUMN_DEFINITION" + | "CSV_INVALID_COLUMN_MAPPING" + | "CSV_INVALID_OPTION_BOM" + | "CSV_INVALID_OPTION_CAST" + | "CSV_INVALID_OPTION_CAST_DATE" + | "CSV_INVALID_OPTION_COLUMNS" + | "CSV_INVALID_OPTION_COMMENT" + | "CSV_INVALID_OPTION_DELIMITER" + | "CSV_INVALID_OPTION_GROUP_COLUMNS_BY_NAME" + | "CSV_INVALID_OPTION_ON_RECORD" + | "CSV_MAX_RECORD_SIZE" + | "CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE" + | "CSV_OPTION_COLUMNS_MISSING_NAME" + | "CSV_QUOTE_NOT_CLOSED" + | "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH" + | "CSV_RECORD_INCONSISTENT_COLUMNS" + | "CSV_UNKNOWN_ERROR" + | "INVALID_OPENING_QUOTE"; export class CsvError extends Error { - readonly code: CsvErrorCode; - [key: string]: any; + readonly code: CsvErrorCode; + [key: string]: any; - constructor(code: CsvErrorCode, message: string | string[], options?: Options, ...contexts: any[]); + constructor( + code: CsvErrorCode, + message: string | string[], + options?: OptionsNormalized, + ...contexts: unknown[] + ); } -declare function parse(input: Buffer | string, options?: Options, callback?: Callback): Parser; -declare function parse(input: Buffer | string, callback?: Callback): Parser; -declare function parse(options?: Options, callback?: Callback): Parser; +type OptionsWithColumns = Omit, "columns"> & { + columns: Exclude; +}; + +declare function parse( + input: string | Buffer | Uint8Array, + options: OptionsWithColumns, + callback?: Callback, +): Parser; +declare function parse( + input: string | Buffer | Uint8Array, + options: Options, + callback?: Callback, +): Parser; + +declare function parse( + options: OptionsWithColumns, + callback?: Callback, +): Parser; +declare function parse(options: Options, callback?: Callback): Parser; + +declare function parse( + input: string | Buffer | Uint8Array, + callback?: Callback, +): Parser; declare function parse(callback?: Callback): Parser; // export default parse; -export { parse } +export { parse }; + +declare function normalize_options(opts: Options): OptionsNormalized; +export { normalize_options }; diff --git a/packages/csv-parse/dist/esm/index.js b/packages/csv-parse/dist/esm/index.js index 5b396c3a7..d76c43fad 100644 --- a/packages/csv-parse/dist/esm/index.js +++ b/packages/csv-parse/dist/esm/index.js @@ -831,8 +831,8 @@ function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1591,7 +1591,7 @@ Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, no Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1601,7 +1601,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1614,7 +1614,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1627,7 +1627,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1642,7 +1642,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2000,7 +2000,9 @@ EventEmitter.init = function() { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2569,94 +2571,19 @@ function Item(fun, array) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; -var title = 'browser'; -var platform = 'browser'; -var browser = true; var env = {}; -var argv = []; -var version = ''; // empty string to avoid regexp issues -var versions = {}; -var release = {}; -var config = {}; - -function noop() {} - -var on = noop; -var addListener = noop; -var once = noop; -var off = noop; -var removeListener = noop; -var removeAllListeners = noop; -var emit = noop; - -function binding(name) { - throw new Error('process.binding is not supported'); -} - -function cwd () { return '/' } -function chdir (dir) { - throw new Error('process.chdir is not supported'); -}function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; -var performanceNow = - performance.now || +performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; -// generate timestamp or delta -// see http://nodejs.org/api/process.html#process_process_hrtime -function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] -} - -var startTime = new Date(); -function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; -} - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime -}; + env: env}; var inherits; if (typeof Object.create === 'function'){ @@ -5403,7 +5330,7 @@ const normalize_options = function (opts) { ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -5935,7 +5862,7 @@ const normalize_options = function (opts) { // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -5954,7 +5881,7 @@ const normalize_options = function (opts) { // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -6085,10 +6012,14 @@ const transform = function (original_options = {}) { this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options({ + const options = normalize_options({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -6831,10 +6762,14 @@ const transform = function (original_options = {}) { if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -6998,4 +6933,4 @@ const parse = function () { return parser; }; -export { CsvError, Parser, parse }; +export { CsvError, Parser, normalize_options, parse }; diff --git a/packages/csv-parse/dist/esm/stream.d.ts b/packages/csv-parse/dist/esm/stream.d.ts index f3b4068f2..02cb2c1db 100644 --- a/packages/csv-parse/dist/esm/stream.d.ts +++ b/packages/csv-parse/dist/esm/stream.d.ts @@ -1,11 +1,17 @@ - -import { Options } from './index.js'; +import { Options } from "./index.js"; declare function parse(options?: Options): TransformStream; // export default parse; export { parse }; export { - CastingContext, CastingFunction, CastingDateFunction, - ColumnOption, Options, Info, CsvErrorCode, CsvError -} from './index.js'; + CastingContext, + CastingFunction, + CastingDateFunction, + ColumnOption, + Options, + OptionsNormalized, + Info, + CsvErrorCode, + CsvError, +} from "./index.js"; diff --git a/packages/csv-parse/dist/esm/sync.d.ts b/packages/csv-parse/dist/esm/sync.d.ts index b507e8b9c..035fb5959 100644 --- a/packages/csv-parse/dist/esm/sync.d.ts +++ b/packages/csv-parse/dist/esm/sync.d.ts @@ -1,11 +1,30 @@ +import { Options } from "./index.js"; -import { Options } from './index.js'; +type OptionsWithColumns = Omit, "columns"> & { + columns: Exclude; +}; + +declare function parse( + input: Buffer | string | Uint8Array, + options: OptionsWithColumns, +): T[]; +declare function parse( + input: Buffer | string | Uint8Array, + options: Options, +): string[][]; +declare function parse(input: Buffer | string | Uint8Array): string[][]; -declare function parse(input: Buffer | string, options?: Options): any; // export default parse; export { parse }; export { - CastingContext, CastingFunction, CastingDateFunction, - ColumnOption, Options, Info, CsvErrorCode, CsvError -} from './index.js'; + CastingContext, + CastingFunction, + CastingDateFunction, + ColumnOption, + Options, + OptionsNormalized, + Info, + CsvErrorCode, + CsvError, +} from "./index.js"; diff --git a/packages/csv-parse/dist/esm/sync.js b/packages/csv-parse/dist/esm/sync.js index fc824a426..22c54d35a 100644 --- a/packages/csv-parse/dist/esm/sync.js +++ b/packages/csv-parse/dist/esm/sync.js @@ -831,8 +831,8 @@ function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1591,7 +1591,7 @@ Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, no Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1601,7 +1601,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1614,7 +1614,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1627,7 +1627,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1642,7 +1642,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2249,7 +2249,7 @@ const normalize_options = function (opts) { ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -2781,7 +2781,7 @@ const normalize_options = function (opts) { // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -2800,7 +2800,7 @@ const normalize_options = function (opts) { // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -2931,10 +2931,14 @@ const transform = function (original_options = {}) { this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options({ + const options = normalize_options({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -3677,10 +3681,14 @@ const transform = function (original_options = {}) { if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -3734,10 +3742,13 @@ const parse = function (data, opts = {}) { } }; const close = () => {}; - const err1 = parser.parse(data, false, push, close); - if (err1 !== undefined) throw err1; - const err2 = parser.parse(undefined, true, push, close); - if (err2 !== undefined) throw err2; + const error = parser.parse(data, true, push, close); + if (error !== undefined) throw error; + // 250606: `parser.parse` was implemented as 2 calls: + // const err1 = parser.parse(data, false, push, close); + // if (err1 !== undefined) throw err1; + // const err2 = parser.parse(undefined, true, push, close); + // if (err2 !== undefined) throw err2; return records; }; diff --git a/packages/csv-parse/dist/iife/index.js b/packages/csv-parse/dist/iife/index.js index 16f849e6f..6be17e805 100644 --- a/packages/csv-parse/dist/iife/index.js +++ b/packages/csv-parse/dist/iife/index.js @@ -834,8 +834,8 @@ var csv_parse = (function (exports) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1594,7 +1594,7 @@ var csv_parse = (function (exports) { Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1604,7 +1604,7 @@ var csv_parse = (function (exports) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1617,7 +1617,7 @@ var csv_parse = (function (exports) { Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1630,7 +1630,7 @@ var csv_parse = (function (exports) { Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1645,7 +1645,7 @@ var csv_parse = (function (exports) { Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2003,7 +2003,9 @@ var csv_parse = (function (exports) { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2572,94 +2574,19 @@ var csv_parse = (function (exports) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ @@ -5406,7 +5333,7 @@ var csv_parse = (function (exports) { ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -5938,7 +5865,7 @@ var csv_parse = (function (exports) { // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -5957,7 +5884,7 @@ var csv_parse = (function (exports) { // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -6088,10 +6015,14 @@ var csv_parse = (function (exports) { this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options({ + const options = normalize_options({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -6834,10 +6765,14 @@ var csv_parse = (function (exports) { if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -7003,6 +6938,7 @@ var csv_parse = (function (exports) { exports.CsvError = CsvError; exports.Parser = Parser; + exports.normalize_options = normalize_options; exports.parse = parse; return exports; diff --git a/packages/csv-parse/dist/iife/sync.js b/packages/csv-parse/dist/iife/sync.js index bf710048f..7917bdad1 100644 --- a/packages/csv-parse/dist/iife/sync.js +++ b/packages/csv-parse/dist/iife/sync.js @@ -834,8 +834,8 @@ var csv_parse_sync = (function (exports) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1594,7 +1594,7 @@ var csv_parse_sync = (function (exports) { Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1604,7 +1604,7 @@ var csv_parse_sync = (function (exports) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1617,7 +1617,7 @@ var csv_parse_sync = (function (exports) { Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1630,7 +1630,7 @@ var csv_parse_sync = (function (exports) { Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1645,7 +1645,7 @@ var csv_parse_sync = (function (exports) { Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2252,7 +2252,7 @@ var csv_parse_sync = (function (exports) { ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -2784,7 +2784,7 @@ var csv_parse_sync = (function (exports) { // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -2803,7 +2803,7 @@ var csv_parse_sync = (function (exports) { // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -2934,10 +2934,14 @@ var csv_parse_sync = (function (exports) { this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options({ + const options = normalize_options({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -3680,10 +3684,14 @@ var csv_parse_sync = (function (exports) { if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -3737,10 +3745,13 @@ var csv_parse_sync = (function (exports) { } }; const close = () => {}; - const err1 = parser.parse(data, false, push, close); - if (err1 !== undefined) throw err1; - const err2 = parser.parse(undefined, true, push, close); - if (err2 !== undefined) throw err2; + const error = parser.parse(data, true, push, close); + if (error !== undefined) throw error; + // 250606: `parser.parse` was implemented as 2 calls: + // const err1 = parser.parse(data, false, push, close); + // if (err1 !== undefined) throw err1; + // const err2 = parser.parse(undefined, true, push, close); + // if (err2 !== undefined) throw err2; return records; }; diff --git a/packages/csv-parse/dist/umd/index.js b/packages/csv-parse/dist/umd/index.js index 688695bd8..8f506acff 100644 --- a/packages/csv-parse/dist/umd/index.js +++ b/packages/csv-parse/dist/umd/index.js @@ -837,8 +837,8 @@ byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1597,7 +1597,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1607,7 +1607,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1620,7 +1620,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1633,7 +1633,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1648,7 +1648,7 @@ Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2006,7 +2006,9 @@ this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2575,94 +2577,19 @@ Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ @@ -5409,7 +5336,7 @@ ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -5941,7 +5868,7 @@ // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -5960,7 +5887,7 @@ // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -6091,10 +6018,14 @@ this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options({ + const options = normalize_options({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -6837,10 +6768,14 @@ if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -7006,6 +6941,7 @@ exports.CsvError = CsvError; exports.Parser = Parser; + exports.normalize_options = normalize_options; exports.parse = parse; })); diff --git a/packages/csv-parse/dist/umd/sync.js b/packages/csv-parse/dist/umd/sync.js index 8aef129fe..755bbd0df 100644 --- a/packages/csv-parse/dist/umd/sync.js +++ b/packages/csv-parse/dist/umd/sync.js @@ -837,8 +837,8 @@ byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1597,7 +1597,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1607,7 +1607,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1620,7 +1620,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1633,7 +1633,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1648,7 +1648,7 @@ Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2255,7 +2255,7 @@ ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -2787,7 +2787,7 @@ // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -2806,7 +2806,7 @@ // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -2937,10 +2937,14 @@ this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options({ + const options = normalize_options({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -3683,10 +3687,14 @@ if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -3740,10 +3748,13 @@ } }; const close = () => {}; - const err1 = parser.parse(data, false, push, close); - if (err1 !== undefined) throw err1; - const err2 = parser.parse(undefined, true, push, close); - if (err2 !== undefined) throw err2; + const error = parser.parse(data, true, push, close); + if (error !== undefined) throw error; + // 250606: `parser.parse` was implemented as 2 calls: + // const err1 = parser.parse(data, false, push, close); + // if (err1 !== undefined) throw err1; + // const err2 = parser.parse(undefined, true, push, close); + // if (err2 !== undefined) throw err2; return records; }; diff --git a/packages/csv-parse/lib/api/index.js b/packages/csv-parse/lib/api/index.js index a1ba1eb02..5dffecc8e 100644 --- a/packages/csv-parse/lib/api/index.js +++ b/packages/csv-parse/lib/api/index.js @@ -115,10 +115,14 @@ const transform = function (original_options = {}) { this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options({ + const options = normalize_options({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -861,10 +865,14 @@ const transform = function (original_options = {}) { if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; diff --git a/packages/csv-parse/lib/api/normalize_options.js b/packages/csv-parse/lib/api/normalize_options.js index ecb1eaaa8..440addfd1 100644 --- a/packages/csv-parse/lib/api/normalize_options.js +++ b/packages/csv-parse/lib/api/normalize_options.js @@ -95,7 +95,7 @@ const normalize_options = function (opts) { ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -650,7 +650,7 @@ const normalize_options = function (opts) { // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -669,7 +669,7 @@ const normalize_options = function (opts) { // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } diff --git a/packages/csv-parse/lib/index.d.ts b/packages/csv-parse/lib/index.d.ts index ec8aa027e..403243a65 100644 --- a/packages/csv-parse/lib/index.d.ts +++ b/packages/csv-parse/lib/index.d.ts @@ -4,280 +4,504 @@ import * as stream from "stream"; -export type Callback = (err: CsvError | undefined, records: any | undefined, info: Info) => void; +export type Callback = ( + err: CsvError | undefined, + records: T[], + info?: Info, +) => void; -export interface Parser extends stream.Transform {} +// export interface Parser extends stream.Transform {} -export class Parser { - constructor(options: Options); - - __push(line: any): any; - - __write(chars: any, end: any, callback: any): any; - - readonly options: Options - - readonly info: Info; +// export class Parser extends stream.Transform { +export class Parser extends stream.Transform { + constructor(options: Options); + + // __push(line: T): CsvError | undefined; + __push(line: any): CsvError | undefined; + + // __write(chars: any, end: any, callback: any): any; + + readonly options: OptionsNormalized; + + readonly info: Info; +} + +export interface Info { + /** + * Count the number of lines being fully commented. + */ + readonly comment_lines: number; + /** + * Count the number of processed empty lines. + */ + readonly empty_lines: number; + /** + * The number of lines encountered in the source dataset, start at 1 for the first line. + */ + readonly lines: number; + /** + * Count the number of processed records. + */ + readonly records: number; + /** + * Count of the number of processed bytes. + */ + readonly bytes: number; + /** + * Number of non uniform records when `relax_column_count` is true. + */ + readonly invalid_field_length: number; + /** + * Normalized verion of `options.columns` when `options.columns` is true, boolean otherwise. + */ + readonly columns: boolean | { name: string }[] | { disabled: true }[]; } export interface CastingContext { - readonly column: number | string; - readonly empty_lines: number; - readonly error: CsvError; - readonly header: boolean; - readonly index: number; - readonly quoting: boolean; - readonly lines: number; - readonly records: number; - readonly invalid_field_length: number; + readonly column: number | string; + readonly empty_lines: number; + readonly error: CsvError; + readonly header: boolean; + readonly index: number; + readonly quoting: boolean; + readonly lines: number; + readonly raw: string | undefined; + readonly records: number; + readonly invalid_field_length: number; } -export type CastingFunction = (value: string, context: CastingContext) => any; +export type CastingFunction = ( + value: string, + context: CastingContext, +) => unknown; + +export type CastingDateFunction = ( + value: string, + context: CastingContext, +) => Date; -export type CastingDateFunction = (value: string, context: CastingContext) => Date; +export type ColumnOption = + | K + | undefined + | null + | false + | { name: K }; -export type ColumnOption = string | undefined | null | false | { name: string }; +export interface OptionsNormalized { + auto_parse?: boolean | CastingFunction; + auto_parse_date?: boolean | CastingDateFunction; + /** + * If true, detect and exclude the byte order mark (BOM) from the CSV input if present. + */ + bom?: boolean; + /** + * If true, the parser will attempt to convert input string to native types. + * If a function, receive the value as first argument, a context as second argument and return a new value. More information about the context properties is available below. + */ + cast?: boolean | CastingFunction; + /** + * If true, the parser will attempt to convert input string to dates. + * If a function, receive the value as argument and return a new value. It requires the "auto_parse" option. Be careful, it relies on Date.parse. + */ + cast_date?: boolean | CastingDateFunction; + /** + * Internal property string the function to + */ + cast_first_line_to_header?: ( + record: T, + ) => ColumnOption< + T extends string[] ? string : T extends unknown ? string : keyof T + >[]; + /** + * List of fields as an array, a user defined callback accepting the first + * line and returning the column names or true if autodiscovered in the first + * CSV line, default to null, affect the result data set in the sense that + * records will be objects instead of arrays. + */ + columns: + | boolean + | ColumnOption< + T extends string[] ? string : T extends unknown ? string : keyof T + >[]; + /** + * Convert values into an array of values when columns are activated and + * when multiple columns of the same name are found. + */ + group_columns_by_name: boolean; + /** + * Treat all the characters after this one as a comment, default to '' (disabled). + */ + comment: string | null; + /** + * Restrict the definition of comments to a full line. Comment characters + * defined in the middle of the line are not interpreted as such. The + * option require the activation of comments. + */ + comment_no_infix: boolean; + /** + * Set the field delimiter. One character only, defaults to comma. + */ + delimiter: Buffer[]; + /** + * Set the source and destination encoding, a value of `null` returns buffer instead of strings. + */ + encoding: BufferEncoding | null; + /** + * Set the escape character, one character only, defaults to double quotes. + */ + escape: null | Buffer; + /** + * Start handling records from the requested number of records. + */ + from: number; + /** + * Start handling records from the requested line number. + */ + from_line: number; + /** + * Don't interpret delimiters as such in the last field according to the number of fields calculated from the number of columns, the option require the presence of the `column` option when `true`. + */ + ignore_last_delimiters: boolean | number; + /** + * Generate two properties `info` and `record` where `info` is a snapshot of the info object at the time the record was created and `record` is the parsed array or object. + */ + info: boolean; + /** + * If true, ignore whitespace immediately following the delimiter (i.e. left-trim all fields), defaults to false. + * Does not remove whitespace in a quoted field. + */ + ltrim: boolean; + /** + * Maximum numer of characters to be contained in the field and line buffers before an exception is raised, + * used to guard against a wrong delimiter or record_delimiter, + * default to 128000 characters. + */ + max_record_size: number; + /** + * Name of header-record title to name objects by. + */ + objname: number | string | undefined; + /** + * Alter and filter records by executing a user defined function. + */ + on_record?: (record: T, context: CastingContext) => T | undefined; + /** + * Optional character surrounding a field, one character only, defaults to double quotes. + */ + quote?: Buffer | null; + /** + * Generate two properties raw and row where raw is the original CSV row content and row is the parsed array or object. + */ + raw: boolean; + /** + * Discard inconsistent columns count, default to false. + */ + relax_column_count: boolean; + /** + * Discard inconsistent columns count when the record contains less fields than expected, default to false. + */ + relax_column_count_less: boolean; + /** + * Discard inconsistent columns count when the record contains more fields than expected, default to false. + */ + relax_column_count_more: boolean; + /** + * Preserve quotes inside unquoted field. + */ + relax_quotes: boolean; + /** + * One or multiple characters used to delimit record rows; defaults to auto discovery if not provided. + * Supported auto discovery method are Linux ("\n"), Apple ("\r") and Windows ("\r\n") row delimiters. + */ + record_delimiter: Buffer[]; + /** + * If true, ignore whitespace immediately preceding the delimiter (i.e. right-trim all fields), defaults to false. + * Does not remove whitespace in a quoted field. + */ + rtrim: boolean; + /** + * Dont generate empty values for empty lines. + * Defaults to false + */ + skip_empty_lines: boolean; + /** + * Skip a line with error found inside and directly go process the next line. + */ + skip_records_with_error: boolean; + /** + * Don't generate records for lines containing empty column values (column matching /\s*\/), defaults to false. + */ + skip_records_with_empty_values: boolean; + /** + * Stop handling records after the requested number of records. + */ + to: number; + /** + * Stop handling records after the requested line number. + */ + to_line: number; + /** + * If true, ignore whitespace immediately around the delimiter, defaults to false. + * Does not remove whitespace in a quoted field. + */ + trim: boolean; +} /* Note, could not `extends stream.TransformOptions` because encoding can be BufferEncoding and undefined as well as null which is not defined in the extended type. */ -export interface Options { - /** - * If true, the parser will attempt to convert read data types to native types. - * @deprecated Use {@link cast} - */ - auto_parse?: boolean | CastingFunction; - autoParse?: boolean | CastingFunction; - /** - * If true, the parser will attempt to convert read data types to dates. It requires the "auto_parse" option. - * @deprecated Use {@link cast_date} - */ - auto_parse_date?: boolean | CastingDateFunction; - autoParseDate?: boolean | CastingDateFunction; - /** - * If true, detect and exclude the byte order mark (BOM) from the CSV input if present. - */ - bom?: boolean; - /** - * If true, the parser will attempt to convert input string to native types. - * If a function, receive the value as first argument, a context as second argument and return a new value. More information about the context properties is available below. - */ - cast?: boolean | CastingFunction; - /** - * If true, the parser will attempt to convert input string to dates. - * If a function, receive the value as argument and return a new value. It requires the "auto_parse" option. Be careful, it relies on Date.parse. - */ - cast_date?: boolean | CastingDateFunction; - castDate?: boolean | CastingDateFunction; - /** - * List of fields as an array, - * a user defined callback accepting the first line and returning the column names or true if autodiscovered in the first CSV line, - * default to null, - * affect the result data set in the sense that records will be objects instead of arrays. - */ - columns?: ColumnOption[] | boolean | ((record: any) => ColumnOption[]); - /** - * Convert values into an array of values when columns are activated and - * when multiple columns of the same name are found. - */ - group_columns_by_name?: boolean; - groupColumnsByName?: boolean; - /** - * Treat all the characters after this one as a comment, default to '' (disabled). - */ - comment?: string; - /** - * Restrict the definition of comments to a full line. Comment characters - * defined in the middle of the line are not interpreted as such. The - * option require the activation of comments. - */ - comment_no_infix?: boolean; - /** - * Set the field delimiter. One character only, defaults to comma. - */ - delimiter?: string | string[] | Buffer; - /** - * Set the source and destination encoding, a value of `null` returns buffer instead of strings. - */ - encoding?: BufferEncoding | undefined; - /** - * Set the escape character, one character only, defaults to double quotes. - */ - escape?: string | null | false | Buffer; - /** - * Start handling records from the requested number of records. - */ - from?: number; - /** - * Start handling records from the requested line number. - */ - from_line?: number; - fromLine?: number; - /** - * Don't interpret delimiters as such in the last field according to the number of fields calculated from the number of columns, the option require the presence of the `column` option when `true`. - */ - ignore_last_delimiters?: boolean | number; - /** - * Generate two properties `info` and `record` where `info` is a snapshot of the info object at the time the record was created and `record` is the parsed array or object. - */ - info?: boolean; - /** - * If true, ignore whitespace immediately following the delimiter (i.e. left-trim all fields), defaults to false. - * Does not remove whitespace in a quoted field. - */ - ltrim?: boolean; - /** - * Maximum numer of characters to be contained in the field and line buffers before an exception is raised, - * used to guard against a wrong delimiter or record_delimiter, - * default to 128000 characters. - */ - max_record_size?: number; - maxRecordSize?: number; - /** - * Name of header-record title to name objects by. - */ - objname?: string; - /** - * Alter and filter records by executing a user defined function. - */ - on_record?: (record: any, context: CastingContext) => any; - onRecord?: (record: any, context: CastingContext) => any; - /** - * Optional character surrounding a field, one character only, defaults to double quotes. - */ - quote?: string | boolean | Buffer | null; - /** - * Generate two properties raw and row where raw is the original CSV row content and row is the parsed array or object. - */ - raw?: boolean; - /** - * Discard inconsistent columns count, default to false. - */ - relax_column_count?: boolean; - relaxColumnCount?: boolean; - /** - * Discard inconsistent columns count when the record contains less fields than expected, default to false. - */ - relax_column_count_less?: boolean; - relaxColumnCountLess?: boolean; - /** - * Discard inconsistent columns count when the record contains more fields than expected, default to false. - */ - relax_column_count_more?: boolean; - relaxColumnCountMore?: boolean; - /** - * Preserve quotes inside unquoted field. - */ - relax_quotes?: boolean; - relaxQuotes?: boolean; - /** - * One or multiple characters used to delimit record rows; defaults to auto discovery if not provided. - * Supported auto discovery method are Linux ("\n"), Apple ("\r") and Windows ("\r\n") row delimiters. - */ - record_delimiter?: string | string[] | Buffer | Buffer[]; - recordDelimiter?: string | string[] | Buffer | Buffer[]; - /** - * If true, ignore whitespace immediately preceding the delimiter (i.e. right-trim all fields), defaults to false. - * Does not remove whitespace in a quoted field. - */ - rtrim?: boolean; - /** - * Dont generate empty values for empty lines. - * Defaults to false - */ - skip_empty_lines?: boolean; - skipEmptyLines?: boolean; - /** - * Skip a line with error found inside and directly go process the next line. - */ - skip_records_with_error?: boolean; - skipRecordsWithError?: boolean; - /** - * Don't generate records for lines containing empty column values (column matching /\s*\/), defaults to false. - */ - skip_records_with_empty_values?: boolean; - skipRecordsWithEmptyValues?: boolean; - /** - * Stop handling records after the requested number of records. - */ - to?: number; - /** - * Stop handling records after the requested line number. - */ - to_line?: number; - toLine?: number; - /** - * If true, ignore whitespace immediately around the delimiter, defaults to false. - * Does not remove whitespace in a quoted field. - */ - trim?: boolean; -} - -export interface Info { - /** - * Count the number of lines being fully commented. - */ - readonly comment_lines: number; - /** - * Count the number of processed empty lines. - */ - readonly empty_lines: number; - /** - * The number of lines encountered in the source dataset, start at 1 for the first line. - */ - readonly lines: number; - /** - * Count the number of processed records. - */ - readonly records: number; - /** - * Count of the number of processed bytes. - */ - readonly bytes: number; - /** - * Number of non uniform records when `relax_column_count` is true. - */ - readonly invalid_field_length: number; - /** - * Normalized verion of `options.columns` when `options.columns` is true, boolean otherwise. - */ - readonly columns: boolean | { name: string }[] | { disabled: true }[]; +export interface Options { + /** + * If true, the parser will attempt to convert read data types to native types. + * @deprecated Use {@link cast} + */ + auto_parse?: boolean | CastingFunction; + autoParse?: boolean | CastingFunction; + /** + * If true, the parser will attempt to convert read data types to dates. It requires the "auto_parse" option. + * @deprecated Use {@link cast_date} + */ + auto_parse_date?: boolean | CastingDateFunction; + autoParseDate?: boolean | CastingDateFunction; + /** + * If true, detect and exclude the byte order mark (BOM) from the CSV input if present. + */ + bom?: boolean; + /** + * If true, the parser will attempt to convert input string to native types. + * If a function, receive the value as first argument, a context as second argument and return a new value. More information about the context properties is available below. + */ + cast?: boolean | CastingFunction; + /** + * If true, the parser will attempt to convert input string to dates. + * If a function, receive the value as argument and return a new value. It requires the "auto_parse" option. Be careful, it relies on Date.parse. + */ + cast_date?: boolean | CastingDateFunction; + castDate?: boolean | CastingDateFunction; + /** + * List of fields as an array, + * a user defined callback accepting the first line and returning the column names or true if autodiscovered in the first CSV line, + * default to null, + * affect the result data set in the sense that records will be objects instead of arrays. + */ + columns?: + | boolean + | ColumnOption< + T extends string[] ? string : T extends unknown ? string : keyof T + >[] + | (( + record: T, + ) => ColumnOption< + T extends string[] ? string : T extends unknown ? string : keyof T + >[]); + /** + * Convert values into an array of values when columns are activated and + * when multiple columns of the same name are found. + */ + group_columns_by_name?: boolean; + groupColumnsByName?: boolean; + /** + * Treat all the characters after this one as a comment, default to '' (disabled). + */ + comment?: string | boolean | null; + /** + * Restrict the definition of comments to a full line. Comment characters + * defined in the middle of the line are not interpreted as such. The + * option require the activation of comments. + */ + comment_no_infix?: boolean | null; + /** + * Set the field delimiter. One character only, defaults to comma. + */ + delimiter?: string | string[] | Buffer; + /** + * Set the source and destination encoding, a value of `null` returns buffer instead of strings. + */ + encoding?: BufferEncoding | boolean | null | undefined; + /** + * Set the escape character, one character only, defaults to double quotes. + */ + escape?: string | null | boolean | Buffer; + /** + * Start handling records from the requested number of records. + */ + from?: number | string; + /** + * Start handling records from the requested line number. + */ + from_line?: null | number | string; + fromLine?: null | number | string; + /** + * Don't interpret delimiters as such in the last field according to the number of fields calculated from the number of columns, the option require the presence of the `column` option when `true`. + */ + ignore_last_delimiters?: boolean | number; + /** + * Generate two properties `info` and `record` where `info` is a snapshot of the info object at the time the record was created and `record` is the parsed array or object. + */ + info?: boolean; + /** + * If true, ignore whitespace immediately following the delimiter (i.e. left-trim all fields), defaults to false. + * Does not remove whitespace in a quoted field. + */ + ltrim?: boolean | null; + /** + * Maximum numer of characters to be contained in the field and line buffers before an exception is raised, + * used to guard against a wrong delimiter or record_delimiter, + * default to 128000 characters. + */ + max_record_size?: number | null | string; + maxRecordSize?: number; + /** + * Name of header-record title to name objects by. + */ + objname?: Buffer | null | number | string; + /** + * Alter and filter records by executing a user defined function. + */ + on_record?: (record: T, context: CastingContext) => T | null | undefined; + onRecord?: (record: T, context: CastingContext) => T | null | undefined; + /** + * Function called when an error occured if the `skip_records_with_error` + * option is activated. + */ + on_skip?: (err: CsvError | undefined, raw: string | undefined) => undefined; + onSkip?: (err: CsvError | undefined, raw: string | undefined) => undefined; + /** + * Optional character surrounding a field, one character only, defaults to double quotes. + */ + quote?: string | boolean | Buffer | null; + /** + * Generate two properties raw and row where raw is the original CSV row content and row is the parsed array or object. + */ + raw?: boolean | null; + /** + * One or multiple characters used to delimit record rows; defaults to auto discovery if not provided. + * Supported auto discovery method are Linux ("\n"), Apple ("\r") and Windows ("\r\n") row delimiters. + */ + record_delimiter?: string | Buffer | null | (string | Buffer | null)[]; + recordDelimiter?: string | Buffer | null | (string | Buffer | null)[]; + /** + * Discard inconsistent columns count, default to false. + */ + relax_column_count?: boolean | null; + relaxColumnCount?: boolean | null; + /** + * Discard inconsistent columns count when the record contains less fields than expected, default to false. + */ + relax_column_count_less?: boolean | null; + relaxColumnCountLess?: boolean | null; + /** + * Discard inconsistent columns count when the record contains more fields than expected, default to false. + */ + relax_column_count_more?: boolean | null; + relaxColumnCountMore?: boolean | null; + /** + * Preserve quotes inside unquoted field. + */ + relax_quotes?: boolean | null; + relaxQuotes?: boolean | null; + /** + * If true, ignore whitespace immediately preceding the delimiter (i.e. right-trim all fields), defaults to false. + * Does not remove whitespace in a quoted field. + */ + rtrim?: boolean | null; + /** + * Dont generate empty values for empty lines. + * Defaults to false + */ + skip_empty_lines?: boolean | null; + skipEmptyLines?: boolean | null; + /** + * Don't generate records for lines containing empty column values (column matching /\s*\/), defaults to false. + */ + skip_records_with_empty_values?: boolean | null; + skipRecordsWithEmptyValues?: boolean | null; + /** + * Skip a line with error found inside and directly go process the next line. + */ + skip_records_with_error?: boolean | null; + skipRecordsWithError?: boolean | null; + /** + * Stop handling records after the requested number of records. + */ + to?: null | number | string; + /** + * Stop handling records after the requested line number. + */ + to_line?: null | number | string; + toLine?: null | number | string; + /** + * If true, ignore whitespace immediately around the delimiter, defaults to false. + * Does not remove whitespace in a quoted field. + */ + trim?: boolean | null; } -export type CsvErrorCode = - 'CSV_INVALID_OPTION_BOM' - | 'CSV_INVALID_OPTION_CAST' - | 'CSV_INVALID_OPTION_CAST_DATE' - | 'CSV_INVALID_OPTION_COLUMNS' - | 'CSV_INVALID_OPTION_GROUP_COLUMNS_BY_NAME' - | 'CSV_INVALID_OPTION_COMMENT' - | 'CSV_INVALID_OPTION_DELIMITER' - | 'CSV_INVALID_OPTION_ON_RECORD' - | 'CSV_INVALID_CLOSING_QUOTE' - | 'INVALID_OPENING_QUOTE' - | 'CSV_INVALID_COLUMN_MAPPING' - | 'CSV_INVALID_ARGUMENT' - | 'CSV_INVALID_COLUMN_DEFINITION' - | 'CSV_MAX_RECORD_SIZE' - | 'CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE' - | 'CSV_QUOTE_NOT_CLOSED' - | 'CSV_RECORD_INCONSISTENT_FIELDS_LENGTH' - | 'CSV_RECORD_INCONSISTENT_COLUMNS' - | 'CSV_OPTION_COLUMNS_MISSING_NAME' +export type CsvErrorCode = + | "CSV_INVALID_ARGUMENT" + | "CSV_INVALID_CLOSING_QUOTE" + | "CSV_INVALID_COLUMN_DEFINITION" + | "CSV_INVALID_COLUMN_MAPPING" + | "CSV_INVALID_OPTION_BOM" + | "CSV_INVALID_OPTION_CAST" + | "CSV_INVALID_OPTION_CAST_DATE" + | "CSV_INVALID_OPTION_COLUMNS" + | "CSV_INVALID_OPTION_COMMENT" + | "CSV_INVALID_OPTION_DELIMITER" + | "CSV_INVALID_OPTION_GROUP_COLUMNS_BY_NAME" + | "CSV_INVALID_OPTION_ON_RECORD" + | "CSV_MAX_RECORD_SIZE" + | "CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE" + | "CSV_OPTION_COLUMNS_MISSING_NAME" + | "CSV_QUOTE_NOT_CLOSED" + | "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH" + | "CSV_RECORD_INCONSISTENT_COLUMNS" + | "CSV_UNKNOWN_ERROR" + | "INVALID_OPENING_QUOTE"; export class CsvError extends Error { - readonly code: CsvErrorCode; - [key: string]: any; + readonly code: CsvErrorCode; + [key: string]: any; - constructor(code: CsvErrorCode, message: string | string[], options?: Options, ...contexts: any[]); + constructor( + code: CsvErrorCode, + message: string | string[], + options?: OptionsNormalized, + ...contexts: unknown[] + ); } -declare function parse(input: Buffer | string, options?: Options, callback?: Callback): Parser; -declare function parse(input: Buffer | string, callback?: Callback): Parser; -declare function parse(options?: Options, callback?: Callback): Parser; +type OptionsWithColumns = Omit, "columns"> & { + columns: Exclude; +}; + +declare function parse( + input: string | Buffer | Uint8Array, + options: OptionsWithColumns, + callback?: Callback, +): Parser; +declare function parse( + input: string | Buffer | Uint8Array, + options: Options, + callback?: Callback, +): Parser; + +declare function parse( + options: OptionsWithColumns, + callback?: Callback, +): Parser; +declare function parse(options: Options, callback?: Callback): Parser; + +declare function parse( + input: string | Buffer | Uint8Array, + callback?: Callback, +): Parser; declare function parse(callback?: Callback): Parser; // export default parse; -export { parse } +export { parse }; + +declare function normalize_options(opts: Options): OptionsNormalized; +export { normalize_options }; diff --git a/packages/csv-parse/lib/index.js b/packages/csv-parse/lib/index.js index 67eb68dff..35e44820f 100644 --- a/packages/csv-parse/lib/index.js +++ b/packages/csv-parse/lib/index.js @@ -9,6 +9,7 @@ import { Transform } from "stream"; import { is_object } from "./utils/is_object.js"; import { transform } from "./api/index.js"; import { CsvError } from "./api/CsvError.js"; +import { normalize_options } from "./api/normalize_options.js"; class Parser extends Transform { constructor(opts = {}) { @@ -134,4 +135,4 @@ const parse = function () { }; // export default parse -export { parse, Parser, CsvError }; +export { parse, Parser, CsvError, normalize_options }; diff --git a/packages/csv-parse/lib/stream.d.ts b/packages/csv-parse/lib/stream.d.ts index f3b4068f2..02cb2c1db 100644 --- a/packages/csv-parse/lib/stream.d.ts +++ b/packages/csv-parse/lib/stream.d.ts @@ -1,11 +1,17 @@ - -import { Options } from './index.js'; +import { Options } from "./index.js"; declare function parse(options?: Options): TransformStream; // export default parse; export { parse }; export { - CastingContext, CastingFunction, CastingDateFunction, - ColumnOption, Options, Info, CsvErrorCode, CsvError -} from './index.js'; + CastingContext, + CastingFunction, + CastingDateFunction, + ColumnOption, + Options, + OptionsNormalized, + Info, + CsvErrorCode, + CsvError, +} from "./index.js"; diff --git a/packages/csv-parse/lib/sync.d.ts b/packages/csv-parse/lib/sync.d.ts index b507e8b9c..035fb5959 100644 --- a/packages/csv-parse/lib/sync.d.ts +++ b/packages/csv-parse/lib/sync.d.ts @@ -1,11 +1,30 @@ +import { Options } from "./index.js"; -import { Options } from './index.js'; +type OptionsWithColumns = Omit, "columns"> & { + columns: Exclude; +}; + +declare function parse( + input: Buffer | string | Uint8Array, + options: OptionsWithColumns, +): T[]; +declare function parse( + input: Buffer | string | Uint8Array, + options: Options, +): string[][]; +declare function parse(input: Buffer | string | Uint8Array): string[][]; -declare function parse(input: Buffer | string, options?: Options): any; // export default parse; export { parse }; export { - CastingContext, CastingFunction, CastingDateFunction, - ColumnOption, Options, Info, CsvErrorCode, CsvError -} from './index.js'; + CastingContext, + CastingFunction, + CastingDateFunction, + ColumnOption, + Options, + OptionsNormalized, + Info, + CsvErrorCode, + CsvError, +} from "./index.js"; diff --git a/packages/csv-parse/lib/sync.js b/packages/csv-parse/lib/sync.js index 5e6b374e5..d48518455 100644 --- a/packages/csv-parse/lib/sync.js +++ b/packages/csv-parse/lib/sync.js @@ -13,10 +13,13 @@ const parse = function (data, opts = {}) { } }; const close = () => {}; - const err1 = parser.parse(data, false, push, close); - if (err1 !== undefined) throw err1; - const err2 = parser.parse(undefined, true, push, close); - if (err2 !== undefined) throw err2; + const error = parser.parse(data, true, push, close); + if (error !== undefined) throw error; + // 250606: `parser.parse` was implemented as 2 calls: + // const err1 = parser.parse(data, false, push, close); + // if (err1 !== undefined) throw err1; + // const err2 = parser.parse(undefined, true, push, close); + // if (err2 !== undefined) throw err2; return records; }; diff --git a/packages/csv-parse/package.json b/packages/csv-parse/package.json index 563084873..cdc1846ce 100644 --- a/packages/csv-parse/package.json +++ b/packages/csv-parse/package.json @@ -1,5 +1,5 @@ { - "version": "5.6.0", + "version": "6.1.0", "name": "csv-parse", "description": "CSV parsing implementing the Node.js `stream.Transform` API", "keywords": [ @@ -72,28 +72,23 @@ } }, "devDependencies": { - "@eslint/js": "^9.15.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@types/mocha": "^10.0.9", - "@types/node": "^22.9.1", - "coffeescript": "^2.7.0", - "csv-generate": "^4.4.2", + "@rollup/plugin-node-resolve": "^16.0.1", + "@types/mocha": "^10.0.10", + "@types/node": "^22.15.30", + "csv-generate": "^4.5.0", "csv-spectrum": "^2.0.0", + "dedent": "^1.6.0", "each": "^2.7.2", - "eslint": "^9.15.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-mocha": "^10.5.0", - "eslint-plugin-prettier": "^5.2.1", - "mocha": "^10.8.2", + "mocha": "^11.5.0", "pad": "^3.3.0", - "prettier": "^3.3.3", - "rollup": "^4.27.3", + "prettier": "^3.5.3", + "rollup": "^4.41.1", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "should": "^13.2.3", - "stream-transform": "^3.3.3", + "stream-transform": "^3.4.0", "ts-node": "^10.9.2", - "typescript": "^5.6.3" + "typescript": "^5.8.3" }, "files": [ "dist", @@ -104,19 +99,12 @@ "main": "./dist/cjs/index.cjs", "mocha": { "inline-diffs": true, - "loader": "./test/loaders/all.js", + "loader": "ts-node/esm", "recursive": true, "reporter": "spec", - "require": [ - "should" - ], "throw-deprecation": false, "timeout": 40000 }, - "lint-staged": { - "*.js": "npm run lint:fix", - "*.md": "prettier -w" - }, "repository": { "type": "git", "url": "https://github.com/adaltas/node-csv.git", @@ -131,8 +119,8 @@ "lint:fix": "eslint --fix", "lint:ts": "tsc --noEmit true", "preversion": "npm run build && git add dist", - "test": "mocha 'test/**/*.{coffee,ts}'", - "test:legacy": "mocha --ignore test/api.web_stream.coffee --ignore test/api.web_stream.ts --ignore test/api.stream.finished.coffee --ignore test/api.stream.iterator.coffee --loader=./test/loaders/legacy/all.js 'test/**/*.{coffee,ts}'" + "test": "mocha 'test/**/*.{js,ts}'", + "test:legacy": "mocha --ignore test/api.web_stream.js --ignore test/api.web_stream.ts --ignore test/api.stream.finished.ts --ignore test/api.stream.iterator.ts 'test/**/*.{js,ts}'" }, "type": "module", "types": "dist/esm/index.d.ts", diff --git a/packages/csv-parse/samples/api.callback.js b/packages/csv-parse/samples/api.callback.js index 30b61d74c..c5843a12c 100644 --- a/packages/csv-parse/samples/api.callback.js +++ b/packages/csv-parse/samples/api.callback.js @@ -1,9 +1,13 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; -const input = '#Welcome\n"1","2","3","4"\n"a","b","c","d"'; parse( - input, + dedent` + # Welcome + "1","2","3","4" + "a","b","c","d" + `, { comment: "#", }, diff --git a/packages/csv-parse/samples/comment.js b/packages/csv-parse/samples/comment.js index 695b49313..4fe3247cf 100644 --- a/packages/csv-parse/samples/comment.js +++ b/packages/csv-parse/samples/comment.js @@ -1,8 +1,13 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; parse( - '#Welcome\n"1","2","3","4"\n"a","b","c","d"', + dedent` + # Welcome + "1","2","3","4" + "a","b","c","d" + `, { comment: "#" }, function (err, data) { assert.deepStrictEqual(data, [ diff --git a/packages/csv-parse/samples/mixed.output_stream.js b/packages/csv-parse/samples/mixed.output_stream.js index b9dd10d8f..3c583d7b5 100644 --- a/packages/csv-parse/samples/mixed.output_stream.js +++ b/packages/csv-parse/samples/mixed.output_stream.js @@ -1,12 +1,13 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; const records = []; parse( - ` - "1","2","3" - "a","b","c" -`, + dedent` + "1","2","3" + "a","b","c" + `, { trim: true, skip_empty_lines: true, diff --git a/packages/csv-parse/samples/option.cast.context.js b/packages/csv-parse/samples/option.cast.context.js index cae9ef6a9..a79bbe0c8 100644 --- a/packages/csv-parse/samples/option.cast.context.js +++ b/packages/csv-parse/samples/option.cast.context.js @@ -1,10 +1,11 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse/sync"; -const data = ` +const data = dedent` 2000-01-01,date1 2050-11-27,date2 -`.trim(); +`; const records = parse(data, { // The cast option exect a function which // is called with two arguments, @@ -43,7 +44,7 @@ assert.deepStrictEqual(records, [ [ "2050-11-27T05:00:00.000Z", { - bytes: 35, + bytes: 33, comment_lines: 0, empty_lines: 0, invalid_field_length: 0, diff --git a/packages/csv-parse/samples/option.cast.header.column.fn.js b/packages/csv-parse/samples/option.cast.header.column.fn.js index 1426f5e84..382e84942 100644 --- a/packages/csv-parse/samples/option.cast.header.column.fn.js +++ b/packages/csv-parse/samples/option.cast.header.column.fn.js @@ -1,18 +1,26 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse/sync"; assert.deepEqual( - parse("a,b,c\n1,2,3\n4,5,6", { - cast: (value, context) => { - if (context.header) return value; - if (context.column === "B") return Number(value); - return String(value); + parse( + dedent` + a,b,c + 1,2,3 + 4,5,6 + `, + { + cast: (value, context) => { + if (context.header) return value; + if (context.column === "B") return Number(value); + return String(value); + }, + columns: (header) => { + return header.map((label) => label.toUpperCase()); + }, + trim: true, }, - columns: (header) => { - return header.map((label) => label.toUpperCase()); - }, - trim: true, - }), + ), [ { A: "1", B: 2, C: "3" }, { A: "4", B: 5, C: "6" }, diff --git a/packages/csv-parse/samples/option.cast.header.columns.true.js b/packages/csv-parse/samples/option.cast.header.columns.true.js index c7de0f764..24c6abe4c 100644 --- a/packages/csv-parse/samples/option.cast.header.columns.true.js +++ b/packages/csv-parse/samples/option.cast.header.columns.true.js @@ -1,16 +1,24 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse/sync"; assert.deepEqual( - parse("a,b,c\n1,2,3\n4,5,6", { - cast: (value, context) => { - if (context.header) return value.toUpperCase(); - if (context.column === "B") return Number(value); - return String(value); + parse( + dedent` + a,b,c + 1,2,3 + 4,5,6 + `, + { + cast: (value, context) => { + if (context.header) return value.toUpperCase(); + if (context.column === "B") return Number(value); + return String(value); + }, + columns: true, + trim: true, }, - columns: true, - trim: true, - }), + ), [ { A: "1", B: 2, C: "3" }, { A: "4", B: 5, C: "6" }, diff --git a/packages/csv-parse/samples/option.cast.js b/packages/csv-parse/samples/option.cast.js index 482efb341..3ce02be79 100644 --- a/packages/csv-parse/samples/option.cast.js +++ b/packages/csv-parse/samples/option.cast.js @@ -1,10 +1,11 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse/sync"; -const data = ` +const data = dedent` 1,2,3 4,5,6 -`.trim(); +`; const records = parse(data, { // The cast option exect a function which // is called with two arguments, diff --git a/packages/csv-parse/samples/option.cast_date.js b/packages/csv-parse/samples/option.cast_date.js index e3b282f2f..5fb59e1eb 100644 --- a/packages/csv-parse/samples/option.cast_date.js +++ b/packages/csv-parse/samples/option.cast_date.js @@ -1,10 +1,11 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse/sync"; -const data = ` -2000-01-01,date1 -2020-01-01,date2 -`.trim(); +const data = dedent` + 2000-01-01,date1 + 2020-01-01,date2 +`; const records = parse(data, { cast: true, cast_date: true, diff --git a/packages/csv-parse/samples/option.columns.array.js b/packages/csv-parse/samples/option.columns.array.js index 06ddb71be..49e79b59f 100644 --- a/packages/csv-parse/samples/option.columns.array.js +++ b/packages/csv-parse/samples/option.columns.array.js @@ -2,9 +2,7 @@ import assert from "node:assert"; import { parse } from "csv-parse"; parse( - ` -"value 1","value 2" -`.trim(), + '"value 1","value 2"', { columns: ["key_1", "key_2"], }, diff --git a/packages/csv-parse/samples/option.columns.function.js b/packages/csv-parse/samples/option.columns.function.js index a6fa7a873..7328fe549 100644 --- a/packages/csv-parse/samples/option.columns.function.js +++ b/packages/csv-parse/samples/option.columns.function.js @@ -1,11 +1,12 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; parse( - ` -"key_1","key_2" -"value 1","value 2" -`.trim(), + dedent` + "key_1","key_2" + "value 1","value 2" + `, { columns: (header) => header.map((column) => column.toUpperCase()), }, diff --git a/packages/csv-parse/samples/option.columns.true.js b/packages/csv-parse/samples/option.columns.true.js index b244d6b06..9656dd3ba 100644 --- a/packages/csv-parse/samples/option.columns.true.js +++ b/packages/csv-parse/samples/option.columns.true.js @@ -1,11 +1,12 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; parse( - ` -"key_1","key_2" -"value 1","value 2" -`.trim(), + dedent` + "key_1","key_2" + "value 1","value 2" + `, { columns: true, }, diff --git a/packages/csv-parse/samples/option.comment.js b/packages/csv-parse/samples/option.comment.js index 20a2f6319..b8e1756be 100644 --- a/packages/csv-parse/samples/option.comment.js +++ b/packages/csv-parse/samples/option.comment.js @@ -1,11 +1,12 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse/sync"; -const data = ` -# At the beginning of a record -"hello" -"world"# At the end of a record -`.trim(); +const data = dedent` + # At the beginning of a record + "hello" + "world"# At the end of a record +`; const records = parse(data, { comment: "#", }); diff --git a/packages/csv-parse/samples/option.comment_no_infix.js b/packages/csv-parse/samples/option.comment_no_infix.js index 24ce92bef..75f59fe99 100644 --- a/packages/csv-parse/samples/option.comment_no_infix.js +++ b/packages/csv-parse/samples/option.comment_no_infix.js @@ -1,11 +1,12 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse/sync"; const output = parse( - ` -# Illustrate the usage of comment_no_infix -a,b#,c -`.trim(), + dedent` + # Illustrate the usage of comment_no_infix + a,b#,c + `, { comment: "#", comment_no_infix: true, diff --git a/packages/csv-parse/samples/option.delimiter.array.js b/packages/csv-parse/samples/option.delimiter.array.js index d0bb0c4aa..e0d6121f7 100644 --- a/packages/csv-parse/samples/option.delimiter.array.js +++ b/packages/csv-parse/samples/option.delimiter.array.js @@ -1,10 +1,12 @@ import assert from "node:assert"; import { parse } from "csv-parse/sync"; -const input = `color name::red::green::blue +const input = ` +color name::red::green::blue Cyan \t "0" :: 255 :: 255 Yellow \t "255" :: "255" ::"0" -Hot Pink \t "255" :: 105 :: "180"`; +Hot Pink \t "255" :: 105 :: "180" +`.trim(); const output = parse(input, { delimiter: ["::", "\t"], diff --git a/packages/csv-parse/samples/option.from.js b/packages/csv-parse/samples/option.from.js index 0da49347a..16bbec059 100644 --- a/packages/csv-parse/samples/option.from.js +++ b/packages/csv-parse/samples/option.from.js @@ -1,13 +1,14 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; parse( - ` -a,b -1,2 -3,4 -5,6 -`.trim(), + dedent` + a,b + 1,2 + 3,4 + 5,6 + `, { columns: true, from: 2, diff --git a/packages/csv-parse/samples/option.on_record.alter.js b/packages/csv-parse/samples/option.on_record.alter.js index bb07c8aa2..44382ec01 100644 --- a/packages/csv-parse/samples/option.on_record.alter.js +++ b/packages/csv-parse/samples/option.on_record.alter.js @@ -1,11 +1,12 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; parse( - ` -a.1,a.2,a.3 -b.1,b.2,b.3 -`.trim(), + dedent` + a.1,a.2,a.3 + b.1,b.2,b.3 + `, { on_record: (record, { lines }) => [lines, record[2], record[0]], }, diff --git a/packages/csv-parse/samples/option.on_record.filter.js b/packages/csv-parse/samples/option.on_record.filter.js index 036ca1008..5d67704f2 100644 --- a/packages/csv-parse/samples/option.on_record.filter.js +++ b/packages/csv-parse/samples/option.on_record.filter.js @@ -1,12 +1,13 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; parse( - ` -line 1 -line 2 -line 3 -`.trim(), + dedent` + line 1 + line 2 + line 3 + `, { on_record: (record, { lines }) => (lines === 2 ? null : record), }, diff --git a/packages/csv-parse/samples/option.on_skip.js b/packages/csv-parse/samples/option.on_skip.js new file mode 100644 index 000000000..101b1acc0 --- /dev/null +++ b/packages/csv-parse/samples/option.on_skip.js @@ -0,0 +1,25 @@ +import assert from "node:assert"; +import dedent from "dedent"; +import { parse } from "csv-parse"; + +parse( + dedent` + a,b,c + invalid + d,e,f + `, + { + skip_records_with_error: true, + on_skip: ({ message, code, record }) => { + assert.equal(message, "Invalid Record Length: expect 3, got 1 on line 2"); + assert.equal(code, "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH"); + assert.deepStrictEqual(record, ["invalid"]); + }, + }, + function (err, records) { + assert.deepStrictEqual(records, [ + ["a", "b", "c"], + ["d", "e", "f"], + ]); + }, +); diff --git a/packages/csv-parse/samples/option.quote.default.js b/packages/csv-parse/samples/option.quote.default.js index f2ef0ea75..cfc2ffc9d 100644 --- a/packages/csv-parse/samples/option.quote.default.js +++ b/packages/csv-parse/samples/option.quote.default.js @@ -1,11 +1,12 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse/sync"; const records = parse( - ` -a,"b",c -"d",e,"f" -`.trim(), + dedent` + a,"b",c + "d",e,"f" + `, ); assert.deepStrictEqual(records, [ diff --git a/packages/csv-parse/samples/option.quote.escape.js b/packages/csv-parse/samples/option.quote.escape.js index bbc09d227..437f2e585 100644 --- a/packages/csv-parse/samples/option.quote.escape.js +++ b/packages/csv-parse/samples/option.quote.escape.js @@ -1,11 +1,12 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse/sync"; const records = parse( - ` -a,"b""b",c -d,"e""e",f -`.trim(), + dedent` + a,"b""b",c + d,"e""e",f + `, ); assert.deepStrictEqual(records, [ diff --git a/packages/csv-parse/samples/option.raw.js b/packages/csv-parse/samples/option.raw.js index 4fa075cb6..4069478d7 100644 --- a/packages/csv-parse/samples/option.raw.js +++ b/packages/csv-parse/samples/option.raw.js @@ -1,11 +1,12 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; parse( - ` -a,b,c -d,e,f -`.trim(), + dedent` + a,b,c + d,e,f + `, { raw: true }, (err, records) => { assert.deepStrictEqual(records, [ diff --git a/packages/csv-parse/samples/option.relax_column_count.columns.js b/packages/csv-parse/samples/option.relax_column_count.columns.js index 9401b0339..2ca0940a0 100644 --- a/packages/csv-parse/samples/option.relax_column_count.columns.js +++ b/packages/csv-parse/samples/option.relax_column_count.columns.js @@ -1,12 +1,13 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; parse( - ` -lastname,firstname,fullname -Ritchie -Lovelace,Ada,"Augusta Ada King, Countess of Lovelace" -`.trim(), + dedent` + lastname,firstname,fullname + Ritchie + Lovelace,Ada,"Augusta Ada King, Countess of Lovelace" + `, { relax_column_count: true, columns: true, diff --git a/packages/csv-parse/samples/option.relax_column_count.js b/packages/csv-parse/samples/option.relax_column_count.js index 4c93369ab..8584fc746 100644 --- a/packages/csv-parse/samples/option.relax_column_count.js +++ b/packages/csv-parse/samples/option.relax_column_count.js @@ -1,12 +1,13 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; parse( - ` -"a 1","a 2" -"b 1" -"c 1","c 2","c 3" -`.trim(), + dedent` + "a 1","a 2" + "b 1" + "c 1","c 2","c 3" + `, { relax_column_count: true, }, diff --git a/packages/csv-parse/samples/option.relax_column_count_less.js b/packages/csv-parse/samples/option.relax_column_count_less.js index 0f9cd8505..fc6a525e9 100644 --- a/packages/csv-parse/samples/option.relax_column_count_less.js +++ b/packages/csv-parse/samples/option.relax_column_count_less.js @@ -1,11 +1,12 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; parse( - ` -a,b,c -d,e -`.trim(), + dedent` + a,b,c + d,e + `, { relax_column_count_less: true, }, diff --git a/packages/csv-parse/samples/option.relax_column_count_more.js b/packages/csv-parse/samples/option.relax_column_count_more.js index b45cbf99c..ab48a0d52 100644 --- a/packages/csv-parse/samples/option.relax_column_count_more.js +++ b/packages/csv-parse/samples/option.relax_column_count_more.js @@ -1,11 +1,12 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; parse( - ` -a,b -c,d,e -`.trim(), + dedent` + a,b + c,d,e + `, { relax_column_count_more: true, }, diff --git a/packages/csv-parse/samples/option.relax_quotes.js b/packages/csv-parse/samples/option.relax_quotes.js index 0d7bc9469..0f281bd4d 100644 --- a/packages/csv-parse/samples/option.relax_quotes.js +++ b/packages/csv-parse/samples/option.relax_quotes.js @@ -2,9 +2,7 @@ import assert from "node:assert"; import { parse } from "csv-parse"; parse( - ` -a,some"text,c -`.trim(), + 'a,some"text,c', { relax_quotes: true, }, diff --git a/packages/csv-parse/samples/option.skip_empty_lines.js b/packages/csv-parse/samples/option.skip_empty_lines.js index fb2a6cd09..ff490050a 100644 --- a/packages/csv-parse/samples/option.skip_empty_lines.js +++ b/packages/csv-parse/samples/option.skip_empty_lines.js @@ -1,12 +1,13 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse/sync"; const records = parse( - ` -"a","b","c" + dedent` + "a","b","c" -"d","e","f" -`, + "d","e","f" + `, { skip_empty_lines: true, }, diff --git a/packages/csv-parse/samples/option.skip_empty_lines.trim.js b/packages/csv-parse/samples/option.skip_empty_lines.trim.js index 87b6b0191..e67b52fc1 100644 --- a/packages/csv-parse/samples/option.skip_empty_lines.trim.js +++ b/packages/csv-parse/samples/option.skip_empty_lines.trim.js @@ -1,17 +1,15 @@ import assert from "node:assert"; import { parse } from "csv-parse/sync"; -const records = parse( - ` +const data = ` "a","b","c" \t "d","e","f" -`, - { - skip_empty_lines: true, - trim: true, - }, -); +`; +const records = parse(data, { + skip_empty_lines: true, + trim: true, +}); assert.deepStrictEqual(records, [ ["a", "b", "c"], diff --git a/packages/csv-parse/samples/option.skip_records_with_empty_values.js b/packages/csv-parse/samples/option.skip_records_with_empty_values.js index 6028dbfb4..8468e76fb 100644 --- a/packages/csv-parse/samples/option.skip_records_with_empty_values.js +++ b/packages/csv-parse/samples/option.skip_records_with_empty_values.js @@ -1,12 +1,13 @@ import assert from "node:assert"; import { parse } from "csv-parse"; -parse( - ` +const data = ` a,b,c , ,\t d,e,f -`.trim(), +`; +parse( + data, { skip_records_with_empty_values: true, }, diff --git a/packages/csv-parse/samples/option.skip_records_with_error.js b/packages/csv-parse/samples/option.skip_records_with_error.js index 7d2d7a8cc..d2175ea6e 100644 --- a/packages/csv-parse/samples/option.skip_records_with_error.js +++ b/packages/csv-parse/samples/option.skip_records_with_error.js @@ -1,4 +1,5 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; const parser = parse( @@ -17,11 +18,11 @@ parser.on("skip", function (err) { assert(/^Invalid Closing Quote/.test(err.message)); }); parser.write( - ` -"a","b","c" -"d","e","f" -"invalid"," " ","record" -"h","i","j" -`.trim(), + dedent` + "a","b","c" + "d","e","f" + "invalid"," " ","record" + "h","i","j" + `, ); parser.end(); diff --git a/packages/csv-parse/samples/option.to.js b/packages/csv-parse/samples/option.to.js index a2032518a..d1f99dfee 100644 --- a/packages/csv-parse/samples/option.to.js +++ b/packages/csv-parse/samples/option.to.js @@ -1,13 +1,14 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse"; parse( - ` -a,b -1,2 -3,4 -5,6 -`.trim(), + dedent` + a,b + 1,2 + 3,4 + 5,6 + `, { columns: true, to: 2, diff --git a/packages/csv-parse/samples/option.to_line.js b/packages/csv-parse/samples/option.to_line.js index 9ea949713..ae6b19514 100644 --- a/packages/csv-parse/samples/option.to_line.js +++ b/packages/csv-parse/samples/option.to_line.js @@ -1,12 +1,13 @@ import assert from "node:assert"; +import dedent from "dedent"; import { parse } from "csv-parse/sync"; const records = parse( - ` -a,1 -b,1 -x,x -`.trim(), + dedent` + a,1 + b,1 + x,x + `, { to_line: 2, }, diff --git a/packages/csv-parse/test/ResizableBuffer.coffee b/packages/csv-parse/test/ResizableBuffer.coffee deleted file mode 100644 index a6b57eb30..000000000 --- a/packages/csv-parse/test/ResizableBuffer.coffee +++ /dev/null @@ -1,117 +0,0 @@ - -import ResizeableBuffer from '../lib/utils/ResizeableBuffer.js' - -describe 'ResizeableBuffer', -> - - describe 'append', -> - - it 'chars inside boundary', -> - rb = new ResizeableBuffer(5) - buf = Buffer.from 'abc' - for i in [0...buf.length] - rb.append(buf[i]) - rb.length.should.eql 3 - rb.clone().toString().should.eql('abc') - - it 'chars larger than size', -> - rb = new ResizeableBuffer(5) - buf = Buffer.from 'abc,def;hij,klm;' - for i in [0...buf.length] - rb.append(buf[i]) - rb.length.should.eql 16 - rb.clone().toString().should.eql 'abc,def;hij,klm;' - - describe 'prepend', -> - - it 'chars inside boundary', -> - rb = new ResizeableBuffer(5) - buf = Buffer.from 'abc' - for i in [1...buf.length] - rb.append(buf[i]) - rb.prepend(buf[0]) - rb.length.should.eql 3 - rb.clone().toString().should.eql 'abc' - - it 'buffer inside boundary', -> - rb = new ResizeableBuffer(5) - buf = Buffer.from 'abc' - for i in [1...buf.length] - rb.append(buf[i]) - rb.prepend(Buffer.from([buf[0]])) - rb.length.should.eql 3 - rb.clone().toString().should.eql 'abc' - - it 'chars same size as size', -> - rb = new ResizeableBuffer(3) - buf = Buffer.from 'abcd' - for i in [1...buf.length] - rb.append(buf[i]) - rb.prepend(buf[0]) - rb.length.should.eql 4 - rb.clone().toString().should.eql 'abcd' - - it 'chars same size as size', -> - rb = new ResizeableBuffer(3) - buf = Buffer.from 'abcd' - for i in [1...buf.length] - rb.append(buf[i]) - rb.prepend(Buffer.from([buf[0]])) - rb.length.should.eql 4 - rb.clone().toString().should.eql 'abcd' - - it 'chars larger than size', -> - rb = new ResizeableBuffer(5) - buf = Buffer.from 'abc,def;hij,klm;' - for i in [1...buf.length] - rb.append(buf[i]) - rb.prepend(buf[0]) - rb.length.should.eql 16 - rb.clone().toString().should.eql 'abc,def;hij,klm;' - - it 'buffer larger than size', -> - rb = new ResizeableBuffer(5) - buf = Buffer.from 'abc,def;hij,klm;' - for i in [1...buf.length] - rb.append(buf[i]) - rb.prepend(Buffer.from([buf[0]])) - rb.length.should.eql 16 - rb.clone().toString().should.eql 'abc,def;hij,klm;' - - it 'buffer larger than size', -> - rb = new ResizeableBuffer(6) - buf = Buffer.from 'abc,def;hij,klm;' - for chr in 'def' - rb.append(chr.charCodeAt()) - rb.prepend(Buffer.from('abc')) - rb.length.should.eql 6 - rb.toString('utf8').should.eql 'abcdef' - - it 'throw invalid state if size equal buffer size', -> - try - rb = new ResizeableBuffer(3) - buf = Buffer.from 'abc,def;hij,klm;' - for chr in 'def' - rb.append(chr.charCodeAt()) - rb.prepend(Buffer.from('abc')) - catch err - err.message.should.eql 'INVALID_BUFFER_STATE' - - describe 'reset', -> - - it 'reset', -> - rb = new ResizeableBuffer(5) - buf = Buffer.from 'abc,def;' - for i in [0...buf.length] - rb.append(buf[i]) - rb.reset() - buf = Buffer.from 'hij,klm;' - for i in [0...buf.length] - rb.append(buf[i]) - rb.clone().toString().should.eql 'hij,klm;' - - describe 'toJSON', -> - rb = new ResizeableBuffer(5) - buf = Buffer.from 'abc,def;' - for i in [0...buf.length] - rb.append(buf[i]) - rb.toJSON().should.eql 'abc,def;' diff --git a/packages/csv-parse/test/ResizableBuffer.js b/packages/csv-parse/test/ResizableBuffer.js new file mode 100644 index 000000000..d2f9cdc3b --- /dev/null +++ b/packages/csv-parse/test/ResizableBuffer.js @@ -0,0 +1,141 @@ +import "should"; +import ResizeableBuffer from "../lib/utils/ResizeableBuffer.js"; + +describe("ResizeableBuffer", function () { + describe("append", function () { + it("chars inside boundary", function () { + const rb = new ResizeableBuffer(5); + const buf = Buffer.from("abc"); + for (let i = 0; i < buf.length; i++) { + rb.append(buf[i]); + } + rb.length.should.eql(3); + rb.clone().toString().should.eql("abc"); + }); + + it("chars larger than size", function () { + const rb = new ResizeableBuffer(5); + const buf = Buffer.from("abc,def;hij,klm;"); + for (let i = 0; i < buf.length; i++) { + rb.append(buf[i]); + } + rb.length.should.eql(16); + rb.clone().toString().should.eql("abc,def;hij,klm;"); + }); + }); + + describe("prepend", function () { + it("chars inside boundary", function () { + const rb = new ResizeableBuffer(5); + const buf = Buffer.from("abc"); + for (let i = 1; i < buf.length; i++) { + rb.append(buf[i]); + } + rb.prepend(buf[0]); + rb.length.should.eql(3); + rb.clone().toString().should.eql("abc"); + }); + + it("buffer inside boundary", function () { + const rb = new ResizeableBuffer(5); + const buf = Buffer.from("abc"); + for (let i = 1; i < buf.length; i++) { + rb.append(buf[i]); + } + rb.prepend(Buffer.from([buf[0]])); + rb.length.should.eql(3); + rb.clone().toString().should.eql("abc"); + }); + + it("chars same size as size, prepend byte", function () { + const rb = new ResizeableBuffer(3); + const buf = Buffer.from("abcd"); + for (let i = 1; i < buf.length; i++) { + rb.append(buf[i]); + } + rb.prepend(buf[0]); + rb.length.should.eql(4); + rb.clone().toString().should.eql("abcd"); + }); + + it("chars same size as size, prepend buffer", function () { + const rb = new ResizeableBuffer(3); + const buf = Buffer.from("abcd"); + for (let i = 1; i < buf.length; i++) { + rb.append(buf[i]); + } + rb.prepend(Buffer.from([buf[0]])); + rb.length.should.eql(4); + rb.clone().toString().should.eql("abcd"); + }); + + it("chars larger than size", function () { + const rb = new ResizeableBuffer(5); + const buf = Buffer.from("abc,def;hij,klm;"); + for (let i = 1; i < buf.length; i++) { + rb.append(buf[i]); + } + rb.prepend(buf[0]); + rb.length.should.eql(16); + rb.clone().toString().should.eql("abc,def;hij,klm;"); + }); + + it("buffer larger than size", function () { + const rb = new ResizeableBuffer(5); + const buf = Buffer.from("abc,def;hij,klm;"); + for (let i = 1; i < buf.length; i++) { + rb.append(buf[i]); + } + rb.prepend(Buffer.from([buf[0]])); + rb.length.should.eql(16); + rb.clone().toString().should.eql("abc,def;hij,klm;"); + }); + + it("buffer equlas size", function () { + const rb = new ResizeableBuffer(6); + for (const chr of "def") { + rb.append(chr.charCodeAt()); + } + rb.prepend(Buffer.from("abc")); + rb.length.should.eql(6); + rb.toString("utf8").should.eql("abcdef"); + }); + + it("throw invalid state if size equal buffer size", function () { + try { + const rb = new ResizeableBuffer(3); + for (const chr of "def") { + rb.append(chr.charCodeAt()); + } + rb.prepend(Buffer.from("abc")); + } catch (err) { + err.message.should.eql("INVALID_BUFFER_STATE"); + } + }); + }); + + describe("reset", function () { + it("reset", function () { + const rb = new ResizeableBuffer(5); + let buf = Buffer.from("abc,def;"); + for (let i = 0; i < buf.length; i++) { + rb.append(buf[i]); + } + rb.reset(); + buf = Buffer.from("hij,klm;"); + for (let i = 0; i < buf.length; i++) { + rb.append(buf[i]); + } + rb.clone().toString().should.eql("hij,klm;"); + }); + + it("toJSON", function () { + const rb = new ResizeableBuffer(5); + const buf = Buffer.from("abc,def;"); + for (let i = 0; i < buf.length; i++) { + rb.append(buf[i]); + } + rb.toJSON().should.eql("abc,def;"); + }); + }); +}); diff --git a/packages/csv-parse/test/api.arguments.coffee b/packages/csv-parse/test/api.arguments.coffee deleted file mode 100644 index dbc82eace..000000000 --- a/packages/csv-parse/test/api.arguments.coffee +++ /dev/null @@ -1,133 +0,0 @@ - -import { generate } from 'csv-generate' -import { parse, Parser } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'API arguments', -> - - it 'exports Parser class', -> - Parser.should.be.a.Function - - describe '0 arg', -> - - it 'no arguments', (next) -> - records = [] - parser = parse() - parser.on 'readable', -> - while d = this.read() - records.push d - parser.on 'err', (err) -> - next err - parser.on 'end', -> - records.should.eql [ [ 'field_1', 'field_2' ], [ 'value 1', 'value 2' ] ] - next() - parser.write 'field_1,field_2\nvalue 1,value 2' - parser.end() - - describe '1 arg', -> - - it 'callback:function; pipe data and get result in callback', (next) -> - generate(length: 2, seed: 1, columns: 2, fixed_size: true) - .pipe parse (err, records) -> - records.should.eql [ [ 'OMH', 'ONKCHhJmjadoA' ], [ 'D', 'GeACHiN' ] ] - next err - - it 'options:object; write data and read stream', (next) -> - records = [] - parser = parse columns: true - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'err', (err) -> - next err - parser.on 'end', -> - records.should.eql [field_1: 'value 1', field_2: 'value 2'] - next() - parser.write 'field_1,field_2\nvalue 1,value 2' - parser.end() - - describe '2 args', -> - - it 'data:string, options:object; read stream', (next) -> - records = [] - parser = parse 'field_1,field_2\nvalue 1,value 2', columns: true - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'err', (err) -> - next err - parser.on 'end', -> - records.should.eql [field_1: 'value 1', field_2: 'value 2'] - next() - - it 'options:object, callback:function; write data and get result in callback', (next) -> - parser = parse columns: true, (err, records) -> - records.should.eql [field_1: 'value 1', field_2: 'value 2'] - next err - parser.write 'field_1,field_2\nvalue 1,value 2' - parser.end() - - it 'data:string, callback:function', (next) -> - parse 'value a,value b\nvalue 1,value 2', (err, records) -> - records.should.eql [ [ 'value a', 'value b' ], [ 'value 1', 'value 2' ] ] - next err - - it 'data:buffer, callback:function', (next) -> - parse Buffer.from('value a,value b\nvalue 1,value 2'), (err, records) -> - records.should.eql [ [ 'value a', 'value b' ], [ 'value 1', 'value 2' ] ] - next err - - it 'data:undefined, options:object', -> - (-> - parse undefined, {} - ).should.throw - message: 'Invalid argument: got undefined at index 0' - code: 'CSV_INVALID_ARGUMENT' - - it 'data:undefined, callback:function', -> - (-> - parse undefined, (->) - ).should.throw - message: 'Invalid argument: got undefined at index 0' - code: 'CSV_INVALID_ARGUMENT' - - it 'data:array, callback:function', -> - (-> - parse ['value a,value b', 'value 1,value 2'], (->) - ).should.throw - message: 'Invalid argument: got ["value a,value b","value 1,value 2"] at index 0' - code: 'CSV_INVALID_ARGUMENT' - - it 'options:object, options:object', -> - (-> - parse {}, {} - ).should.throw - message: 'Invalid argument: got {} at index 1' - code: 'CSV_INVALID_ARGUMENT' - - describe '3 args', -> - - it 'data:string, options:object, callback:function', (next) -> - parse 'field_1,field_2\nvalue 1,value 2', columns: true, (err, records) -> - records.should.eql [field_1: 'value 1', field_2: 'value 2'] - next err - - it 'data:buffer, options:object, callback:function', (next) -> - parse Buffer.from('field_1,field_2\nvalue 1,value 2'), columns: true, (err, records) -> - records.should.eql [field_1: 'value 1', field_2: 'value 2'] - next err - - it 'data:undefined, options:object, callback:function', -> - (-> - parse undefined, columns: true, (->) - ).should.throw - message: 'Invalid argument: got undefined at index 0' - code: 'CSV_INVALID_ARGUMENT' - - it 'data:string, options:object, callback:undefined', -> - (-> - parse 'field_1,field_2\nvalue 1,value 2', columns: true, undefined - ).should.throw - message: 'Invalid argument: got undefined at index 2' - code: 'CSV_INVALID_ARGUMENT' - diff --git a/packages/csv-parse/test/api.arguments.js b/packages/csv-parse/test/api.arguments.js new file mode 100644 index 000000000..ea81a563e --- /dev/null +++ b/packages/csv-parse/test/api.arguments.js @@ -0,0 +1,54 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("API arguments", function () { + describe("2 args", function () { + it("data:undefined, options:object", function () { + (() => { + parse(undefined, {}); + }).should.throw({ + message: "Invalid argument: got undefined at index 0", + code: "CSV_INVALID_ARGUMENT", + }); + }); + + it("data:undefined, callback:function", function () { + (() => { + parse(undefined, () => {}); + }).should.throw({ + message: "Invalid argument: got undefined at index 0", + code: "CSV_INVALID_ARGUMENT", + }); + }); + + it("data:array, callback:function", function () { + (() => { + parse(["value a,value b", "value 1,value 2"], () => {}); + }).should.throw({ + message: + 'Invalid argument: got ["value a,value b","value 1,value 2"] at index 0', + code: "CSV_INVALID_ARGUMENT", + }); + }); + + it("options:object, options:object", function () { + (() => { + parse({}, {}); + }).should.throw({ + message: "Invalid argument: got {} at index 1", + code: "CSV_INVALID_ARGUMENT", + }); + }); + }); + + describe("3 args", function () { + it("data:undefined, options:object, callback:function", function () { + (() => { + parse(undefined, { columns: true }, () => {}); + }).should.throw({ + message: "Invalid argument: got undefined at index 0", + code: "CSV_INVALID_ARGUMENT", + }); + }); + }); +}); diff --git a/packages/csv-parse/test/api.arguments.ts b/packages/csv-parse/test/api.arguments.ts new file mode 100644 index 000000000..c79194e6a --- /dev/null +++ b/packages/csv-parse/test/api.arguments.ts @@ -0,0 +1,152 @@ +import "should"; +import { generate } from "csv-generate"; +import { parse, Parser } from "../lib/index.js"; + +describe("API arguments", function () { + it("exports Parser class", function () { + Parser.should.be.a.Function; + }); + + describe("0 arg", function () { + it("no arguments", function (next) { + const records: string[] = []; + const parser = parse(); + parser.on("readable", function () { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("err", (err) => { + next(err); + }); + parser.on("end", () => { + records.should.eql([ + ["field_1", "field_2"], + ["value 1", "value 2"], + ]); + next(); + }); + parser.write("field_1,field_2\nvalue 1,value 2"); + parser.end(); + }); + }); + + describe("1 arg", function () { + it("callback:function; pipe data and get result in callback", function (next) { + generate({ length: 2, seed: 1, columns: 2, fixed_size: true }).pipe( + parse((err, records) => { + records.should.eql([ + ["OMH", "ONKCHhJmjadoA"], + ["D", "GeACHiN"], + ]); + next(err); + }), + ); + }); + + it("options:object; write data and read stream", function (next) { + const records: string[] = []; + const parser = parse({ columns: true }); + parser.on("readable", function () { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("err", (err) => { + next(err); + }); + parser.on("end", () => { + records.should.eql([{ field_1: "value 1", field_2: "value 2" }]); + next(); + }); + parser.write("field_1,field_2\nvalue 1,value 2"); + parser.end(); + }); + }); + + describe("2 args", function () { + it("data:string, options:object; read stream", function (next) { + const records: string[] = []; + const parser = parse("field_1,field_2\nvalue 1,value 2", { + columns: true, + }); + parser.on("readable", function () { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("err", (err) => { + next(err); + }); + parser.on("end", () => { + records.should.eql([{ field_1: "value 1", field_2: "value 2" }]); + next(); + }); + }); + + it("options:object, callback:function; write data and get result in callback", function (next) { + const parser = parse({ columns: true }, (err, records) => { + records.should.eql([{ field_1: "value 1", field_2: "value 2" }]); + next(err); + }); + parser.write("field_1,field_2\nvalue 1,value 2"); + parser.end(); + }); + + it("data:string, callback:function", function (next) { + parse("value a,value b\nvalue 1,value 2", (err, records) => { + records.should.eql([ + ["value a", "value b"], + ["value 1", "value 2"], + ]); + next(err); + }); + }); + + it("data:buffer, callback:function", function (next) { + parse(Buffer.from("value a,value b\nvalue 1,value 2"), (err, records) => { + records.should.eql([ + ["value a", "value b"], + ["value 1", "value 2"], + ]); + next(err); + }); + }); + }); + + describe("3 args", function () { + it("data:string, options:object, callback:function", function (next) { + parse( + "field_1,field_2\nvalue 1,value 2", + { columns: true }, + (err, records) => { + records.should.eql([{ field_1: "value 1", field_2: "value 2" }]); + next(err); + }, + ); + }); + + it("data:buffer, options:object, callback:function", function (next) { + parse( + Buffer.from("field_1,field_2\nvalue 1,value 2"), + { columns: true }, + (err, records) => { + records.should.eql([{ field_1: "value 1", field_2: "value 2" }]); + next(err); + }, + ); + }); + + it("data:string, options:object, callback:undefined", function () { + (() => { + parse("field_1,field_2\nvalue 1,value 2", { columns: true }, undefined); + }).should.throw({ + message: "Invalid argument: got undefined at index 2", + code: "CSV_INVALID_ARGUMENT", + }); + }); + }); +}); diff --git a/packages/csv-parse/test/api.assert_error.coffee b/packages/csv-parse/test/api.assert_error.coffee deleted file mode 100644 index 55bd3d732..000000000 --- a/packages/csv-parse/test/api.assert_error.coffee +++ /dev/null @@ -1,112 +0,0 @@ - -import { CsvError } from '../lib/index.js' -import ResizeableBuffer from '../lib/utils/ResizeableBuffer.js' - -export assert_error = (err, assert = {}, exhaustive = false) -> - if Array.isArray err - assert_error e, assert[i] for e, i in err - return - if exhaustive then for key, value of err - assert.should.have.keys(key) - err.should.be.an.Error() - for key, expect of assert - value = err[key] - if typeof expect is 'string' - # eg, convert a buffer - value = value.toString() if value?.toString? - should(value).deepEqual expect - else if expect instanceof RegExp - should(value).match expect - else if expect is undefined - should(value).be.undefined() - else if expect is null - should(value).be.null() - else - should(value).deepEqual expect - -describe 'API assert_error', -> - - it 'work on array', -> - err = new CsvError 'A_MESSAGE', 'A message' - assert_error [err, err], [ - code: 'A_MESSAGE' - message: 'A message' - , - code: 'A_MESSAGE' - message: 'A message' - ] - - it 'exhaustive detect a property not in assert', -> - err = new CsvError 'A_MESSAGE', 'A message', {}, a_key: 'a value' - ( -> - assert_error err, - code: 'A_MESSAGE' - message: 'A message' - , true - ).should.throw /expected Object .* to have key a_key/ - - it 'detect a property not in error', -> - err = new CsvError 'A_MESSAGE', 'A message' - ( -> - assert_error err, - code: 'A_MESSAGE' - message: 'A message' - a_key: 'a value' - ).should.throw "expected undefined to equal 'a value'" - - it 'validate a string value', -> - err = new CsvError 'A_MESSAGE', 'A message' - assert_error err, - code: 'A_MESSAGE' - message: 'A message' - ( -> - assert_error err, - code: 'A_MESSAGE' - message: 'Another mesage' - ).should.throw "expected 'A message' to equal 'Another mesage'" - - it 'validate a null value', -> - err = new CsvError 'A_MESSAGE', 'A message' - ( -> - assert_error err, - code: 'A_MESSAGE' - message: null - ).should.throw "expected 'A message' to be null" - - it 'validate a undefined value', -> - err = new CsvError 'A_MESSAGE', 'A message' - ( -> - assert_error err, - code: 'A_MESSAGE' - message: undefined - ).should.throw "expected 'A message' to be undefined" - - it 'validate a boolean true value', -> - err = new CsvError 'A_MESSAGE', 'A message', {}, a_boolean: true - assert_error err, - a_boolean: true - ( -> - assert_error err, - a_boolean: false - ).should.throw "expected true to equal false" - - it 'validate a boolean true value', -> - err = new CsvError 'A_MESSAGE', 'A message', {}, a_boolean: false - assert_error err, - a_boolean: false - ( -> - assert_error err, - a_boolean: true - ).should.throw "expected false to equal true" - - it 'validate a regexp value', -> - err = new CsvError 'A_MESSAGE', 'A message' - assert_error err, - code: 'A_MESSAGE' - message: /^A.*/ - ( -> - assert_error err, - code: 'A_MESSAGE' - message: /^Another.*/ - ).should.throw "expected 'A message' to match /^Another.*/" - diff --git a/packages/csv-parse/test/api.assert_error.ts b/packages/csv-parse/test/api.assert_error.ts new file mode 100644 index 000000000..28e0517c5 --- /dev/null +++ b/packages/csv-parse/test/api.assert_error.ts @@ -0,0 +1,167 @@ +import should from "should"; +import { CsvError, normalize_options } from "../lib/index.js"; + +/* eslint mocha/no-exports: "off" */ +export const assert_error = function ( + err: CsvError | CsvError[], + assert: + | ({ code?: string; message?: string | RegExp | undefined | null } & T) + | ({ code?: string; message?: string | RegExp | undefined | null } & T)[], + exhaustive = false, +) { + if (Array.isArray(err)) { + err.forEach((e, i) => + assert_error(e, Array.isArray(assert) ? assert[i] : assert), + ); + return; + } + if (exhaustive) { + for (const key in err) { + assert.should.have.keys(key); + } + } + err.should.be.an.Error(); + for (const [key, expect] of Object.entries(assert)) { + let value = err[key]; + if (typeof expect === "string") { + // eg, convert a buffer + if (value?.toString) { + value = value.toString(); + } + should(value).deepEqual(expect); + } else if (expect instanceof RegExp) { + should(value).match(expect); + } else if (expect === undefined) { + should(value).be.undefined(); + } else if (expect === null) { + should(value).be.null(); + } else { + should(value).deepEqual(expect); + } + } +}; + +describe("API assert_error", function () { + it("work on array", function () { + const err = new CsvError("CSV_UNKNOWN_ERROR", "A message"); + assert_error( + [err, err], + [ + { + code: "CSV_UNKNOWN_ERROR", + message: "A message", + }, + { + code: "CSV_UNKNOWN_ERROR", + message: "A message", + }, + ], + ); + }); + + it("exhaustive detect a property not in assert", function () { + const options = normalize_options({}); + const err = new CsvError("CSV_UNKNOWN_ERROR", "A message", options, { + a_key: "a value", + }); + (() => { + assert_error( + err, + { + code: "CSV_UNKNOWN_ERROR", + message: "A message", + }, + true, + ); + }).should.throw(/expected Object .* to have key a_key/); + }); + + it("detect a property not in error", function () { + const err = new CsvError("CSV_UNKNOWN_ERROR", "A message"); + (() => { + assert_error(err, { + code: "CSV_UNKNOWN_ERROR", + message: "A message", + a_key: "a value", + }); + }).should.throw("expected undefined to equal 'a value'"); + }); + + it("validate a string value", function () { + const err = new CsvError("CSV_UNKNOWN_ERROR", "A message"); + assert_error(err, { + code: "CSV_UNKNOWN_ERROR", + message: "A message", + }); + (() => { + assert_error(err, { + code: "CSV_UNKNOWN_ERROR", + message: "Another mesage", + }); + }).should.throw("expected 'A message' to equal 'Another mesage'"); + }); + + it("validate a null value", function () { + const err = new CsvError("CSV_UNKNOWN_ERROR", "A message"); + (() => { + assert_error(err, { + code: "CSV_UNKNOWN_ERROR", + message: null, + }); + }).should.throw("expected 'A message' to be null"); + }); + + it("validate a undefined value", function () { + const err = new CsvError("CSV_UNKNOWN_ERROR", "A message"); + (() => { + assert_error(err, { + code: "CSV_UNKNOWN_ERROR", + message: undefined, + }); + }).should.throw("expected 'A message' to be undefined"); + }); + + it("validate a boolean true value", function () { + const options = normalize_options({}); + const err = new CsvError("CSV_UNKNOWN_ERROR", "A message", options, { + a_boolean: true, + }); + assert_error<{ a_boolean: boolean }>(err, { + a_boolean: true, + }); + (() => { + assert_error<{ a_boolean: boolean }>(err, { + a_boolean: false, + }); + }).should.throw("expected true to equal false"); + }); + + it("validate a boolean false value", function () { + const options = normalize_options({}); + const err = new CsvError("CSV_UNKNOWN_ERROR", "A message", options, { + a_boolean: false, + }); + assert_error(err, { + a_boolean: false, + }); + (() => { + assert_error(err, { + a_boolean: true, + }); + }).should.throw("expected false to equal true"); + }); + + it("validate a regexp value", function () { + const err = new CsvError("CSV_UNKNOWN_ERROR", "A message"); + assert_error(err, { + code: "CSV_UNKNOWN_ERROR", + message: /^A.*/, + }); + (() => { + assert_error(err, { + code: "CSV_UNKNOWN_ERROR", + message: /^Another.*/, + }); + }).should.throw("expected 'A message' to match /^Another.*/"); + }); +}); diff --git a/packages/csv-parse/test/api.error.coffee b/packages/csv-parse/test/api.error.coffee deleted file mode 100644 index 81e1372a2..000000000 --- a/packages/csv-parse/test/api.error.coffee +++ /dev/null @@ -1,33 +0,0 @@ - -import { parse, CsvError } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'API error', -> - - it 'set code', -> - err = new CsvError 'MY_CODE', ['a', 'b', 'c'] - err.code.should.eql 'MY_CODE' - - it 'convert array message to string', -> - err = new CsvError 'MY_CODE', ['a', 'b', 'c'] - err.message.should.eql 'a b c' - - it 'set additional context information', -> - err = new CsvError 'MY_CODE', 'msg', {}, a: 1, b: 2 - err.a.should.eql 1 - err.b.should.eql 2 - - it 'errors are enriched by context', -> - parse 'a"b', (err) -> - assert_error err, - message: /Invalid Opening Quote/ - code: 'INVALID_OPENING_QUOTE' - column: 0 - empty_lines: 0 - header: false - index: 0 - invalid_field_length: 0 - quoting: false - lines: 1 - records: 0 - field: 'a' diff --git a/packages/csv-parse/test/api.error.ts b/packages/csv-parse/test/api.error.ts new file mode 100644 index 000000000..1b0b50a01 --- /dev/null +++ b/packages/csv-parse/test/api.error.ts @@ -0,0 +1,44 @@ +import "should"; +import { parse, CsvError, normalize_options } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; + +describe("API error", function () { + it("set code", function () { + const err = new CsvError("CSV_UNKNOWN_ERROR", ["a", "b", "c"]); + err.code.should.eql("CSV_UNKNOWN_ERROR"); + }); + + it("convert array message to string", function () { + const err = new CsvError("CSV_UNKNOWN_ERROR", ["a", "b", "c"]); + err.message.should.eql("a b c"); + }); + + it("set additional context information", function () { + const options = normalize_options({}); + const err = new CsvError("CSV_UNKNOWN_ERROR", "msg", options, { + a: 1, + b: 2, + }); + err.a.should.eql(1); + err.b.should.eql(2); + }); + + it("errors are enriched by context", function () { + parse('a"b', (err) => { + if (!err) throw Error("Invalid assertion"); + assert_error(err, { + message: /Invalid Opening Quote/, + code: "INVALID_OPENING_QUOTE", + column: 0, + empty_lines: 0, + header: false, + index: 0, + invalid_field_length: 0, + quoting: false, + lines: 1, + records: 0, + field: "a", + }); + }); + }); +}); diff --git a/packages/csv-parse/test/api.info.coffee b/packages/csv-parse/test/api.info.coffee deleted file mode 100644 index 45db2de12..000000000 --- a/packages/csv-parse/test/api.info.coffee +++ /dev/null @@ -1,70 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'API info', -> - - it 'is exported in the callback on error', (next) -> - parse ''' - 1,2,3 - a,b, - ''', (err, records, info) -> - info.should.eql - bytes: 10 - columns: false - comment_lines: 0 - empty_lines: 0 - invalid_field_length: 0 - lines: 2 - records: 2 - next() - - it 'is exported in the callback on success', (next) -> - parse ''' - 1,2,3 - a,b,c - ''', (err, records, info) -> - info.should.eql - bytes: 11 - columns: false - comment_lines: 0 - empty_lines: 0 - invalid_field_length: 0 - lines: 2 - records: 2 - next err - - it 'discovered columns are included', (next) -> - parse ''' - a,b,c - 1,2,3 - ''', columns: true, (err, records, info) -> - info.should.eql - bytes: 11 - comment_lines: 0 - columns: [ - { name: 'a' } - { name: 'b' } - { name: 'c' } - ] - empty_lines: 0 - invalid_field_length: 0 - lines: 2 - records: 1 - next err - - it 'with multiline records', (next) -> - parse ''' - a,b,c - d,"e - ",f - g,h,i - ''', (err, records, info) -> - info.should.eql - bytes: 20 - columns: false - comment_lines: 0 - empty_lines: 0 - invalid_field_length: 0 - lines: 4 - records: 3 - next err diff --git a/packages/csv-parse/test/api.info.ts b/packages/csv-parse/test/api.info.ts new file mode 100644 index 000000000..90f81e67e --- /dev/null +++ b/packages/csv-parse/test/api.info.ts @@ -0,0 +1,68 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("API info", function () { + it("is exported in the callback on error", function (next) { + parse("1,2,3\na,b,", (err, records, info) => { + if (!info) return next(Error("Invalid assessment")); + info.should.eql({ + bytes: 10, + columns: false, + comment_lines: 0, + empty_lines: 0, + invalid_field_length: 0, + lines: 2, + records: 2, + }); + next(); + }); + }); + + it("is exported in the callback on success", function (next) { + parse("1,2,3\na,b,c", (err, records, info) => { + if (!info) return next(Error("Invalid assessment")); + info.should.eql({ + bytes: 11, + columns: false, + comment_lines: 0, + empty_lines: 0, + invalid_field_length: 0, + lines: 2, + records: 2, + }); + next(err); + }); + }); + + it("discovered columns are included", function (next) { + parse("a,b,c\n1,2,3", { columns: true }, (err, records, info) => { + if (!info) return next(Error("Invalid assessment")); + info.should.eql({ + bytes: 11, + comment_lines: 0, + columns: [{ name: "a" }, { name: "b" }, { name: "c" }], + empty_lines: 0, + invalid_field_length: 0, + lines: 2, + records: 1, + }); + next(err); + }); + }); + + it("with multiline records", function (next) { + parse('a,b,c\nd,"e\n",f\ng,h,i', (err, records, info) => { + if (!info) return next(Error("Invalid assessment")); + info.should.eql({ + bytes: 20, + columns: false, + comment_lines: 0, + empty_lines: 0, + invalid_field_length: 0, + lines: 4, + records: 3, + }); + next(err); + }); + }); +}); diff --git a/packages/csv-parse/test/api.stream.destroy.coffee b/packages/csv-parse/test/api.stream.destroy.coffee deleted file mode 100644 index 2ac2310b9..000000000 --- a/packages/csv-parse/test/api.stream.destroy.coffee +++ /dev/null @@ -1,59 +0,0 @@ - -import fs from 'fs' -import os from 'os' -import { generate } from 'csv-generate' -import { parse } from '../lib/index.js' - -describe 'API destroy', -> - - it 'inside readable with input string', (next) -> - parser = parse() - parser.on 'readable', -> - while this.read() - parser.destroy(Error 'Catch me') - parser.write """ - "ABC","45" - "DEF","23" - """ - parser.on 'error', (err) -> - err.message.should.eql 'Catch me' - parser._readableState.destroyed.should.be.true() - next() - parser.on 'end', -> - next Error 'End event shouldnt be called' - # Note, removing =nextTick trigger both the error and end events - process.nextTick -> - parser.end() - - it 'inside readable with fs input stream', (next) -> - fs.writeFile "#{os.tmpdir()}/data.csv", "a,b,c\n1,2,3", (err) -> - return next err if err - parser = parse() - parser.on 'readable', -> - while record = this.read() - parser.destroy(Error 'Catch me') - parser.on 'error', (err) -> - err.message.should.eql 'Catch me' - parser._readableState.destroyed.should.be.true() - next() - parser.on 'end', -> - next Error 'End event shouldnt be called' - fs - .createReadStream "#{os.tmpdir()}/data.csv" - .pipe parser - - it 'inside readable with generator input stream', (next) -> - # csv-generate emit data synchronously, it cant detect error on time - parser = parse() - parser.on 'readable', -> - while record = this.read() - parser.destroy(Error 'Catch me') - parser.on 'error', (err) -> - err.message.should.eql 'Catch me' - parser._readableState.destroyed.should.be.true() - version = parseInt /^v(\d+)/.exec(process.version)[1], 10 - next() if version >= 14 - parser.on 'end', -> - next() - generate length: 2, seed: 1, columns: 2, fixed_size: true - .pipe parser diff --git a/packages/csv-parse/test/api.stream.destroy.ts b/packages/csv-parse/test/api.stream.destroy.ts new file mode 100644 index 000000000..5b01fffe3 --- /dev/null +++ b/packages/csv-parse/test/api.stream.destroy.ts @@ -0,0 +1,76 @@ +import fs from "fs"; +import os from "os"; +import "should"; +import { generate } from "csv-generate"; +import { parse, Parser } from "../lib/index.js"; + +interface ParserPrivate { + _readableState: { + destroyed: boolean; + }; +} + +describe("API destroy", function () { + it("inside readable with input string", function (next) { + const parser = parse() as Parser & ParserPrivate; + parser.on("readable", function () { + while (parser.read()) { + parser.destroy(Error("Catch me")); + } + }); + parser.write('"ABC","45"\n"DEF","23"'); + parser.on("error", (err) => { + err.message.should.eql("Catch me"); + parser._readableState.destroyed.should.be.true(); + next(); + }); + parser.on("end", () => { + next(Error("End event shouldnt be called")); + }); + // Note, removing =nextTick trigger both the error and end events + process.nextTick(() => { + parser.end(); + }); + }); + + it("inside readable with fs input stream", function (next) { + fs.writeFile(`${os.tmpdir()}/data.csv`, "a,b,c\n1,2,3", (err) => { + if (err) return next(err); + const parser = parse() as Parser & ParserPrivate; + parser.on("readable", function () { + while (parser.read()) { + parser.destroy(Error("Catch me")); + } + }); + parser.on("error", (err) => { + err.message.should.eql("Catch me"); + parser._readableState.destroyed.should.be.true(); + next(); + }); + parser.on("end", () => { + next(Error("End event shouldnt be called")); + }); + fs.createReadStream(`${os.tmpdir()}/data.csv`).pipe(parser); + }); + }); + + it("inside readable with generator input stream", function (next) { + // csv-generate emit data synchronously, it cant detect error on time + const parser = parse() as Parser & ParserPrivate; + parser.on("readable", function () { + while (parser.read()) { + parser.destroy(Error("Catch me")); + } + }); + parser.on("error", (err) => { + err.message.should.eql("Catch me"); + parser._readableState.destroyed.should.be.true(); + const version = /^v(\d+)/.exec(process.version); + if (version && parseInt(version[1], 10) >= 14) next(); + }); + parser.on("end", () => { + next(); + }); + generate({ length: 2, seed: 1, columns: 2, fixed_size: true }).pipe(parser); + }); +}); diff --git a/packages/csv-parse/test/api.stream.events.coffee b/packages/csv-parse/test/api.stream.events.coffee deleted file mode 100644 index 0a469cab9..000000000 --- a/packages/csv-parse/test/api.stream.events.coffee +++ /dev/null @@ -1,107 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'API events', -> - - it 'emit `readable` event', (next) -> - records = [] - parser = parse() - parser.on 'readable', -> - while record = this.read() - records.push record - parser.write """ - "ABC","45" - "DEF","23" - """ - parser.on 'end', -> - records.should.eql [ - [ 'ABC', '45' ] - [ 'DEF', '23' ] - ] - next() - parser.end() - - it 'emit `data` event', (next) -> - records = [] - parser = parse() - parser.on 'data', (record) -> - records.push record - parser.write """ - "ABC","45" - "DEF","23" - """ - parser.on 'end', -> - records.should.eql [ - [ 'ABC', '45' ] - [ 'DEF', '23' ] - ] - next() - parser.end() - - it 'ensure error in _transform is called once', (next) -> - data = ''' - x " a b",x " c d" - x " e f", x " g h" - ''' - parser = parse (err) -> - assert_error err, - message: 'Invalid Opening Quote: a quote is found on field 0 at line 1, value is " x "' - code: 'INVALID_OPENING_QUOTE' - field: ' x ' - next() - parser.write chr for chr in data - parser.end() - - it 'emit `error`', (next) -> - parser = parse() - parser.on 'readable', -> - while @read() then true - parser.on 'end', -> - next Error 'End should not be fired' - parser.on 'error', (err) -> - err.message.should.eql 'Invalid Record Length: expect 3, got 2 on line 2' - next() - parser.write """ - a,a,a - b,b - """ - parser.end() - - it 'emit `error` with data as argument', (next) -> - parser = parse """ - a,a,a - b,b - c,c,c - """ - parser.on 'end', -> - next Error 'End should not be fired' - parser.on 'error', (err) -> - err.message.should.eql 'Invalid Record Length: expect 3, got 2 on line 2' - next() - - it 'emit `destroy` event', (next) -> - parser = parse """ - a,a,a - b,b,b - c,c,c - """ - parser.on 'readable', (data) -> - while this.read() isnt null then true - parser.on 'close', next - parser.on 'error', -> - next Error 'Event `error` should not be fired' - - it 'emit `destroy` event with `to_line` option', (next) -> - # See https://github.com/adaltas/node-csv/issues/333 - parser = parse """ - a,a,a - b,b,b - c,c,c - """, to_line: 2 - parser.on 'readable', (data) -> - while this.read() isnt null then true - parser.on 'close', next - parser.on 'error', -> - next Error 'Event `error` should not be fired' - diff --git a/packages/csv-parse/test/api.stream.events.ts b/packages/csv-parse/test/api.stream.events.ts new file mode 100644 index 000000000..5c8f0a7c8 --- /dev/null +++ b/packages/csv-parse/test/api.stream.events.ts @@ -0,0 +1,114 @@ +import "should"; +import { parse } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; + +describe("API events", function () { + it("emit `readable` event", function (next) { + const records: string[] = []; + const parser = parse(); + parser.on("readable", () => { + let record; + while ((record = parser.read())) { + records.push(record); + } + }); + parser.write('"ABC","45"\n"DEF","23"'); + parser.on("end", () => { + records.should.eql([ + ["ABC", "45"], + ["DEF", "23"], + ]); + next(); + }); + parser.end(); + }); + + it("emit `data` event", function (next) { + const records: string[] = []; + const parser = parse(); + parser.on("data", (record) => { + records.push(record); + }); + parser.write('"ABC","45"\n"DEF","23"'); + parser.on("end", () => { + records.should.eql([ + ["ABC", "45"], + ["DEF", "23"], + ]); + next(); + }); + parser.end(); + }); + + it("ensure error in _transform is called once", function (next) { + const data = ' x " a b",x " c d"\nx " e f", x " g h"'; + const parser = parse((err) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + 'Invalid Opening Quote: a quote is found on field 0 at line 1, value is " x "', + code: "INVALID_OPENING_QUOTE", + field: " x ", + }); + next(); + }); + for (const chr of data) { + parser.write(chr); + } + parser.end(); + }); + + it("emit `error`", function (next) { + const parser = parse(); + parser.on("readable", () => { + while (parser.read()) true; + }); + parser.on("end", () => { + next(Error("End should not be fired")); + }); + parser.on("error", (err) => { + err.message.should.eql( + "Invalid Record Length: expect 3, got 2 on line 2", + ); + next(); + }); + parser.write("a,a,a\nb,b"); + parser.end(); + }); + + it("emit `error` with data as argument", function (next) { + const parser = parse("a,a,a\nb,b\nc,c,c"); + parser.on("end", () => { + next(Error("End should not be fired")); + }); + parser.on("error", (err) => { + err.message.should.eql( + "Invalid Record Length: expect 3, got 2 on line 2", + ); + next(); + }); + }); + + it("emit `destroy` event", function (next) { + const parser = parse("a,a,a\nb,b,b\nc,c,c"); + parser.on("readable", () => { + while (parser.read() !== null) true; + }); + parser.on("close", next); + parser.on("error", () => { + next(Error("Event `error` should not be fired")); + }); + }); + + it("emit `destroy` event with `to_line` option", function (next) { + // See https://github.com/adaltas/node-csv/issues/333 + const parser = parse("a,a,a\nb,b,b\nc,c,c", { to_line: 2 }); + parser.on("readable", () => { + while (parser.read() !== null) true; + }); + parser.on("close", next); + parser.on("error", () => { + next(Error("Event `error` should not be fired")); + }); + }); +}); diff --git a/packages/csv-parse/test/api.stream.finished.coffee b/packages/csv-parse/test/api.stream.finished.coffee deleted file mode 100644 index 23ac98f22..000000000 --- a/packages/csv-parse/test/api.stream.finished.coffee +++ /dev/null @@ -1,61 +0,0 @@ - -import { Readable } from 'node:stream' -import * as stream from 'node:stream/promises' -import { generate } from 'csv-generate' -import { parse } from '../lib/index.js' - -describe 'API stream.finished', -> - - it 'resolved at the end', -> - # See https://github.com/adaltas/node-csv/issues/333 - records = [] - parser = generate(length: 10).pipe parse() - parser.on 'readable', () => - while (record = parser.read()) isnt null - records.push record - await stream.finished parser - records.length.should.eql 10 - - it 'aborted (with generate())', -> - # See https://github.com/adaltas/node-csv/issues/333 - # See https://github.com/adaltas/node-csv/issues/410 - # Prevent `Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close` - records = [] - parser = generate(length: 10).pipe parse to_line: 3 - parser.on 'readable', () => - while (record = parser.read()) isnt null - records.push record - await stream.finished parser - records.length.should.eql 3 - - it.skip 'aborted (with Readable)', -> - # See https://github.com/adaltas/node-csv/issues/333 - # See https://github.com/adaltas/node-csv/issues/410 - # Prevent `Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close` - records = [] - reader = new Readable - highWaterMark: 10 - read: (size) -> - for i in [0...size] - this.push "#{size},#{i}\n" - parser = reader.pipe parse to_line: 3 - parser.on 'readable', () => - while (record = parser.read()) isnt null - records.push record - await stream.finished parser - console.log records - records.length.should.eql 3 - - it 'rejected on error', -> - parser = parse to_line: 3 - parser.write 'a,b,c\n' - parser.write 'd,e,f\n' - parser.write 'h,i,j,ohno\n' - parser.write 'k,l,m\n' - parser.end() - parser.on 'readable', () => - while (record = parser.read()) isnt null then true - stream - .finished parser - .should.be.rejectedWith - code: 'CSV_RECORD_INCONSISTENT_FIELDS_LENGTH' diff --git a/packages/csv-parse/test/api.stream.finished.ts b/packages/csv-parse/test/api.stream.finished.ts new file mode 100644 index 000000000..43bae6663 --- /dev/null +++ b/packages/csv-parse/test/api.stream.finished.ts @@ -0,0 +1,77 @@ +import "should"; +import { Readable } from "node:stream"; +import * as stream from "node:stream/promises"; +import { generate } from "csv-generate"; +import { parse } from "../lib/index.js"; + +describe("API stream.finished", function () { + it("resolved at the end", async function () { + // See https://github.com/adaltas/node-csv/issues/333 + const records = []; + const parser = generate({ length: 10 }).pipe(parse()); + parser.on("readable", () => { + let record; + while ((record = parser.read()) !== null) { + records.push(record); + } + }); + await stream.finished(parser); + records.length.should.eql(10); + }); + + it("aborted (with generate())", async function () { + // See https://github.com/adaltas/node-csv/issues/333 + // See https://github.com/adaltas/node-csv/issues/410 + // Prevent `Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close` + const records = []; + const parser = generate({ length: 10 }).pipe(parse({ to_line: 3 })); + parser.on("readable", () => { + let record; + while ((record = parser.read()) !== null) { + records.push(record); + } + }); + await stream.finished(parser); + records.length.should.eql(3); + }); + + it.skip("aborted (with Readable)", async function () { + // See https://github.com/adaltas/node-csv/issues/333 + // See https://github.com/adaltas/node-csv/issues/410 + // Prevent `Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close` + const records: string[] = []; + const reader = new Readable({ + highWaterMark: 10, + read: function (size) { + for (let i = 0; i < size; i++) { + this.push(`${size},${i}\n`); + } + }, + }); + const parser = reader.pipe(parse({ to_line: 3 })); + parser.on("readable", () => { + let record; + while ((record = parser.read()) !== null) { + records.push(record); + } + }); + await stream.finished(parser); + console.log(records); + records.length.should.eql(3); + }); + + it("rejected on error", async function () { + const parser = parse({ to_line: 3 }); + parser.write("a,b,c\n"); + parser.write("d,e,f\n"); + parser.write("h,i,j,ohno\n"); + parser.write("k,l,m\n"); + parser.end(); + parser.on("readable", () => { + while (parser.read() !== null) true; + }); + stream.finished(parser).should.be.rejectedWith({ + code: "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", + }); + }); +}); diff --git a/packages/csv-parse/test/api.stream.iterator.coffee b/packages/csv-parse/test/api.stream.iterator.coffee deleted file mode 100644 index 196b0e127..000000000 --- a/packages/csv-parse/test/api.stream.iterator.coffee +++ /dev/null @@ -1,25 +0,0 @@ - -import * as stream from 'node:stream/promises' -import { generate } from 'csv-generate' -import { parse } from '../lib/index.js' - -describe 'API stream.iterator', -> - - it 'classic', -> - parser = generate(length: 10).pipe parse() - records = [] - for await record from parser - records.push record - records.length.should.eql 10 - - it 'with iteractor stoped in between', -> - # See https://github.com/adaltas/node-csv/issues/333 - # See https://github.com/adaltas/node-csv/issues/410 - # Prevent `Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close` - records = [] - parser = generate(length: 10).pipe parse - to_line: 2 - records = [] - for await record from parser - records.push record - records.length.should.eql 2 diff --git a/packages/csv-parse/test/api.stream.iterator.ts b/packages/csv-parse/test/api.stream.iterator.ts new file mode 100644 index 000000000..a45a360f3 --- /dev/null +++ b/packages/csv-parse/test/api.stream.iterator.ts @@ -0,0 +1,30 @@ +import "should"; +import { generate } from "csv-generate"; +import { parse } from "../lib/index.js"; + +describe("API stream.iterator", function () { + it("classic", async function () { + const parser = generate({ length: 10 }).pipe(parse()); + const records = []; + for await (const record of parser) { + records.push(record); + } + records.length.should.eql(10); + }); + + it("with iteractor stoped in between", async function () { + // See https://github.com/adaltas/node-csv/issues/333 + // See https://github.com/adaltas/node-csv/issues/410 + // Prevent `Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close` + const records = []; + const parser = generate({ length: 10 }).pipe( + parse({ + to_line: 2, + }), + ); + for await (const record of parser) { + records.push(record); + } + records.length.should.eql(2); + }); +}); diff --git a/packages/csv-parse/test/api.stream.pipe.coffee b/packages/csv-parse/test/api.stream.pipe.coffee deleted file mode 100644 index a2f036eb4..000000000 --- a/packages/csv-parse/test/api.stream.pipe.coffee +++ /dev/null @@ -1,59 +0,0 @@ - -import fs from 'fs' -import { Readable } from 'stream' -import { generate } from 'csv-generate' -import { parse } from '../lib/index.js' - -describe 'API pipe', -> - - it 'piping in and reading out', (next) -> - finished = false - parser = parse() - records = [] - generator = generate length: 2, seed: 1, columns: 2, fixed_size: true - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'end', -> - finished = true - parser.on 'end', -> - finished.should.be.ok - records.should.eql [ - [ 'OMH', 'ONKCHhJmjadoA' ] - [ 'D', 'GeACHiN' ] - ] - next() - generator.pipe(parser) - - it 'piping in and callback out', (next) -> - generator = generate length: 2, seed: 1, columns: 2, fixed_size: true - generator.pipe parse (err, records) -> - records.should.eql [ - [ 'OMH', 'ONKCHhJmjadoA' ] - [ 'D', 'GeACHiN' ] - ] - next() - - it 'catch source error', (next) -> - parser = parse() - parser.on 'error', -> - next new Error 'Should not pass here' - parser.on 'end', -> - next new Error 'Should not pass here' - rs = fs.createReadStream('/doesnotexist') - rs.on 'error', (err) -> - err.code.should.eql 'ENOENT' - next() - rs.pipe(parser) - - it 'handle empty string', (next) -> - s = new Readable() - s._read = -> - @push null - s.pipe parse - delimiter: ',' - , (err, records) -> - records.should.eql [] unless err - next err - - diff --git a/packages/csv-parse/test/api.stream.pipe.ts b/packages/csv-parse/test/api.stream.pipe.ts new file mode 100644 index 000000000..3c1870652 --- /dev/null +++ b/packages/csv-parse/test/api.stream.pipe.ts @@ -0,0 +1,89 @@ +import "should"; +import fs from "fs"; +import { Readable } from "stream"; +import { generate } from "csv-generate"; +import { parse, CsvError } from "../lib/index.js"; + +describe("API pipe", function () { + it("piping in and reading out", function (next) { + let finished = false; + const parser = parse(); + const records: string[] = []; + const generator = generate({ + length: 2, + seed: 1, + columns: 2, + fixed_size: true, + }); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + finished = true; + }); + parser.on("end", () => { + finished.should.be.ok; + records.should.eql([ + ["OMH", "ONKCHhJmjadoA"], + ["D", "GeACHiN"], + ]); + next(); + }); + generator.pipe(parser); + }); + + it("piping in and callback out", function (next) { + const generator = generate({ + length: 2, + seed: 1, + columns: 2, + fixed_size: true, + }); + generator.pipe( + parse((err, records) => { + records.should.eql([ + ["OMH", "ONKCHhJmjadoA"], + ["D", "GeACHiN"], + ]); + next(); + }), + ); + }); + + it("catch source error", function (next) { + const parser = parse(); + parser.on("error", () => { + next(new Error("Should not pass here")); + }); + parser.on("end", () => { + next(new Error("Should not pass here")); + }); + const rs = fs.createReadStream("/doesnotexist"); + rs.on("error", (err) => { + (err as CsvError).code.should.eql("ENOENT"); + next(); + }); + rs.pipe(parser); + }); + + it("handle empty string", function (next) { + const s = new Readable(); + s._read = () => { + s.push(null); + }; + s.pipe( + parse( + { + delimiter: ",", + }, + (err, records) => { + if (!err) records.should.eql([]); + next(err); + }, + ), + ); + }); +}); diff --git a/packages/csv-parse/test/api.stream.write.coffee b/packages/csv-parse/test/api.stream.write.coffee deleted file mode 100644 index defb7c4f9..000000000 --- a/packages/csv-parse/test/api.stream.write.coffee +++ /dev/null @@ -1,51 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'API write', -> - - it 'string randomly splited', (next) -> - records = [] - parser = parse() - parser.on 'readable', -> - while(d = parser.read()) - records.push d - parser.on 'end', -> - records.should.eql [ - [ 'Test 0', '0', '"' ] - [ 'Test 1', '1', '"' ] - [ 'Test 2', '2', '"' ] - [ 'Test 3', '3', '"' ] - [ 'Test 4', '4', '"' ] - [ 'Test 5', '5', '"' ] - [ 'Test 6', '6', '"' ] - [ 'Test 7', '7', '"' ] - [ 'Test 8', '8', '"' ] - [ 'Test 9', '9', '"' ] - ] - next() - buffer = '' - for i in [0...10] - buffer += ''.concat "Test #{i}", ',', i, ',', '""""', "\n" - if buffer.length > 250 - parser.write buffer.substr 0, 250 - buffer = buffer.substr 250 - parser.write buffer - parser.end() - - it 'throw error if not writable', (next) -> - parser = parse() - parser.on 'error', (err) -> - err.message.should.eql 'write after end' - next() - parser.write 'abc,123' - parser.end() - parser.write 'def,456' - - it 'support multi-bytes utf8 encoded characters', (next) -> - parser = parse (err, records) -> - records[0][0].should.eql '€' - next() - parser.write Buffer.from [0xE2] - parser.write Buffer.from [0x82] - parser.write Buffer.from [0xAC] - parser.end() diff --git a/packages/csv-parse/test/api.stream.write.ts b/packages/csv-parse/test/api.stream.write.ts new file mode 100644 index 000000000..5424aac75 --- /dev/null +++ b/packages/csv-parse/test/api.stream.write.ts @@ -0,0 +1,62 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("API write", function () { + it("string randomly splited", function (next) { + const records: string[] = []; + const parser = parse(); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + records.should.eql([ + ["Test 0", "0", '"'], + ["Test 1", "1", '"'], + ["Test 2", "2", '"'], + ["Test 3", "3", '"'], + ["Test 4", "4", '"'], + ["Test 5", "5", '"'], + ["Test 6", "6", '"'], + ["Test 7", "7", '"'], + ["Test 8", "8", '"'], + ["Test 9", "9", '"'], + ]); + next(); + }); + let buffer = ""; + for (let i = 0; i < 10; i++) { + buffer += "".concat(`Test ${i}`, ",", `${i}`, ",", '""""', "\n"); + if (buffer.length > 250) { + parser.write(buffer.substring(0, 250)); + buffer = buffer.substring(250); + } + } + parser.write(buffer); + parser.end(); + }); + + it("throw error if not writable", function (next) { + const parser = parse(); + parser.on("error", (err) => { + err.message.should.eql("write after end"); + next(); + }); + parser.write("abc,123"); + parser.end(); + parser.write("def,456"); + }); + + it("support multi-bytes utf8 encoded characters", function (next) { + const parser = parse((err, records) => { + records[0][0].should.eql("€"); + next(); + }); + parser.write(Buffer.from([0xe2])); + parser.write(Buffer.from([0x82])); + parser.write(Buffer.from([0xac])); + parser.end(); + }); +}); diff --git a/packages/csv-parse/test/api.sync.coffee b/packages/csv-parse/test/api.sync.coffee deleted file mode 100644 index ccecfee91..000000000 --- a/packages/csv-parse/test/api.sync.coffee +++ /dev/null @@ -1,46 +0,0 @@ - -import { parse } from '../lib/sync.js' - -describe 'API sync', -> - - it 'take a string and return records', -> - records = parse 'field_1,field_2\nvalue 1,value 2' - records.should.eql [ [ 'field_1', 'field_2' ], [ 'value 1', 'value 2' ] ] - - it 'take a buffer and return records', -> - records = parse Buffer.from 'field_1,field_2\nvalue 1,value 2' - records.should.eql [ [ 'field_1', 'field_2' ], [ 'value 1', 'value 2' ] ] - - it 'honors columns option', -> - records = parse 'field_1,field_2\nvalue 1,value 2', columns: true - records.should.eql [ 'field_1': 'value 1', 'field_2': 'value 2' ] - - it 'honors objname option', -> - records = parse 'field_1,field_2\nname 1,value 1\nname 2,value 2', objname: 'field_1', columns: true - records.should.eql { - 'name 1': {'field_1': 'name 1', 'field_2': 'value 1'}, - 'name 2': {'field_1': 'name 2', 'field_2': 'value 2'} - } - - it 'honors to_line', -> - records = parse '1\n2\n3\n4', to_line: 2 - records.should.eql [ [ '1' ], [ '2' ] ] - - it 'catch errors', -> - try - parse 'A,B\nB\nC,K', trim: true - throw Error 'Error not catched' - catch err - err.message.should.eql 'Invalid Record Length: expect 2, got 1 on line 2' - - it 'catch err in last line while flushing', -> - ( -> - parse """ - headerA, headerB - A2, B2 - A1, B1, C2, D2 - """ - ).should.throw 'Invalid Record Length: expect 2, got 4 on line 3' - - - diff --git a/packages/csv-parse/test/api.sync.ts b/packages/csv-parse/test/api.sync.ts new file mode 100644 index 000000000..d04a3f6e2 --- /dev/null +++ b/packages/csv-parse/test/api.sync.ts @@ -0,0 +1,76 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/sync.js"; + +describe("API sync", function () { + it("take a string and return records", function () { + const records = parse("field_1,field_2\nvalue 1,value 2"); + records.should.eql([ + ["field_1", "field_2"], + ["value 1", "value 2"], + ]); + }); + + it("take a buffer and return records", function () { + const records = parse(Buffer.from("field_1,field_2\nvalue 1,value 2")); + records.should.eql([ + ["field_1", "field_2"], + ["value 1", "value 2"], + ]); + }); + + it("take a Uint8Array and return records", function () { + const records = parse( + new TextEncoder().encode("field_1,field_2\nvalue 1,value 2"), + ); + records.should.eql([ + ["field_1", "field_2"], + ["value 1", "value 2"], + ]); + }); + + it("honors columns option", function () { + const records = parse("field_1,field_2\nvalue 1,value 2", { + columns: true, + }); + records.should.eql([{ field_1: "value 1", field_2: "value 2" }]); + }); + + it("honors objname option", function () { + const records = parse("field_1,field_2\nname 1,value 1\nname 2,value 2", { + objname: "field_1", + columns: true, + }); + records.should.eql({ + "name 1": { field_1: "name 1", field_2: "value 1" }, + "name 2": { field_1: "name 2", field_2: "value 2" }, + }); + }); + + it("honors to_line", function () { + const records = parse("1\n2\n3\n4", { to_line: 2 }); + records.should.eql([["1"], ["2"]]); + }); + + it("catch errors", function () { + try { + parse("A,B\nB\nC,K", { trim: true }); + throw Error("Error not catched"); + } catch (err) { + if (!err) throw Error("Invalid assessment"); + (err as Error).message.should.eql( + "Invalid Record Length: expect 2, got 1 on line 2", + ); + } + }); + + it("catch err in last line while flushing", function () { + (() => { + parse(dedent` + headerA, headerB + A2, B2 + A1, B1, C2, D2 + `); + }).should.throw("Invalid Record Length: expect 2, got 4 on line 3"); + }); +}); diff --git a/packages/csv-parse/test/api.types.sync.ts b/packages/csv-parse/test/api.types.sync.ts index afccfd19f..8bd36a1c7 100644 --- a/packages/csv-parse/test/api.types.sync.ts +++ b/packages/csv-parse/test/api.types.sync.ts @@ -1,83 +1,92 @@ - -import 'should' +import "should"; import { parse, - CastingContext, CastingFunction, CastingDateFunction, - ColumnOption, Options, Info, CsvErrorCode, CsvError -} from '../lib/sync.js' + CastingContext, + CastingFunction, + CastingDateFunction, + ColumnOption, + Options, + Info, + CsvErrorCode, + CsvError, +} from "../lib/sync.js"; + +describe("API Types", function () { + type Person = { name: string; age: number }; -describe('API Types', () => { - - it('respect parse signature', () => { + it("respect parse signature", function () { // No argument - parse("") - parse("", {}) - parse(Buffer.from("")) - parse(Buffer.from(""), {}) - }) - - it('return records', () => { + parse(""); + parse("", {}); + parse(Buffer.from("")); + parse(Buffer.from(""), {}); + }); + + it("return records", function () { try { - const records: object = parse("") - typeof records - }catch (err){ - if (err instanceof CsvError){ - err.message + const records = parse(""); + typeof records; + } catch (err) { + if (err instanceof CsvError) { + err.message; } } - }) - - it('Options', () => { + }); + + it("Options", function () { (options: Options) => { const bom: boolean | undefined = options.bom; - return [bom] - } - }) - - it('CastingContext', () => { + return [bom]; + }; + }); + + it("CastingContext", function () { const options: Options = { cast: (value: string, context: CastingContext) => { - return `${value} ${context.index}` - } - } + return `${value} ${context.index}`; + }, + }; return options; - }) - - it('CastingDateFunction', () => { - const castDate: CastingDateFunction = (value: string, context: CastingContext) => { - return new Date(`${value} ${context.index}`) - } + }); + + it("CastingDateFunction", function () { + const castDate: CastingDateFunction = ( + value: string, + context: CastingContext, + ) => { + return new Date(`${value} ${context.index}`); + }; const options: Options = { - cast_date: castDate - } + cast_date: castDate, + }; return options; - }) - - it('CastingFunction', () => { + }); + + it("CastingFunction", function () { const cast: CastingFunction = (value: string, context: CastingContext) => { - return `${value} ${context.index}` + return `${value} ${context.index}`; }; const options: Options = { - cast: cast + cast: cast, }; return options; - }) - - it('ColumnOption', () => { - const column: ColumnOption = {name: 'sth'}; + }); + + it("ColumnOption", function () { + const column: ColumnOption = { name: "sth" }; const options: Options = { - columns: [column] - } + columns: [column], + }; return options; - }) - - it('CsvErrorCode', () => { - const err = new CsvError('CSV_RECORD_INCONSISTENT_FIELDS_LENGTH', 'error'); + }); + + it("CsvErrorCode", function () { + const err = new CsvError("CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", "error"); const code: CsvErrorCode = err.code; return code; - }) - - it('Info', () => { + }); + + it("Info", function () { const info: Info = { bytes: 1, columns: true, @@ -88,6 +97,29 @@ describe('API Types', () => { records: 1, }; return info; - }) - -}) + }); + + describe("Generic types", function () { + it("Exposes string[][] if columns is not specified", function () { + const data: string[][] = parse("", {}); + }); + + it("Exposes string[][] if columns is falsy", function () { + const data: string[][] = parse("", { + columns: false, + }); + }); + + it("Exposes unknown[] if columns is specified as boolean", function () { + const data: unknown[] = parse("", { + columns: true, + }); + }); + + it("Exposes T[] if columns is specified", function () { + const data: Person[] = parse("", { + columns: true, + }); + }); + }); +}); diff --git a/packages/csv-parse/test/api.types.ts b/packages/csv-parse/test/api.types.ts index c57c34f27..30920d5e5 100644 --- a/packages/csv-parse/test/api.types.ts +++ b/packages/csv-parse/test/api.types.ts @@ -1,398 +1,506 @@ +import "should"; +import { + parse, + CastingContext, + Info, + Options, + Parser, + CsvError, + normalize_options, +} from "../lib/index.js"; -import 'should' -import { parse, CastingContext, Info, Options, Parser, CsvError } from '../lib/index.js' -import { parse as parse_sync } from '../lib/sync.js' +describe("API Types", function () { + type Person = { name: string; age: number }; -describe('API Types', () => { - - describe('stream/callback API', () => { - - it('respect parse signature', () => { + describe("stream/callback API", function () { + it("respect parse signature", function () { // No argument - parse() - parse("") - parse("", () => {}) - parse("", {}) - parse("", {}, () => {}) - parse(Buffer.from("")) - parse(Buffer.from(""), () => {}) - parse(Buffer.from(""), {}) - parse(Buffer.from(""), {}, () => {}) - parse(() => {}) - parse({}) - parse({}, () => {}) - }) - - it('Expose options', () => { - const parser: Parser = parse() - const options: Options = parser.options - const keys: string[] = Object.keys(options) - keys.sort().should.eql([ - 'bom', 'cast', 'cast_date', 'cast_first_line_to_header', - 'cast_function', 'columns', 'comment', 'comment_no_infix', 'delimiter', - 'encoding', 'escape', 'from', 'from_line', 'group_columns_by_name', - 'ignore_last_delimiters', 'info', 'ltrim', 'max_record_size', 'objname', - 'on_record', 'on_skip', 'quote', 'raw', 'record_delimiter', - 'relax_column_count', 'relax_column_count_less', - 'relax_column_count_more', 'relax_quotes', 'rtrim', 'skip_empty_lines', - 'skip_records_with_empty_values', 'skip_records_with_error', 'to', - 'to_line', 'trim' - ]) - }) - - it('Expose info', () => { - const parser: Parser = parse() - const info: Info = parser.info - const keys: string[] = Object.keys(info) - keys.sort().should.eql([ - 'bytes', - 'comment_lines', 'empty_lines', - 'invalid_field_length', 'lines', 'records' - ]) - }) - - it('Receive Callback', (next) => { - parse('a\nb', function(err: Error|undefined, records: object, info: Info){ - if(err !== undefined){ - records.should.eql([['a'], ['b']]) - info.records.should.eql(2) - } - next(err) - }) - }) - - }) - - describe('sync api', () => { - - it('respect parse signature', () => { - // No argument - parse_sync("") - parse_sync("", {}) - parse_sync(Buffer.from("")) - parse_sync(Buffer.from(""), {}) - }) - - it('return records', () => { - try { - const records: object = parse_sync("") - typeof records - }catch (err){ - if (err instanceof CsvError){ - err.message + parse(); + parse(""); + parse("", () => {}); + parse("", {}); + parse("", {}, () => {}); + parse(Buffer.from("")); + parse(Buffer.from(""), () => {}); + parse(Buffer.from(""), {}); + parse(Buffer.from(""), {}, () => {}); + parse(() => {}); + parse({}); + parse({}, () => {}); + }); + + it("Expose options", function () { + const parser: Parser = parse(); + const options = parser.options; + const keys: string[] = Object.keys(options); + keys + .sort() + .should.eql([ + "bom", + "cast", + "cast_date", + "cast_first_line_to_header", + "cast_function", + "columns", + "comment", + "comment_no_infix", + "delimiter", + "encoding", + "escape", + "from", + "from_line", + "group_columns_by_name", + "ignore_last_delimiters", + "info", + "ltrim", + "max_record_size", + "objname", + "on_record", + "on_skip", + "quote", + "raw", + "record_delimiter", + "relax_column_count", + "relax_column_count_less", + "relax_column_count_more", + "relax_quotes", + "rtrim", + "skip_empty_lines", + "skip_records_with_empty_values", + "skip_records_with_error", + "to", + "to_line", + "trim", + ]); + }); + + it("Expose info", function () { + const parser: Parser = parse(); + const info: Info = parser.info; + const keys: string[] = Object.keys(info); + keys + .sort() + .should.eql([ + "bytes", + "comment_lines", + "empty_lines", + "invalid_field_length", + "lines", + "records", + ]); + }); + + it("Receive Callback", function (next) { + parse("a\nb", function (err, records, info) { + if (err !== undefined) { + records!.should.eql([["a"], ["b"]]); + info!.records.should.eql(2); } - } - }) - - }) - - describe('Info', () => { - + next(err); + }); + }); + }); + + describe("Info", function () { const fakeinfo = { - bytes: 1, columns: true, - comment_lines: 1, empty_lines: 1, - invalid_field_length: 1, lines: 1, records: 1 - } - - it('bytes', () => { - const info: Info = fakeinfo - const bytes: number = info.bytes - bytes - }) - - it('comment_lines', () => { - const info: Info = fakeinfo - const comment_lines: number = info.comment_lines - comment_lines - }) - - it('empty_lines', () => { - const info: Info = fakeinfo - const empty_lines: number = info.empty_lines - empty_lines - }) - - it('lines', () => { - const info: Info = fakeinfo - const lines: number = info.lines - lines - }) - - it('records', () => { - const info: Info = fakeinfo - const records: number = info.records - records - }) - - it('invalid_field_length', () => { - const info: Info = fakeinfo - const invalid_field_length: number = info.invalid_field_length - invalid_field_length - }) - - it('columns may be a boolean or an array', () => { + bytes: 1, + columns: true, + comment_lines: 1, + empty_lines: 1, + invalid_field_length: 1, + lines: 1, + records: 1, + }; + + it("bytes", function () { + const info: Info = fakeinfo; + const bytes: number = info.bytes; + bytes; + }); + + it("comment_lines", function () { + const info: Info = fakeinfo; + const comment_lines: number = info.comment_lines; + comment_lines; + }); + + it("empty_lines", function () { + const info: Info = fakeinfo; + const empty_lines: number = info.empty_lines; + empty_lines; + }); + + it("lines", function () { + const info: Info = fakeinfo; + const lines: number = info.lines; + lines; + }); + + it("records", function () { + const info: Info = fakeinfo; + const records: number = info.records; + records; + }); + + it("invalid_field_length", function () { + const info: Info = fakeinfo; + const invalid_field_length: number = info.invalid_field_length; + invalid_field_length; + }); + + it("columns may be a boolean or an array", function () { // Boolean const infoBoolean: Info = { - bytes: 1, columns: true, - comment_lines: 1, empty_lines: 1, - invalid_field_length: 1, lines: 1, records: 1 - } + bytes: 1, + columns: true, + comment_lines: 1, + empty_lines: 1, + invalid_field_length: 1, + lines: 1, + records: 1, + }; + infoBoolean; // Array with name = const infoName: Info = { - bytes: 1, columns: [{name: 'a column'}], - comment_lines: 1, empty_lines: 1, - invalid_field_length: 1, lines: 1, records: 1 - } + bytes: 1, + columns: [{ name: "a column" }], + comment_lines: 1, + empty_lines: 1, + invalid_field_length: 1, + lines: 1, + records: 1, + }; + infoName; // Array with disabled = true const infoDisabled: Info = { - bytes: 1, columns: [{disabled: true}], - comment_lines: 1, empty_lines: 1, - invalid_field_length: 1, lines: 1, records: 1 - } - }) - - }) - - describe('Options', () => { - - it('cast', () => { - const options: Options = {} - options.cast = true - options.cast = () => {} - }) - - it('cast_date', () => { - const options: Options = {} - options.cast_date = true - options.castDate = true + bytes: 1, + columns: [{ disabled: true }], + comment_lines: 1, + empty_lines: 1, + invalid_field_length: 1, + lines: 1, + records: 1, + }; + infoDisabled; + }); + }); + + describe("Options", function () { + it("cast", function () { + const options: Options = {}; + options.cast = true; + options.cast = () => {}; + }); + + it("cast_date", function () { + const options: Options = {}; + options.cast_date = true; + options.castDate = true; options.cast_date = (value: string, context: CastingContext) => { - return new Date(`${value} ${context.index}`) - } - }) - - it('columns', () => { - const options: Options = {} - options.columns = true - options.columns = [] - options.columns = ['string', undefined, null, false, {name: 'column-name'}] - options.columns = (record: string[]) => { - const fields: string[] = record.map( (field: string) => { - return field.toUpperCase() - }) - return fields - } - options.columns = (record: string[]) => { - record - return ['string', undefined, null, false, {name: 'column-name'}] - } - }) - - it('group_columns_by_name', () => { - const options: Options = {} - options.group_columns_by_name = true - options.groupColumnsByName = true - }) - - it('comment', () => { - const options: Options = {} - options.comment = '\\' - }) - - it('delimiter', () => { - const options: Options = {} - options.delimiter = ':' - options.delimiter = [':', ')'] - options.delimiter = Buffer.from(':') - }) - - it('escape', () => { - const options: Options = {} - options.escape = ':' - options.escape = Buffer.from('"') - }) - - it('from', () => { - const options: Options = {} - options.from = 10 - }) - - it('from_line', () => { - const options: Options = {} - options.from_line = 10 - options.fromLine = 10 - }) - - it('ignore_last_delimiters', () => { - const options: Options = {} - options.ignore_last_delimiters = true - options.ignore_last_delimiters = 1 - }) - - it('info', () => { - const options: Options = {} - options.info = true - }) - - it('ltrim', () => { - const options: Options = {} - options.ltrim = true - }) - - it('max_record_size', () => { - const options: Options = {} - options.max_record_size = 100 - options.maxRecordSize = 100 - }) - - it('objname', () => { - const options: Options = {} - options.objname = 'name' - }) - - it('on_record', () => { - const options: Options = {} - options.on_record = (record, {lines}) => - [lines, record[0]] - options.onRecord = (record, {lines}) => - [lines, record[0]] - }) - - it('quote', () => { - const options: Options = {} - options.quote = '"' - options.quote = true - options.quote = Buffer.from('"') - options.quote = null - }) - - it('raw', () => { - const options: Options = {} - options.raw = true - }) - - it('relax_column_count', () => { - const options: Options = {} - options.relax_column_count = true - options.relaxColumnCount = true - options.relax_column_count_less = true - options.relaxColumnCountLess = true - options.relax_column_count_more = true - options.relaxColumnCountMore = true - }) - - it('relax_quotes', () => { - const options: Options = {} - options.relax_quotes = true - options.relaxQuotes = true - }) - - it('record_delimiter', () => { - const options: Options = {} - options.record_delimiter = '\n' - options.record_delimiter = ['\n'] - options.record_delimiter = Buffer.from('\n') - options.record_delimiter = [Buffer.from('\n')] - options.recordDelimiter = '\n' - }) - - it('rtrim', () => { - const options: Options = {} - options.rtrim = true - }) - - it('skip_empty_lines', () => { - const options: Options = {} - options.skip_empty_lines = true - options.skipEmptyLines = true - }) - - it('skip_empty_lines', () => { - const options: Options = {} - options.skip_empty_lines = true - options.skipEmptyLines = true - }) - - it('skip_records_with_empty_values', () => { - const options: Options = {} - options.skip_records_with_empty_values = true - options.skipRecordsWithEmptyValues = true - }) - - it('skip_records_with_error', () => { - const options: Options = {} - options.skip_records_with_error = true - options.skipRecordsWithError = true - }) - - it('to', () => { - const options: Options = {} - options.to = 10 - }) - - it('to_line', () => { - const options: Options = {} - options.to_line = 10 - options.toLine = 10 - }) - - it('trim', () => { - const options: Options = {} - options.trim = true - }) - - }) - - describe('CastingContext', () => { - - it('all properties', () => { + return new Date(`${value} ${context.index}`); + }; + }); + + it("columns", function () { + const options: Options = {}; + options.columns = true; + options.columns = []; + options.columns = [ + "string", + undefined, + null, + false, + { name: "column-name" }, + ]; + options.columns = (record) => { + const fields = record.map((field: string) => { + return field.toUpperCase(); + }); + return fields; + }; + options.columns = (record) => { + record; + return ["string", undefined, null, false, { name: "column-name" }]; + }; + + const typedOptions: Options = {}; + typedOptions.columns = ["age", undefined, null, false, { name: "name" }]; + typedOptions.columns = (record: Person) => { + record; + return ["age"]; + }; + + const unknownTypedOptions: Options = {}; + unknownTypedOptions.columns = ["anything", undefined, null, false]; + unknownTypedOptions.columns = (record: unknown) => { + record; + return ["anything", undefined, null, false]; + }; + }); + + it("group_columns_by_name", function () { + const options: Options = {}; + options.group_columns_by_name = true; + options.groupColumnsByName = true; + }); + + it("comment", function () { + const options: Options = {}; + options.comment = "\\"; + }); + + it("delimiter", function () { + const options: Options = {}; + options.delimiter = ":"; + options.delimiter = [":", ")"]; + options.delimiter = Buffer.from(":"); + }); + + it("escape", function () { + const options: Options = {}; + options.escape = ":"; + options.escape = Buffer.from('"'); + }); + + it("from", function () { + const options: Options = {}; + options.from = 10; + }); + + it("from_line", function () { + const options: Options = {}; + options.from_line = 10; + options.fromLine = 10; + }); + + it("ignore_last_delimiters", function () { + const options: Options = {}; + options.ignore_last_delimiters = true; + options.ignore_last_delimiters = 1; + }); + + it("info", function () { + const options: Options = {}; + options.info = true; + }); + + it("ltrim", function () { + const options: Options = {}; + options.ltrim = true; + }); + + it("max_record_size", function () { + const options: Options = {}; + options.max_record_size = 100; + options.maxRecordSize = 100; + }); + + it("objname", function () { + const options: Options = {}; + options.objname = "name"; + }); + + it("on_record", function () { + const options: Options = {}; + options.on_record = (record, { lines }) => [lines.toString(), record[0]]; + options.onRecord = (record, { lines }) => [lines.toString(), record[0]]; + }); + + it("quote", function () { + const options: Options = {}; + options.quote = '"'; + options.quote = true; + options.quote = Buffer.from('"'); + options.quote = null; + }); + + it("raw", function () { + const options: Options = {}; + options.raw = true; + }); + + it("relax_column_count", function () { + const options: Options = {}; + options.relax_column_count = true; + options.relaxColumnCount = true; + options.relax_column_count_less = true; + options.relaxColumnCountLess = true; + options.relax_column_count_more = true; + options.relaxColumnCountMore = true; + }); + + it("relax_quotes", function () { + const options: Options = {}; + options.relax_quotes = true; + options.relaxQuotes = true; + }); + + it("record_delimiter", function () { + const options: Options = {}; + options.record_delimiter = "\n"; + options.record_delimiter = ["\n"]; + options.record_delimiter = Buffer.from("\n"); + options.record_delimiter = [Buffer.from("\n")]; + options.recordDelimiter = "\n"; + }); + + it("rtrim", function () { + const options: Options = {}; + options.rtrim = true; + }); + + it("skip_empty_lines", function () { + const options: Options = {}; + options.skip_empty_lines = true; + options.skipEmptyLines = true; + }); + + it("skip_records_with_empty_values", function () { + const options: Options = {}; + options.skip_records_with_empty_values = true; + options.skipRecordsWithEmptyValues = true; + }); + + it("skip_records_with_error", function () { + const options: Options = {}; + options.skip_records_with_error = true; + options.skipRecordsWithError = true; + }); + + it("to", function () { + const options: Options = {}; + options.to = 10; + }); + + it("to_line", function () { + const options: Options = {}; + options.to_line = 10; + options.toLine = 10; + }); + + it("trim", function () { + const options: Options = {}; + options.trim = true; + }); + }); + + describe("CastingContext", function () { + it("all properties", function () { (context: CastingContext) => { - const column: number|string = context.column - const empty_lines: number = context.empty_lines - const header: boolean = context.header - const index: number = context.index - const quoting: boolean = context.quoting - const lines: number = context.lines - const records: number = context.records - const invalid_field_length: number = context.invalid_field_length + const column: number | string = context.column; + const empty_lines: number = context.empty_lines; + const header: boolean = context.header; + const index: number = context.index; + const quoting: boolean = context.quoting; + const lines: number = context.lines; + const records: number = context.records; + const invalid_field_length: number = context.invalid_field_length; return [ - column, empty_lines, header, index, - quoting, lines, records, invalid_field_length - ] - } - }) - }) - - describe('CsvError', () => { - describe('Typescript definition is accurate', () => { - it('Minimum', () => { - const error = new CsvError("CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", "MESSAGE"); - - error.code.should.eql("CSV_RECORD_INCONSISTENT_FIELDS_LENGTH") - error.message.should.eql("MESSAGE") - }) - - it('Multiple messages', () => { - const error = new CsvError("CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", ["MESSAGE1", "MESSAGE2"]) - - error.code.should.eql("CSV_RECORD_INCONSISTENT_FIELDS_LENGTH") - error.message.should.eql("MESSAGE1 MESSAGE2") - }) - - it('Supports contexts', () => { - const error = new CsvError("CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", "MESSAGE", {}, { testContext: { testProp: "testValue" } }) - - error.code.should.eql("CSV_RECORD_INCONSISTENT_FIELDS_LENGTH") - error.message.should.eql("MESSAGE") - error.should.have.key("testContext").and.eql({ testProp: "testValue" }) - }) - }) - - it('Proper type is thrown when an error is encountered', () => { - parse(`a,b\nc`, function (e: Error|undefined) { + column, + empty_lines, + header, + index, + quoting, + lines, + records, + invalid_field_length, + ]; + }; + }); + }); + + describe("CsvError", function () { + describe("Typescript definition is accurate", function () { + it("Minimum", function () { + const error = new CsvError( + "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", + "MESSAGE", + ); + + error.code.should.eql("CSV_RECORD_INCONSISTENT_FIELDS_LENGTH"); + error.message.should.eql("MESSAGE"); + }); + + it("Multiple messages", function () { + const error = new CsvError("CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", [ + "MESSAGE1", + "MESSAGE2", + ]); + + error.code.should.eql("CSV_RECORD_INCONSISTENT_FIELDS_LENGTH"); + error.message.should.eql("MESSAGE1 MESSAGE2"); + }); + + it("Supports contexts", function () { + const options = normalize_options({}); + const error = new CsvError( + "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", + "MESSAGE", + options, + { testContext: { testProp: "testValue" } }, + ); + + error.code.should.eql("CSV_RECORD_INCONSISTENT_FIELDS_LENGTH"); + error.message.should.eql("MESSAGE"); + error.should.have.key("testContext").and.eql({ testProp: "testValue" }); + }); + }); + + it("Proper type is thrown when an error is encountered", function () { + parse(`a,b\nc`, function (e) { + if (!e) throw Error("Invalid assessment"); const isCsvError = e instanceof CsvError; isCsvError.should.be.true(); - (e as CsvError).code.should.eql('CSV_RECORD_INCONSISTENT_FIELDS_LENGTH'); - }) - }) - }) -}) + e.code.should.eql("CSV_RECORD_INCONSISTENT_FIELDS_LENGTH"); + }); + }); + }); + + describe("Generic types", function () { + it("Exposes string[][] if columns is not specified", function (next) { + parse("", {}, (error, records: string[][] | undefined) => { + records; + next(error); + }); + }); + + it("Exposes string[][] if columns is falsy", function (next) { + parse( + "", + { + columns: false, + }, + (error, records: string[][] | undefined) => { + records; + next(error); + }, + ); + }); + + it("Exposes unknown[] if columns is specified as boolean", function (next) { + parse( + "", + { + columns: true, + }, + (error, records: unknown[] | undefined) => { + records; + next(error); + }, + ); + }); + + it("Exposes T[] if columns is specified", function (next) { + parse( + "", + { + columns: true, + }, + (error, records: Person[]) => { + records; + next(error); + }, + ); + }); + }); +}); diff --git a/packages/csv-parse/test/api.web_stream.coffee b/packages/csv-parse/test/api.web_stream.coffee deleted file mode 100644 index 5165f8776..000000000 --- a/packages/csv-parse/test/api.web_stream.coffee +++ /dev/null @@ -1,54 +0,0 @@ - -import {generate as generateStream} from 'csv-generate/stream' -import {parse as parseStream} from '../lib/stream.js' -import {parse as parseClassic} from '../lib/index.js' - -describe 'api stream', -> - - it.skip 'perf classic', -> - console.time('classic') - generator = generateClassic({ - objectMode: true, - length: 10000000 - }) - for await record from generator - continue - console.timeEnd('classic') - - it.skip 'perf stream', -> - console.time('stream') - generator = generateStream({ - objectMode: true, - length: 10000000 - }) - reader = generator.getReader() - while true - { done, value } = await reader.read() - break if done - # for await chunk from generator.getReader().read() - # console.log(Buffer.from(chunk).toString()); - console.timeEnd('stream') - - it 'perf stream with iterator', -> - generator = generateStream - objectMode: false, - length: 5 - parser = parseStream() - stream = generator.pipeThrough parser - records = [] - for await record from stream - records.push record - records.length.should.eql 5 - - # it 'perf stream with reader', -> - # generator = generateStream({ - # objectMode: true, - # length: 10 - # }); - # records = [] - # reader = generator.getReader() - # while true - # { done, record } = await reader.read() - # break if done - # records.push record - # records.length.should.eql 10 diff --git a/packages/csv-parse/test/api.web_stream.js b/packages/csv-parse/test/api.web_stream.js new file mode 100644 index 000000000..9b79664e9 --- /dev/null +++ b/packages/csv-parse/test/api.web_stream.js @@ -0,0 +1,67 @@ +import "should"; +import { generate as generateStream } from "csv-generate/stream"; +import { parse as parseStream } from "../lib/stream.js"; + +describe("api stream", function () { + it.skip("perf classic", async function () { + console.time("classic"); + // TODO: implement + const generateClassic = () => {}; + const generator = generateClassic({ + objectMode: true, + length: 10000000, + }); + for await (const record of generator) { + record; + continue; + } + console.timeEnd("classic"); + }); + + it.skip("perf stream", async function () { + console.time("stream"); + const generator = generateStream({ + objectMode: true, + length: 10000000, + }); + const reader = generator.getReader(); + while (true) { + const { done, value } = await reader.read(); + value; + if (done) break; + } + // for await (const chunk of generator.getReader().read()) { + // console.log(Buffer.from(chunk).toString()); + // } + console.timeEnd("stream"); + }); + + it("perf stream with iterator", async function () { + const generator = generateStream({ + objectMode: false, + length: 5, + }); + const parser = parseStream(); + const stream = generator.pipeThrough(parser); + const records = []; + for await (const record of stream) { + records.push(record); + } + records.length.should.eql(5); + }); + + // it('perf stream with reader', async function() { + // const generator = generateStream({ + // objectMode: true, + // length: 10 + // }); + // const records = []; + // const reader = generator.getReader(); + // while (true) { + // const { done, record } = await reader.read(); + // if (done) break; + // records.push(record); + // } + // records.length.should.eql(10); + // }); +}); diff --git a/packages/csv-parse/test/api.web_stream.ts b/packages/csv-parse/test/api.web_stream.ts index c328d1efb..38a724a83 100644 --- a/packages/csv-parse/test/api.web_stream.ts +++ b/packages/csv-parse/test/api.web_stream.ts @@ -2,9 +2,9 @@ import "should"; import { parse as parseStream } from "../lib/stream.js"; import { CsvError } from "../lib/index.js"; -describe("API Web Stream", () => { - describe("stream/web/TransformStream", () => { - it("simple parse", async () => { +describe("API Web Stream", function () { + describe("stream/web/TransformStream", function () { + it("simple parse", async function () { const stream = parseStream(); const writer = stream.writable.getWriter(); const reader = stream.readable.getReader(); diff --git a/packages/csv-parse/test/info.comment_lines.coffee b/packages/csv-parse/test/info.comment_lines.coffee deleted file mode 100644 index d6a4974c2..000000000 --- a/packages/csv-parse/test/info.comment_lines.coffee +++ /dev/null @@ -1,59 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'info comment_lines', -> - - it 'no empty lines', (next) -> - parse ''' - a,b,c - d,e,f - ''', comment: '#', (err, records, {comment_lines}) -> - comment_lines.should.eql 0 unless err - next err - - it 'comment in the middle of a line', (next) -> - parse ''' - a,b,c - d,e,f # comment - h,i,j - ''', comment: '#', (err, records, {comment_lines}) -> - comment_lines.should.eql 0 unless err - next err - - it 'single comment line', (next) -> - parse '# comment', comment: '#', (err, records, {comment_lines}) -> - comment_lines.should.eql 1 unless err - next err - - it 'single comment line with empty field', (next) -> - parse '""# comment', comment: '#', (err, records, {comment_lines}) -> - comment_lines.should.eql 0 unless err - next err - - it 'two line in the middle of dataset', (next) -> - parse ''' - a,b,c - # comment 1 - # comment 2 - d,e,f - ''', comment: '#', skip_empty_lines: true, (err, records, {comment_lines}) -> - comment_lines.should.eql 2 unless err - next err - - it 'one line at the end of dataset', (next) -> - parse ''' - a,b,c - d,e,f - # comment - ''', comment: '#', (err, records, {comment_lines}) -> - comment_lines.should.eql 1 unless err - next err - - it 'one line a the begining', (next) -> - parse ''' - # comment - a,b,c - d,e,f - ''', comment: '#', (err, records, {comment_lines}) -> - comment_lines.should.eql 1 unless err - next err diff --git a/packages/csv-parse/test/info.comment_lines.js b/packages/csv-parse/test/info.comment_lines.js new file mode 100644 index 000000000..dd307c37a --- /dev/null +++ b/packages/csv-parse/test/info.comment_lines.js @@ -0,0 +1,96 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("info comment_lines", function () { + it("no empty lines", function (next) { + parse( + "a,b,c\nd,e,f", + { + comment: "#", + }, + (err, records, { comment_lines }) => { + if (!err) comment_lines.should.eql(0); + next(err); + }, + ); + }); + + it("comment in the middle of a line", function (next) { + parse( + "a,b,c\nd,e,f # comment\nh,i,j", + { + comment: "#", + }, + (err, records, { comment_lines }) => { + if (!err) comment_lines.should.eql(0); + next(err); + }, + ); + }); + + it("single comment line", function (next) { + parse( + "# comment", + { + comment: "#", + }, + (err, records, { comment_lines }) => { + if (!err) comment_lines.should.eql(1); + next(err); + }, + ); + }); + + it("single comment line with empty field", function (next) { + parse( + '""# comment', + { + comment: "#", + }, + (err, records, { comment_lines }) => { + if (!err) comment_lines.should.eql(0); + next(err); + }, + ); + }); + + it("two line in the middle of dataset", function (next) { + parse( + "a,b,c\n# comment 1\n# comment 2\nd,e,f", + { + comment: "#", + skip_empty_lines: true, + }, + (err, records, { comment_lines }) => { + if (!err) comment_lines.should.eql(2); + next(err); + }, + ); + }); + + it("one line at the end of dataset", function (next) { + parse( + "a,b,c\nd,e,f\n# comment", + { + comment: "#", + }, + (err, records, { comment_lines }) => { + if (!err) comment_lines.should.eql(1); + next(err); + }, + ); + }); + + it("one line a the begining", function (next) { + parse( + "# comment\na,b,c\nd,e,f", + { + comment: "#", + }, + (err, records, { comment_lines }) => { + if (!err) comment_lines.should.eql(1); + next(err); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/info.empty_lines.coffee b/packages/csv-parse/test/info.empty_lines.coffee deleted file mode 100644 index 1cb0f496b..000000000 --- a/packages/csv-parse/test/info.empty_lines.coffee +++ /dev/null @@ -1,54 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'info empty_lines', -> - - it 'no lines', (next) -> - parse '', (err, records, {empty_lines}) -> - empty_lines.should.eql 0 - next() - - it 'no empty lines', (next) -> - parse ''' - a,b,c - d,e,f - ''', (err, records, {empty_lines}) -> - empty_lines.should.eql 0 - next() - - it 'one line in the middle of dataset', (next) -> - parse ''' - a,b,c - - d,e,f - ''', skip_empty_lines: true, (err, records, {empty_lines}) -> - empty_lines.should.eql 1 - next() - - it 'one line at the end of dataset', (next) -> - parse ''' - a,b,c - d,e,f - - ''', (err, records, {empty_lines}) -> - empty_lines.should.eql 1 - next() - - it 'dont count empty lines when empty and skip_empty_lines disabled', (next) -> - parse ''' - - a,b,c - d,e,f - ''', (err, records, {empty_lines}) -> - err.message.should.eql 'Invalid Record Length: expect 1, got 3 on line 2' - empty_lines.should.eql 0 - next() - - it 'dont count commented lines', (next) -> - parse ''' - a,b,c - d,e,f - # comment - ''', (err, records, {empty_lines}) -> - empty_lines.should.eql 0 - next() diff --git a/packages/csv-parse/test/info.empty_lines.js b/packages/csv-parse/test/info.empty_lines.js new file mode 100644 index 000000000..93d62b6c4 --- /dev/null +++ b/packages/csv-parse/test/info.empty_lines.js @@ -0,0 +1,55 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("info empty_lines", function () { + it("no lines", function (next) { + parse("", (err, records, { empty_lines }) => { + empty_lines.should.eql(0); + next(); + }); + }); + + it("no empty lines", function (next) { + parse("a,b,c\nd,e,f", (err, records, { empty_lines }) => { + empty_lines.should.eql(0); + next(); + }); + }); + + it("one line in the middle of dataset", function (next) { + parse( + "a,b,c\n\nd,e,f", + { + skip_empty_lines: true, + }, + (err, records, { empty_lines }) => { + empty_lines.should.eql(1); + next(); + }, + ); + }); + + it("one line at the end of dataset", function (next) { + parse("a,b,c\nd,e,f\n", (err, records, { empty_lines }) => { + empty_lines.should.eql(1); + next(); + }); + }); + + it("dont count empty lines when empty and skip_empty_lines disabled", function (next) { + parse("\na,b,c\nd,e,f", (err, records, { empty_lines }) => { + err.message.should.eql( + "Invalid Record Length: expect 1, got 3 on line 2", + ); + empty_lines.should.eql(0); + next(); + }); + }); + + it("dont count commented lines", function (next) { + parse("a,b,c\nd,e,f\n# comment", (err, records, { empty_lines }) => { + empty_lines.should.eql(0); + next(); + }); + }); +}); diff --git a/packages/csv-parse/test/info.invalid_field_length.coffee b/packages/csv-parse/test/info.invalid_field_length.coffee deleted file mode 100644 index 334e82d9d..000000000 --- a/packages/csv-parse/test/info.invalid_field_length.coffee +++ /dev/null @@ -1,33 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'info invalid_field_length', -> - - it 'with relax_column_count', (next) -> - parse ''' - a,b,c - d,e - f,g,h - i,j - ''', - relax_column_count: true - , (err, records, {invalid_field_length}) -> - records.length.should.eql 4 - invalid_field_length.should.eql 2 - next() - - it 'with relax_column_count and skip_empty_lines', (next) -> - parser = parse ''' - a,b,c - - d,e,f - - h,i - ''', - relax_column_count: true - skip_empty_lines: true - , (err, data, {empty_lines, invalid_field_length, records})-> - empty_lines.should.eql 2 - invalid_field_length.should.eql 1 - records.should.eql 3 - next() diff --git a/packages/csv-parse/test/info.invalid_field_length.js b/packages/csv-parse/test/info.invalid_field_length.js new file mode 100644 index 000000000..f48e594ff --- /dev/null +++ b/packages/csv-parse/test/info.invalid_field_length.js @@ -0,0 +1,34 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("info invalid_field_length", function () { + it("with relax_column_count", function (next) { + parse( + "a,b,c\nd,e\nf,g,h\ni,j", + { + relax_column_count: true, + }, + (err, records, { invalid_field_length }) => { + records.length.should.eql(4); + invalid_field_length.should.eql(2); + next(); + }, + ); + }); + + it("with relax_column_count and skip_empty_lines", function (next) { + parse( + "a,b,c\n\nd,e,f\n\nh,i", + { + relax_column_count: true, + skip_empty_lines: true, + }, + (err, data, { empty_lines, invalid_field_length, records }) => { + empty_lines.should.eql(2); + invalid_field_length.should.eql(1); + records.should.eql(3); + next(); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/info.lines.coffee b/packages/csv-parse/test/info.lines.coffee deleted file mode 100644 index c836fa460..000000000 --- a/packages/csv-parse/test/info.lines.coffee +++ /dev/null @@ -1,108 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'properties lines', -> - - it 'count lines', (next) -> - p = parse """ - a,b,c - d,e,f - h,i,j - """, (err) -> - p.info.lines.should.eql 3 unless err - next err - - it 'count no line', (next) -> - p = parse "", (err) -> - p.info.lines.should.eql 1 unless err - next err - - it 'count empty lines', (next) -> - p = parse "\n\n", (err) -> - p.info.lines.should.eql 3 unless err - next err - - it 'should count sparse empty lines', (next) -> - p = parse """ - - a,b,c - - d,e,f - h,i,j - - """, skip_empty_lines: true, (err) -> - p.info.lines.should.eql 6 unless err - next err - - it 'should display correct line number when invalid opening quotes', (next) -> - parse """ - "this","line","is",valid - "this","line",is,"also,valid" - this,"line",is,"invalid",h"ere" - "and",valid,line,follows... - """, (err, records) -> - assert_error err, - message: 'Invalid Opening Quote: a quote is found on field 4 at line 3, value is "h"' - code: 'INVALID_OPENING_QUOTE' - field: 'h' - (records == undefined).should.be.true - next() - - it 'should count empty lines with "skip_empty_lines" true', (next) -> - parse """ - "this","line","is",valid - - "this","line",is,"also,valid" - this,"line",is,invalid h"ere" - "and",valid,line,follows... - """, skip_empty_lines: true, (err, records) -> - assert_error err, - message: 'Invalid Opening Quote: a quote is found on field 3 at line 4, value is "invalid h"' - code: 'INVALID_OPENING_QUOTE' - field: 'invalid h' - (records == undefined).should.be.true - next() - - it 'should display correct line number when unclosed quotes', (next) -> - parse """ - "",1974,8.8392926E7,"","" - "",1974,8.8392926E7,"","" - "",1974,8.8392926E7,"","" - "",1974,8.8392926E7,""," - "",1974,8.8392926E7,"","" - """, (err, records) -> - assert_error err, - message: 'Quote Not Closed: the parsing is finished with an opening quote at line 5' - code: 'CSV_QUOTE_NOT_CLOSED' - (records == undefined).should.be.true - next() - - it 'should display correct line number when invalid quotes', (next) -> - parse """ - " 1974 8.8392926E7 ""t " - " 1974 8.8392926E7 ""t " - "" 1974 8.8392926E7 ""t "" - " 1974 8.8392926E7 ""t " - " 1974 8.8392926E7 "t "" - """, quote: '"', escape: '"', delimiter: "\t", (err, records) -> - assert_error err, - message: 'Invalid Closing Quote: got " " at line 3 instead of delimiter, record delimiter, trimable character (if activated) or comment' - code: 'CSV_INVALID_CLOSING_QUOTE' - (records == undefined).should.be.true - next() - - it 'should display correct line number when invalid quotes from string', (next) -> - parse """ - "",1974,8.8392926E7,"","" - "",1974,8.8392926E7,""t,"" - "",1974,8.8392926E7,""t,"" - "",1974,8.8392926E7,"","" - "",1974,8.8392926E7,"","" - "",1974,8.8392926E7,""t,"" - """, quote: '"', escape: '"', (err, records) -> - assert_error err, - message: 'Invalid Closing Quote: got "t" at line 2 instead of delimiter, record delimiter, trimable character (if activated) or comment' - code: 'CSV_INVALID_CLOSING_QUOTE' - (records == undefined).should.be.true - next() diff --git a/packages/csv-parse/test/info.lines.ts b/packages/csv-parse/test/info.lines.ts new file mode 100644 index 000000000..6ed28469e --- /dev/null +++ b/packages/csv-parse/test/info.lines.ts @@ -0,0 +1,164 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; + +describe("info lines", function () { + it("count lines", function (next) { + const p = parse("a,b,c\nd,e,f\nh,i,j", (err) => { + if (!err) p.info.lines.should.eql(3); + next(err); + }); + }); + + it("count no line", function (next) { + const p = parse("", (err) => { + if (!err) p.info.lines.should.eql(1); + next(err); + }); + }); + + it("count empty lines", function (next) { + const p = parse("\n\n", (err) => { + if (!err) p.info.lines.should.eql(3); + next(err); + }); + }); + + it("should count sparse empty lines", function (next) { + const p = parse( + "\na,b,c\n\nd,e,f\nh,i,j\n", + { + skip_empty_lines: true, + }, + (err) => { + if (!err) p.info.lines.should.eql(6); + next(err); + }, + ); + }); + + it("should display correct line number when invalid opening quotes", function (next) { + parse( + dedent` + "this","line","is",valid + "this","line",is,"also,valid" + this,"line",is,"invalid",h"ere" + "and",valid,line,follows... + `, + (err, records) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + 'Invalid Opening Quote: a quote is found on field 4 at line 3, value is "h"', + code: "INVALID_OPENING_QUOTE", + field: "h", + }); + (records == undefined).should.be.true(); + next(); + }, + ); + }); + + it('should count empty lines with "skip_empty_lines" true', function (next) { + parse( + dedent` + "this","line","is",valid + + "this","line",is,"also,valid" + this,"line",is,invalid h"ere" + "and",valid,line,follows... + `, + { + skip_empty_lines: true, + }, + (err, records) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + 'Invalid Opening Quote: a quote is found on field 3 at line 4, value is "invalid h"', + code: "INVALID_OPENING_QUOTE", + field: "invalid h", + }); + (records == undefined).should.be.true(); + next(); + }, + ); + }); + + it("should display correct line number when unclosed quotes", function (next) { + parse( + dedent` + "",1974,8.8392926E7,"","" + "",1974,8.8392926E7,"","" + "",1974,8.8392926E7,"","" + "",1974,8.8392926E7,""," + "",1974,8.8392926E7,"","" + `, + (err, records) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + "Quote Not Closed: the parsing is finished with an opening quote at line 5", + code: "CSV_QUOTE_NOT_CLOSED", + }); + (records == undefined).should.be.true(); + next(); + }, + ); + }); + + it("should display correct line number when invalid quotes", function (next) { + parse( + dedent` + " 1974 8.8392926E7 ""t " + " 1974 8.8392926E7 ""t " + "" 1974 8.8392926E7 ""t "" + " 1974 8.8392926E7 ""t " + " 1974 8.8392926E7 "t "" + `, + { + quote: '"', + escape: '"', + delimiter: "\t", + }, + (err, records) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + 'Invalid Closing Quote: got " " at line 3 instead of delimiter, record delimiter, trimable character (if activated) or comment', + code: "CSV_INVALID_CLOSING_QUOTE", + }); + (records == undefined).should.be.true(); + next(); + }, + ); + }); + + it("should display correct line number when invalid quotes from string", function (next) { + parse( + dedent` + "",1974,8.8392926E7,"","" + "",1974,8.8392926E7,""t,"" + "",1974,8.8392926E7,""t,"" + "",1974,8.8392926E7,"","" + "",1974,8.8392926E7,"","" + "",1974,8.8392926E7,""t,"" + `, + { + quote: '"', + escape: '"', + }, + (err, records) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + 'Invalid Closing Quote: got "t" at line 2 instead of delimiter, record delimiter, trimable character (if activated) or comment', + code: "CSV_INVALID_CLOSING_QUOTE", + }); + (records == undefined).should.be.true(); + next(); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/info.records.coffee b/packages/csv-parse/test/info.records.coffee deleted file mode 100644 index 9c66903b1..000000000 --- a/packages/csv-parse/test/info.records.coffee +++ /dev/null @@ -1,25 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'properties count records', -> - - it 'without any options', (next) -> - parser = parse """ - a,b,c - d,e,f - g,h,i - """, (err) -> - parser.info.records.should.eql 3 unless err - next err - - it 'with "column" option', (next) -> - parser = parse """ - 1,2,3 - d,e,f - g,h,i - j,k,l - m,n,o - """, columns: true, (err) -> - parser.info.records.should.eql 4 unless err - next err - diff --git a/packages/csv-parse/test/info.records.js b/packages/csv-parse/test/info.records.js new file mode 100644 index 000000000..8886ba666 --- /dev/null +++ b/packages/csv-parse/test/info.records.js @@ -0,0 +1,38 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; + +describe("info count records", function () { + it("without any options", function (next) { + const parser = parse( + dedent` + a,b,c + d,e,f + g,h,i + `, + (err) => { + if (!err) parser.info.records.should.eql(3); + next(err); + }, + ); + }); + + it('with "column" option', function (next) { + const parser = parse( + dedent` + 1,2,3 + d,e,f + g,h,i + j,k,l + m,n,o + `, + { + columns: true, + }, + (err) => { + if (!err) parser.info.records.should.eql(4); + next(err); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/loaders/all.js b/packages/csv-parse/test/loaders/all.js deleted file mode 100644 index 4e81c3449..000000000 --- a/packages/csv-parse/test/loaders/all.js +++ /dev/null @@ -1,15 +0,0 @@ -import * as coffee from "./coffee.js"; -import * as ts from "ts-node/esm"; - -const coffeeRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; -const tsRegex = /\.ts$/; - -export function load(url, context, next) { - if (coffeeRegex.test(url)) { - return coffee.load.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.load.apply(this, arguments); - } - return next(url, context, next); -} diff --git a/packages/csv-parse/test/loaders/coffee.js b/packages/csv-parse/test/loaders/coffee.js deleted file mode 100644 index 75b15abe0..000000000 --- a/packages/csv-parse/test/loaders/coffee.js +++ /dev/null @@ -1,20 +0,0 @@ -import CoffeeScript from "coffeescript"; - -// See https://github.com/nodejs/node/issues/36396 -const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; - -export async function load(url, context, next) { - if (extensionsRegex.test(url)) { - const format = "module"; - const { source: rawSource } = await next(url, { format }); - const source = CoffeeScript.compile(rawSource.toString(), { - bare: true, - inlineMap: true, - filename: url, - header: false, - sourceMap: false, - }); - return { format, source }; - } - return next(url, context); -} diff --git a/packages/csv-parse/test/loaders/legacy/all.js b/packages/csv-parse/test/loaders/legacy/all.js deleted file mode 100644 index f5e57e542..000000000 --- a/packages/csv-parse/test/loaders/legacy/all.js +++ /dev/null @@ -1,36 +0,0 @@ -import * as coffee from "./coffee.js"; -import * as ts from "ts-node/esm"; - -const coffeeRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; -const tsRegex = /\.ts$/; - -export function resolve(specifier) { - if (coffeeRegex.test(specifier)) { - return coffee.resolve.apply(this, arguments); - } - if (tsRegex.test(specifier)) { - return ts.resolve.apply(this, arguments); - } - return ts.resolve.apply(this, arguments); -} - -export function getFormat(url) { - if (coffeeRegex.test(url)) { - return coffee.getFormat.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.getFormat.apply(this, arguments); - } - return ts.getFormat.apply(this, arguments); -} - -export function transformSource(source, context) { - const { url } = context; - if (coffeeRegex.test(url)) { - return coffee.transformSource.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.transformSource.apply(this, arguments); - } - return ts.transformSource.apply(this, arguments); -} diff --git a/packages/csv-parse/test/loaders/legacy/coffee.js b/packages/csv-parse/test/loaders/legacy/coffee.js deleted file mode 100644 index 6a9975db9..000000000 --- a/packages/csv-parse/test/loaders/legacy/coffee.js +++ /dev/null @@ -1,50 +0,0 @@ -// coffeescript-loader.mjs -import { URL, pathToFileURL } from "url"; -import CoffeeScript from "coffeescript"; -import { cwd } from "process"; - -const baseURL = pathToFileURL(`${cwd()}/`).href; - -// CoffeeScript files end in .coffee, .litcoffee or .coffee.md. -const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; - -export function resolve(specifier, context, defaultResolve) { - const { parentURL = baseURL } = context; - // Node.js normally errors on unknown file extensions, so return a URL for - // specifiers ending in the CoffeeScript file extensions. - if (extensionsRegex.test(specifier)) { - return { - url: new URL(specifier, parentURL).href, - stop: true, - }; - } - // Let Node.js handle all other specifiers. - return defaultResolve(specifier, context, defaultResolve); -} - -export function getFormat(url, context, defaultGetFormat) { - // Now that we patched resolve to let CoffeeScript URLs through, we need to - // tell Node.js what format such URLs should be interpreted as. For the - // purposes of this loader, all CoffeeScript URLs are ES modules. - if (extensionsRegex.test(url)) { - return { - format: "module", - stop: true, - }; - } - // Let Node.js handle all other URLs. - return defaultGetFormat(url, context, defaultGetFormat); -} - -export function transformSource(source, context, defaultTransformSource) { - const { url } = context; - - if (extensionsRegex.test(url)) { - return { - source: CoffeeScript.compile(String(source), { bare: true }), - }; - } - - // Let Node.js handle all other sources. - return defaultTransformSource(source, context, defaultTransformSource); -} diff --git a/packages/csv-parse/test/option.bom.coffee b/packages/csv-parse/test/option.bom.coffee deleted file mode 100644 index 938b3af4b..000000000 --- a/packages/csv-parse/test/option.bom.coffee +++ /dev/null @@ -1,110 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'Option `bom`', -> - - it 'validate', -> - (-> - parse bom: 'ohno', ( -> ) - ).should.throw - message: 'Invalid option bom: bom must be true, got "ohno"' - code: 'CSV_INVALID_OPTION_BOM' - - it 'preserve bom if not defined', (next) -> - parser = parse (err, records) -> - records.should.eql [ - ['\ufeffa', 'b', 'c'] - ['d', 'e', 'f'] - ] - next() - parser.write Buffer.from "\ufeffa,b,c\n" - parser.write Buffer.from 'd,e,f' - parser.end() - - it 'preserve BOM if false', (next) -> - parser = parse bom: false, (err, records) -> - records.should.eql [ - ['\ufeffa', 'b', 'c'] - ['d', 'e', 'f'] - ] - next() - parser.write Buffer.from "\ufeffa,b,c\n" - parser.write Buffer.from 'd,e,f' - parser.end() - - it 'with column option with bom `true`', (next) -> - parser = parse - columns: true - bom: true - , (err, records) -> - records[0]['key'].should.eql 'value' - next() - parser.write Buffer.from "\ufeffkey\nvalue" - parser.end() - - it 'with column option with bom `false`', (next) -> - parser = parse - columns: true - bom: false - , (err, records) -> - records[0]['\ufeffkey'].should.eql 'value' - next() - parser.write Buffer.from "\ufeffkey\nvalue" - parser.end() - - it 'throw parsing error if quote follow bom', (next) -> - parser = parse (err) -> - assert_error err, - message: 'Invalid Opening Quote: a quote is found on field 0 at line 1, value is "\ufeff" (utf8 bom)' - code: 'INVALID_OPENING_QUOTE' - field: '\ufeff' - next() - parser.write Buffer.from "\ufeff\"a\",b,c\n" - parser.write Buffer.from 'd,e,f' - parser.end() - - it 'handle BOM with utf8 (default)', (next) -> - parser = parse bom: true, (err, records) -> - records.should.eql [ - ['a', 'b', 'c'] - ['d', 'e', 'f'] - ] - next() - parser.write Buffer.from "\ufeffa,b,c\n" - parser.write Buffer.from 'd,e,f' - parser.end() - - it 'preserve data if BOM is true', (next) -> - parser = parse bom: true, (err, records) -> - records.should.eql [ - ['a', 'b', 'c'] - ['d', 'e', 'f'] - ] - next() - parser.write Buffer.from "a,b,c\n" - parser.write Buffer.from 'd,e,f' - parser.end() - - it 'handle BOM even if no enough data in the first package', (next) -> - parser = parse bom: true, (err, records) -> - records.should.eql [ - ['a', 'b', 'c'] - ['d', 'e', 'f'] - ] - next() - parser.write Buffer.from [239] - parser.write Buffer.from [187] - parser.write Buffer.from [191] - parser.write Buffer.from "a,b,c\n" - parser.write Buffer.from "d,e,f" - parser.end() - - it 'preserve data if no enough data to detect BOM', (next) -> - parser = parse bom: true, (err, records) -> - records.should.eql [ - ['\ufffd'] - ] - next() - parser.write Buffer.from [239, 187] - parser.end() diff --git a/packages/csv-parse/test/option.bom.js b/packages/csv-parse/test/option.bom.js new file mode 100644 index 000000000..1c9638d74 --- /dev/null +++ b/packages/csv-parse/test/option.bom.js @@ -0,0 +1,13 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `bom`", function () { + it("validate", function () { + (() => { + parse({ bom: "ohno" }, () => {}); + }).should.throw({ + message: 'Invalid option bom: bom must be true, got "ohno"', + code: "CSV_INVALID_OPTION_BOM", + }); + }); +}); diff --git a/packages/csv-parse/test/option.bom.ts b/packages/csv-parse/test/option.bom.ts new file mode 100644 index 000000000..c831a9e78 --- /dev/null +++ b/packages/csv-parse/test/option.bom.ts @@ -0,0 +1,144 @@ +import "should"; +import { parse } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; + +describe("Option `bom`", function () { + it("preserve bom if not defined", function (next) { + const parser = parse((err, records) => { + records.should.eql([ + ["\ufeffa", "b", "c"], + ["d", "e", "f"], + ]); + next(); + }); + parser.write(Buffer.from("\ufeffa,b,c\n")); + parser.write(Buffer.from("d,e,f")); + parser.end(); + }); + + it("preserve BOM if false", function (next) { + const parser = parse({ bom: false }, (err, records) => { + records.should.eql([ + ["\ufeffa", "b", "c"], + ["d", "e", "f"], + ]); + next(); + }); + parser.write(Buffer.from("\ufeffa,b,c\n")); + parser.write(Buffer.from("d,e,f")); + parser.end(); + }); + + it("with column option with bom `true`", function (next) { + const parser = parse( + { + columns: true, + bom: true, + }, + (err, records) => { + const record = records[0] as { key: string }; + record["key"].should.eql("value"); + next(); + }, + ); + parser.write(Buffer.from("\ufeffkey\nvalue")); + parser.end(); + }); + + it("with column option with bom `false`", function (next) { + const parser = parse( + { + columns: true, + bom: false, + }, + (err, records) => { + const record = records[0] as { "\ufeffkey": string }; + record["\ufeffkey"].should.eql("value"); + next(); + }, + ); + parser.write(Buffer.from("\ufeffkey\nvalue")); + parser.end(); + }); + + it("throw parsing error if quote follow bom", function (next) { + const parser = parse((err) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + 'Invalid Opening Quote: a quote is found on field 0 at line 1, value is "\ufeff" (utf8 bom)', + code: "INVALID_OPENING_QUOTE", + field: "\ufeff", + }); + next(); + }); + parser.write(Buffer.from('\ufeff"a",b,c\n')); + parser.write(Buffer.from("d,e,f")); + parser.end(); + }); + + it("handle BOM with utf8 (default)", function (next) { + const parser = parse({ bom: true }, (err, records) => { + records.should.eql([ + ["a", "b", "c"], + ["d", "e", "f"], + ]); + next(); + }); + parser.write(Buffer.from("\ufeffa,b,c\n")); + parser.write(Buffer.from("d,e,f")); + parser.end(); + }); + + it("preserve data if BOM is true", function (next) { + const parser = parse({ bom: true }, (err, records) => { + records.should.eql([ + ["a", "b", "c"], + ["d", "e", "f"], + ]); + next(); + }); + parser.write(Buffer.from("a,b,c\n")); + parser.write(Buffer.from("d,e,f")); + parser.end(); + }); + + it("handle BOM even if no enough data in the first package", function (next) { + const parser = parse({ bom: true }, (err, records) => { + records.should.eql([ + ["a", "b", "c"], + ["d", "e", "f"], + ]); + next(); + }); + parser.write(Buffer.from([239])); + parser.write(Buffer.from([187])); + parser.write(Buffer.from([191])); + parser.write(Buffer.from("a,b,c\n")); + parser.write(Buffer.from("d,e,f")); + parser.end(); + }); + + it("preserve data if no enough data to detect BOM", function (next) { + const parser = parse({ bom: true }, (err, records) => { + records.should.eql([["\ufffd"]]); + next(); + }); + parser.write(Buffer.from([239, 187])); + parser.end(); + }); + + it("options instance is updated and not re-created (see #460)", async function () { + // https://github.com/adaltas/node-csv/issues/460 + const parser = parse({ + columns: true, + bom: true, + from_line: 2, + }); + parser.write(Buffer.from("\ufeffa,b\n")); + parser.write(Buffer.from("1,2\n")); + parser.write(Buffer.from("3,4\n")); + parser.end(); + parser.options?.columns.should.eql([{ name: "1" }, { name: "2" }]); + }); +}); diff --git a/packages/csv-parse/test/option.cast.coffee b/packages/csv-parse/test/option.cast.coffee deleted file mode 100644 index d83c7a33c..000000000 --- a/packages/csv-parse/test/option.cast.coffee +++ /dev/null @@ -1,289 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'Option `cast`', -> - - it 'validate', -> - (-> - parse cast: 'ohno', ( -> ) - ).should.throw - message: 'Invalid option cast: cast must be true or a function, got "ohno"' - code: 'CSV_INVALID_OPTION_CAST' - - describe 'boolean true', -> - - it 'all columns', (next) -> - parse '1,2,3', cast: true, (err, records) -> - records.should.eql [ [1, 2, 3] ] unless err - next() - - it 'convert numbers', (next) -> - records = [] - parser = parse({ cast: true }) - parser.write """ - 20322051544,1979,8.8017226E7,8e2,ABC,45,2000-01-01 - 28392898392,1974,8.8392926e7,8E2,DEF,23,2050-11-27 - """ - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'error', (err) -> - next err - parser.on 'end', -> - records.should.eql [ - [20322051544, 1979, 8.8017226e7, 800, 'ABC', 45, '2000-01-01'] - [28392898392, 1974, 8.8392926e7, 800, 'DEF', 23, '2050-11-27'] - ] - next() - parser.end() - - it 'ints', (next) -> - parse '123a,123,+123,-123,0123,+0123,-0123,', cast: true, (err, records) -> - records.should.eql [ ['123a', 123, 123, -123, 123, 123, -123, ''] ] - next() - - it 'ints isnt exposed to DOS vulnerabilities, npm security issue 69742', (next) -> - data = Array.from( length: 3000000 ).map( (x) -> '1' ).join('') + '!' - parse data, cast: true, (err, records) -> - records[0][0].length.should.eql 3000001 - next() - - it 'float', (next) -> - parse '123a,1.23,0.123,01.23,.123,123.', cast: true, (err, records) -> - records.should.eql [ ['123a', 1.23, 0.123, 1.23, 0.123, 123] ] - next() - - describe 'function', -> - - it 'custom function', (next) -> - parse """ - hello - """, - cast: (value, context) -> - Object.keys(context).sort() - , (err, records) -> - records.should.eql [ - [[ - 'bytes', - 'column', 'columns', 'comment_lines', 'empty_lines', 'error', - 'header', 'index', 'invalid_field_length', 'lines', 'quoting', - 'raw', 'records' - ]] - ] unless err - next err - - it 'return anything, eg a string or an object', (next) -> - parse """ - 2000-01-01,date1 - 2050-11-27,date2 - """, - cast: (value, context) -> - if context.index is 0 - then "#{value}T05:00:00.000Z" - else {...context} - , (err, records) -> - records.should.eql [ - [ '2000-01-01T05:00:00.000Z', { - bytes: 16, - column: 1, columns: false, comment_lines: 0, empty_lines: 0, error: undefined, - header: false, index: 1, invalid_field_length: 0, lines: 1, - quoting: false, raw: undefined, records: 0 - } ] - [ '2050-11-27T05:00:00.000Z', { - bytes: 33, - column: 1, columns: false, comment_lines: 0, empty_lines: 0, error: undefined, - header: false, index: 1, invalid_field_length: 0, lines: 2, - quoting: false, raw: undefined, records: 1 - } ] - ] unless err - next err - - it 'column is a string', (next) -> - parse """ - 1,2 - 3,4,5 - 6 - """, - columns: ['a', 'b'] - relax_column_count: true - cast: (value, {header, column}) -> - typeof column - , (err, records) -> - records.should.eql [ - {a: 'string', b: 'string'} - {a: 'string', b: 'string'} - {a: 'string'} - ] unless err - next err - - it 'dont call cast on unreferenced columns', (next) -> - # It doesn't make sense to cast value which cannot later be assigned - # to a column name in the returned object - parse """ - 1,2 - 3,4,5,6 - 7 - """, - columns: ['a', 'b'] - relax_column_count: true - cast: (value, {column}) -> - throw Error 'Oh no' if value > 4 and value < 7 - , (err, records) -> - next err - - it 'custom function with quoting context', (next) -> - parse """ - "2000-01-01",date1 - 2025-12-31,"date2" - 2050-11-27,"date3" - """, - cast: (value, {quoting}) -> - quoting - , (err, records) -> - records.should.eql [ - [ true, false ] - [ false, true ] - [ false, true ] - ] unless err - next err - - it 'return undefined', -> - - it 'accept all values', (next) -> - parse """ - 1,2,3 - 4,5,6 - """, - max_record_size: 10 - cast: (value, {index}) -> - switch index - when 0 - undefined - when 1 - false - when 2 - null - , (err, records) -> - records.shift().should.eql [undefined, false, null] - next err - - describe 'columns', -> - - it 'header is true on first line when columns is true', (next) -> - parse """ - a,b,c - 1,2,3 - 4,5,6 - """, - columns: true - cast: (value, {header}) -> - if header then value else parseInt value - , (err, records) -> - records.should.eql [ - {a: 1, b: 2, c: 3} - {a: 4, b: 5, c: 6} - ] unless err - next err - - it 'header is false when columns is an object', (next) -> - parse """ - 1,2,3 - 4,5,6 - """, - columns: ['a', 'b', 'c'] - cast: (value, {header}) -> - header.should.be.false() - parseInt value - , (err, records) -> - records.should.eql [ - {a: 1, b: 2, c: 3} - {a: 4, b: 5, c: 6} - ] unless err - next err - - it 'dont count header line', (next) -> - parse """ - a,b,c - 1,2,3 - 4,5,6 - """, - columns: true - cast: (value) -> - value - , (err, records) -> - next err - - it 'filter columns if value is undefined', (next) -> - parse """ - a,b,c,d - 1,2,3,4 - 5,6,7,8 - """, - columns: true, - cast: (value, context) -> - switch context.index - when 0 then if context.header then value else Number(value) - when 2 then value - else undefined - , (err, records) -> - records.should.eql [ - 'a': 1 - 'c': '3' - , - 'a': 5 - 'c': '7' - ] unless err - next err - - it 'throw error if header is invalid', (next) -> - parse """ - a,b,c,d - 1,2,3,4 - 5,6,7,8 - """, - columns: true, - cast: (value, context) -> - switch context.index - when 0 then if context.header then 'string' else value - when 1 then if context.header then undefined else value - when 2 then if context.header then null else value - when 3 then if context.header then 1234 else value - , (err) -> - assert_error err, - message: 'Invalid column definition: expect a string or a literal object, got 1234 at position 3' - code: 'CSV_INVALID_COLUMN_DEFINITION' - next() - - describe 'group_columns_by_name', -> - - it 'leading zeros are maintained when group_columns_by_name is true', (next) -> - parse """ - FIELD_1,FIELD_1,FIELD_1 - 0,2,3 - 0,0,4 - """, - cast: true - columns: true - group_columns_by_name: true - , (err, records) -> - records.should.eql [ - 'FIELD_1': [0, 2, 3] - , - 'FIELD_1': [0, 0, 4] - ] unless err - next err - - describe 'error', -> - - it 'catch error', (next) -> - parse """ - 1,2,3 - 4,5,6 - """, - cast: (value) -> - if value is '6' then throw Error 'Catchme' - value - , (err, records) -> - err.message.should.eql 'Catchme' - next() diff --git a/packages/csv-parse/test/option.cast.js b/packages/csv-parse/test/option.cast.js new file mode 100644 index 000000000..c172e136c --- /dev/null +++ b/packages/csv-parse/test/option.cast.js @@ -0,0 +1,14 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `cast`", function () { + it("validate", function () { + (() => { + parse({ cast: "ohno" }, () => {}); + }).should.throw({ + message: + 'Invalid option cast: cast must be true or a function, got "ohno"', + code: "CSV_INVALID_OPTION_CAST", + }); + }); +}); diff --git a/packages/csv-parse/test/option.cast.ts b/packages/csv-parse/test/option.cast.ts new file mode 100644 index 000000000..c435daede --- /dev/null +++ b/packages/csv-parse/test/option.cast.ts @@ -0,0 +1,400 @@ +import "should"; +import { parse } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; + +describe("Option `cast`", function () { + describe("boolean true", function () { + it("all columns", function (next) { + parse("1,2,3", { cast: true }, (err, records) => { + if (!err) records.should.eql([[1, 2, 3]]); + next(); + }); + }); + + it("convert numbers", function (next) { + const records: string[] = []; + const parser = parse({ cast: true }); + parser.write( + "20322051544,1979,8.8017226E7,8e2,ABC,45,2000-01-01\n28392898392,1974,8.8392926e7,8E2,DEF,23,2050-11-27", + ); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("error", (err) => { + next(err); + }); + parser.on("end", () => { + records.should.eql([ + [20322051544, 1979, 8.8017226e7, 800, "ABC", 45, "2000-01-01"], + [28392898392, 1974, 8.8392926e7, 800, "DEF", 23, "2050-11-27"], + ]); + next(); + }); + parser.end(); + }); + + it("ints", function (next) { + parse( + "123a,123,+123,-123,0123,+0123,-0123,", + { cast: true }, + (err, records) => { + records.should.eql([["123a", 123, 123, -123, 123, 123, -123, ""]]); + next(); + }, + ); + }); + + it("ints isnt exposed to DOS vulnerabilities, npm security issue 69742", function (next) { + const data = + Array.from({ length: 3000000 }) + .map(() => "1") + .join("") + "!"; + parse(data, { cast: true }, (err, records) => { + records[0][0].length.should.eql(3000001); + next(); + }); + }); + + it("float", function (next) { + parse( + "123a,1.23,0.123,01.23,.123,123.", + { cast: true }, + (err, records) => { + records.should.eql([["123a", 1.23, 0.123, 1.23, 0.123, 123]]); + next(); + }, + ); + }); + }); + + describe("function", function () { + it("custom function", function (next) { + parse( + "hello", + { + cast: (value, context) => Object.keys(context).sort(), + }, + (err, records) => { + if (!err) { + records.should.eql([ + [ + [ + "bytes", + "column", + "columns", + "comment_lines", + "empty_lines", + "error", + "header", + "index", + "invalid_field_length", + "lines", + "quoting", + "raw", + "records", + ], + ], + ]); + } + next(err); + }, + ); + }); + + it("return anything, eg a string or an object", function (next) { + parse( + "2000-01-01,date1\n2050-11-27,date2", + { + cast: (value, context) => { + if (context.index === 0) { + return `${value}T05:00:00.000Z`; + } else { + return { ...context }; + } + }, + }, + (err, records) => { + if (!err) { + records.should.eql([ + [ + "2000-01-01T05:00:00.000Z", + { + bytes: 16, + column: 1, + columns: false, + comment_lines: 0, + empty_lines: 0, + error: undefined, + header: false, + index: 1, + invalid_field_length: 0, + lines: 1, + quoting: false, + raw: undefined, + records: 0, + }, + ], + [ + "2050-11-27T05:00:00.000Z", + { + bytes: 33, + column: 1, + columns: false, + comment_lines: 0, + empty_lines: 0, + error: undefined, + header: false, + index: 1, + invalid_field_length: 0, + lines: 2, + quoting: false, + raw: undefined, + records: 1, + }, + ], + ]); + } + next(err); + }, + ); + }); + + it("column is a string", function (next) { + parse( + "1,2\n3,4,5\n6", + { + columns: ["a", "b"], + relax_column_count: true, + cast: (value, { column }) => typeof column, + }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: "string", b: "string" }, + { a: "string", b: "string" }, + { a: "string" }, + ]); + } + next(err); + }, + ); + }); + + it("dont call cast on unreferenced columns", function (next) { + parse( + "1,2\n3,4,5,6\n7", + { + columns: ["a", "b"], + relax_column_count: true, + cast: (value) => { + const valueInt = parseInt(value); + if (valueInt > 4 && valueInt < 7) throw Error("Oh no"); + }, + }, + (err) => { + next(err); + }, + ); + }); + + it("custom function with quoting context", function (next) { + parse( + '"2000-01-01",date1\n2025-12-31,"date2"\n2050-11-27,"date3"', + { + cast: (value, { quoting }) => quoting, + }, + (err, records) => { + if (!err) { + records.should.eql([ + [true, false], + [false, true], + [false, true], + ]); + } + next(err); + }, + ); + }); + + it("accept all values", function (next) { + parse( + "1,2,3\n4,5,6", + { + max_record_size: 10, + cast: (value, { index }) => { + switch (index) { + case 0: + return undefined; + case 1: + return false; + case 2: + return null; + } + }, + }, + (err, records) => { + records.shift()?.should.eql([undefined, false, null]); + next(err); + }, + ); + }); + }); + + describe("columns", function () { + it("header is true on first line when columns is true", function (next) { + parse( + "a,b,c\n1,2,3\n4,5,6", + { + columns: true, + cast: (value, { header }) => (header ? value : parseInt(value)), + }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: 1, b: 2, c: 3 }, + { a: 4, b: 5, c: 6 }, + ]); + } + next(err); + }, + ); + }); + + it("header is false when columns is an object", function (next) { + parse( + "1,2,3\n4,5,6", + { + columns: ["a", "b", "c"], + cast: (value, { header }) => { + header.should.be.false(); + return parseInt(value); + }, + }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: 1, b: 2, c: 3 }, + { a: 4, b: 5, c: 6 }, + ]); + } + next(err); + }, + ); + }); + + it("dont count header line", function (next) { + parse( + "a,b,c\n1,2,3\n4,5,6", + { + columns: true, + cast: (value) => value, + }, + (err) => { + next(err); + }, + ); + }); + + it("filter columns if value is undefined", function (next) { + parse( + "a,b,c,d\n1,2,3,4\n5,6,7,8", + { + columns: true, + cast: (value, context) => { + switch (context.index) { + case 0: + return context.header ? value : Number(value); + case 2: + return value; + default: + return undefined; + } + }, + }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: 1, c: "3" }, + { a: 5, c: "7" }, + ]); + } + next(err); + }, + ); + }); + + it("throw error if header is invalid", function (next) { + parse( + "a,b,c,d\n1,2,3,4\n5,6,7,8", + { + columns: true, + cast: (value, context) => { + switch (context.index) { + case 0: + return context.header ? "string" : value; + case 1: + return context.header ? undefined : value; + case 2: + return context.header ? null : value; + case 3: + return context.header ? 1234 : value; + } + }, + }, + (err) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + "Invalid column definition: expect a string or a literal object, got 1234 at position 3", + code: "CSV_INVALID_COLUMN_DEFINITION", + }); + next(); + }, + ); + }); + }); + + describe("group_columns_by_name", function () { + it("leading zeros are maintained when group_columns_by_name is true", function (next) { + parse( + "FIELD_1,FIELD_1,FIELD_1\n0,2,3\n0,0,4", + { + cast: true, + columns: true, + group_columns_by_name: true, + }, + (err, records) => { + if (!err) { + records.should.eql([ + { FIELD_1: [0, 2, 3] }, + { FIELD_1: [0, 0, 4] }, + ]); + } + next(err); + }, + ); + }); + }); + + describe("error", function () { + it("catch error", function (next) { + parse( + "1,2,3\n4,5,6", + { + cast: (value) => { + if (value === "6") throw Error("Catchme"); + return value; + }, + }, + (err) => { + if (!err) return next(Error("Invalid assessment")); + err.message.should.eql("Catchme"); + next(); + }, + ); + }); + }); +}); diff --git a/packages/csv-parse/test/option.cast_date.coffee b/packages/csv-parse/test/option.cast_date.coffee deleted file mode 100644 index ccabd8505..000000000 --- a/packages/csv-parse/test/option.cast_date.coffee +++ /dev/null @@ -1,57 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'Option `cast_date`', -> - - it 'validate', -> - (-> - parse cast: true, cast_date: 'ohno', ( -> ) - ).should.throw - message: 'Invalid option cast_date: cast_date must be true or a function, got "ohno"' - code: 'CSV_INVALID_OPTION_CAST_DATE' - - it 'true', (next) -> - parser = parse """ - 2000-01-01,date1 - 2050-11-27,date2 - """, - cast: true - cast_date: true - , (err, records) -> - records.should.eql [ - [ new Date('2000-01-01T00:00:00.000Z'), 'date1' ], - [ new Date('2050-11-27T00:00:00.000Z'), 'date2' ] - ] - next err - - it 'as a function', (next) -> - # Current implementation rely on `isNaN(Date.parse(value))` - # While it return `NaN` in Firefox, Node.js return a timestamp for - # `Date.parse('Test 1')` - parser = parse """ - 2000-01-01 - 2050-11-27 - """, - cast: true - cast_date: (value, context) -> - new Date( (new Date(value)).getTime() + context.lines*60*60*1000) - , (err, records) -> - records.should.eql [ - [ new Date('2000-01-01T01:00:00.000Z') ], - [ new Date('2050-11-27T02:00:00.000Z') ] - ] - next err - - it 'value end with space and number (issue #342)', (next) -> - # Current implementation rely on `isNaN(Date.parse(value))` - # While it return `NaN` in Firefox, Node.js return a timestamp for - # `node -e 'console.info(Date.parse("Test 1"))'` - parser = parse """ - Test 1 - """, - cast: true - cast_date: true - , (err, [[record]]) -> - record.toISOString().should.match /^\d{4}-\d{2}-\d{2}/ - next err diff --git a/packages/csv-parse/test/option.cast_date.js b/packages/csv-parse/test/option.cast_date.js new file mode 100644 index 000000000..d1406a736 --- /dev/null +++ b/packages/csv-parse/test/option.cast_date.js @@ -0,0 +1,14 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `cast_date`", function () { + it("validate", function () { + (() => { + parse({ cast: true, cast_date: "ohno" }, () => {}); + }).should.throw({ + message: + 'Invalid option cast_date: cast_date must be true or a function, got "ohno"', + code: "CSV_INVALID_OPTION_CAST_DATE", + }); + }); +}); diff --git a/packages/csv-parse/test/option.cast_date.ts b/packages/csv-parse/test/option.cast_date.ts new file mode 100644 index 000000000..dac9b38b6 --- /dev/null +++ b/packages/csv-parse/test/option.cast_date.ts @@ -0,0 +1,64 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `cast_date`", function () { + it("true", function (next) { + parse( + "2000-01-01,date1\n2050-11-27,date2", + { + cast: true, + cast_date: true, + }, + (err, records) => { + records.should.eql([ + [new Date("2000-01-01T00:00:00.000Z"), "date1"], + [new Date("2050-11-27T00:00:00.000Z"), "date2"], + ]); + next(err); + }, + ); + }); + + it("as a function", function (next) { + // Current implementation rely on `isNaN(Date.parse(value))` + // While it return `NaN` in Firefox, Node.js return a timestamp for + // `Date.parse('Test 1')` + parse( + "2000-01-01\n2050-11-27", + { + cast: true, + cast_date: (value, context) => { + return new Date( + new Date(value).getTime() + context.lines * 60 * 60 * 1000, + ); + }, + }, + (err, records) => { + records.should.eql([ + [new Date("2000-01-01T01:00:00.000Z")], + [new Date("2050-11-27T02:00:00.000Z")], + ]); + next(err); + }, + ); + }); + + it("value end with space and number (issue #342)", function (next) { + // Current implementation rely on `isNaN(Date.parse(value))` + // While it return `NaN` in Firefox, Node.js return a timestamp for + // `node -e 'console.info(Date.parse("Test 1"))'` + parse( + "Test 1", + { + cast: true, + cast_date: true, + }, + (err, [[record]]) => { + (record as unknown as Date) + .toISOString() + .should.match(/^\d{4}-\d{2}-\d{2}/); + next(err); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/option.columns.coffee b/packages/csv-parse/test/option.columns.coffee deleted file mode 100644 index 24840d262..000000000 --- a/packages/csv-parse/test/option.columns.coffee +++ /dev/null @@ -1,331 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'Option `columns`', -> - - describe 'validation', -> - - it 'check the columns value', -> - (-> - parse "", columns: [{ - name: 'valid', - },{ - invalid: 'oh no' - }], (->) - ).should.throw - message: 'Option columns missing name: property "name" is required at position 1 when column is an object literal' - code: 'CSV_OPTION_COLUMNS_MISSING_NAME' - - it 'check the columns value', -> - (-> - parse "", columns: [{name: 'valid'}, true], (->) - ).should.throw - message: 'Invalid column definition: expect a string or a literal object, got true at position 1' - code: 'CSV_INVALID_COLUMN_DEFINITION' - - it 'check the columns value', -> - (-> - parse "", columns: {}, (->) - ).should.throw - message: 'Invalid option columns: expect an array, a function or true, got {}' - code: 'CSV_INVALID_OPTION_COLUMNS' - - it 'skip columns with false value', (next) -> - parse """ - 1,2,3,4 - 5,6,7,8 - """, columns: ["a", false, "c", false], (err, records) -> - records.should.eql [ - { a: "1", c: "3" } - { a: "5", c: "7" } - ] unless err - next err - - it 'dont mutate options', (next) -> - columns = ["a", false, "c", false] - parse """ - 1,2,3,4 - 5,6,7,8 - """, columns: columns, (err) -> - columns.should.eql ["a", false, "c", false] unless err - next err - - describe 'duplicate column names', -> - - it 'with true', (next) -> - parse ''' - a,b,a,c - 1,2,3,4 - 5,6,7,8 - ''', columns: true, (err, records) -> - records.should.eql [ - {a: '3', b: '2', c: '4'} - {a: '7', b: '6', c: '8'} - ] unless err - next err - - it 'with array', (next) -> - columns = ['a', 'b', 'a', 'c'] - parse ''' - 1,2,3,4 - 5,6,7,8 - ''', columns: columns, (err, records) -> - records.should.eql [ - {a: '3', b: '2', c: '4'} - {a: '7', b: '6', c: '8'} - ] unless err - next err - - it 'lines with empty column names', (next) -> - parse ''' - ,,, - 1,2,3,4 - 5,6,7,8 - ''', columns: true, (err, records) -> - records.should.eql [ - {'': '4'} - {'': '8'} - ] unless err - next err - - describe 'boolean', -> - - it 'read from first row if true', (next) -> - parse """ - FIELD_1,FIELD_2,FIELD_3,FIELD_4,FIELD_5,FIELD_6 - 20322051544,1979,8.8017226E7,ABC,45,2000-01-01 - 28392898392,1974,8.8392926E7,DEF,23,2050-11-27 - """, columns: true, (err, records) -> - records.should.eql [ - 'FIELD_1': '20322051544' - 'FIELD_2': '1979' - 'FIELD_3': '8.8017226E7' - 'FIELD_4': 'ABC' - 'FIELD_5': '45' - 'FIELD_6': '2000-01-01' - , - 'FIELD_1': '28392898392' - 'FIELD_2': '1974' - 'FIELD_3': '8.8392926E7' - 'FIELD_4': 'DEF' - 'FIELD_5': '23' - 'FIELD_6': '2050-11-27' - ] unless err - next err - - it 'disabled if false', (next) -> - parse """ - a,b,c - d,e,f - """, columns: false, (err, records) -> - records.should.eql [ - ['a', 'b', 'c'] - ['d', 'e', 'f'] - ] unless err - next err - - it 'header detection honors skip_empty_lines', (next) -> - parse """ - - a,b,c - 1,2,3 - """, columns: true, skip_empty_lines: true, (err, records) -> - records.should.eql [ - {a: "1", b: "2", c: "3"} - ] unless err - next err - - it 'header detection honors skip_records_with_empty_values', (next) -> - parse """ - ,, - a,b,c - 1,2,3 - """, columns: true, skip_records_with_empty_values: true, (err, records) -> - records.should.eql [ - {a: "1", b: "2", c: "3"} - ] unless err - next err - - describe 'array', -> - - it 'enforced by user if array', (next) -> - parse """ - 20322051544,1979,8.8017226E7,ABC,45,2000-01-01 - 28392898392,1974,8.8392926E7,DEF,23,2050-11-27 - """, columns: ["FIELD_1", "FIELD_2", "FIELD_3", "FIELD_4", "FIELD_5", "FIELD_6"], (err, records) -> - records.should.eql [ - "FIELD_1":"20322051544" - "FIELD_2":"1979" - "FIELD_3":"8.8017226E7" - "FIELD_4":"ABC" - "FIELD_5":"45" - "FIELD_6":"2000-01-01" - , - "FIELD_1":"28392898392" - "FIELD_2":"1974" - "FIELD_3":"8.8392926E7" - "FIELD_4":"DEF" - "FIELD_5":"23" - "FIELD_6":"2050-11-27" - ] unless err - next err - - it 'validate options column length on first line', (next) -> - parse """ - 1,2,3 - 4,5,6,x - 7,8,9,x - """, columns: ["a", "b", "c", "d"], (err) -> - assert_error err, - message: 'Invalid Record Length: columns length is 4, got 3 on line 1' - code: 'CSV_RECORD_INCONSISTENT_COLUMNS' - next() - - it 'validate options column length on last line', (next) -> - parse """ - 1,2,3,x - 4,5,6,x - 7,8,9 - """, columns: ["a", "b", "c", "d"], (err) -> - assert_error err, - message: 'Invalid Record Length: columns length is 4, got 3 on line 3' - code: 'CSV_RECORD_INCONSISTENT_COLUMNS' - next() - - it 'context column is null when cast force the context creation', (next) -> - # Trigger cast to force the creation of a context - parse "a\nb,\n", - columns: true - cast: (value) -> value - , (err) -> - assert_error err, - message: 'Invalid Record Length: columns length is 1, got 2 on line 2' - code: 'CSV_RECORD_INCONSISTENT_COLUMNS' - column: null - next() - - it 'context column is null when columns number inferieur to record length, fix regression #259', (next) -> - parse "a\nb,\n", columns: true, (err) -> - assert_error err, - message: 'Invalid Record Length: columns length is 1, got 2 on line 2' - code: 'CSV_RECORD_INCONSISTENT_COLUMNS' - column: null - next() - - it 'skips column names defined as undefined', (next) -> - parse """ - 0,1,2,3,4 - 5,6,7,8,9 - """, columns: ['a',,,, 'b'], (err, records) -> - records.should.eql [ - {a: '0', b: '4'} - {a: '5', b: '9'} - ] unless err - next err - - it 'skips column names defined as false', (next) -> - parse """ - 0,1,2,3,4 - 5,6,7,8,9 - """, columns: ['a',false,false,false, 'b'], (err, records) -> - records.should.eql [ - {a: '0', b: '4'} - {a: '5', b: '9'} - ] unless err - next err - - it 'skips column names defined as null and last', (next) -> - # Fix a but where error was not throw if columns empty count was equal to - # the number of column in the dataset plus one. - # It seems the bug is due to to JavaScript as - # `console.log(JSON.stringify([,,]))` - # report only 2 null values - parse """ - 0,1,2 - 3,4,5 - """, columns: ['a',null,null], (err, records) -> - records.should.eql [ - { a: '0' } - { a: '3' } - ] unless err - next err - - it 'illustrate bug with undefined values', (next) -> - # Be careful on how JavaScript handle multiple trailing commas as it - # will discard the last one. - # For exemple, `console.log(JSON.stringify([,,]))` report 2 null values - parse """ - 0,1,2 - 3,4,5 - """, columns: ['a',,,], (err, records) -> - records.should.eql [ - { a: '0' } - { a: '3' } - ] unless err - next err - - it 'last column value ignore when `null`', (next) -> - # Trigger a bug where error is try to stringify and parse an undefined - # value, conjointly triggered by a null column and a - # CSV_RECORD_INCONSISTENT_COLUMNS error - parse """ - col_a,col_b,col_c - foo,bar - foo,bar,baz - """ - , columns: ['a', 'b', null], (err) -> - err.code.should.eql 'CSV_RECORD_INCONSISTENT_COLUMNS' - next() - - describe 'function', -> - - it 'takes first line as argument', (next) -> - parse """ - FIELD_1,FIELD_2,FIELD_3,FIELD_4,FIELD_5,FIELD_6 - 20322051544,1979,8.8017226E7,ABC,45,2000-01-01 - 28392898392,1974,8.8392926E7,DEF,23,2050-11-27 - """, columns: (record) -> - for column in record - column.toLowerCase() - , (err, records) -> - records.should.eql [ - "field_1":"20322051544" - "field_2":"1979" - "field_3":"8.8017226E7" - "field_4":"ABC" - "field_5":"45" - "field_6":"2000-01-01" - , - "field_1":"28392898392" - "field_2":"1974" - "field_3": "8.8392926E7" - "field_4":"DEF" - "field_5":"23" - "field_6":"2050-11-27" - ] unless err - next err - - it 'catch thrown errors', (next) -> - parse """ - FIELD_1,FIELD_2,FIELD_3,FIELD_4 - abc,123,def,456 - hij,789,klm,0 - """, columns: (columns) -> - throw Error 'Catchme' - , (err) -> - err.message.should.eql 'Catchme' - next() - - it 'must return an array of headers', (next) -> - parse """ - FIELD_1 - abc - """, columns: (columns) -> - return {FIELD: true} - , (err) -> - assert_error err, - message: 'Invalid Column Mapping: expect an array from column function, got {"FIELD":true}' - code: 'CSV_INVALID_COLUMN_MAPPING' - headers: FIELD: true - next() diff --git a/packages/csv-parse/test/option.columns.js b/packages/csv-parse/test/option.columns.js new file mode 100644 index 000000000..1a18fe14e --- /dev/null +++ b/packages/csv-parse/test/option.columns.js @@ -0,0 +1,70 @@ +import "should"; +import { parse } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; + +describe("Option `columns`", function () { + describe("validation", function () { + it("check the columns value", function () { + (() => { + parse( + "", + { + columns: [ + { + name: "valid", + }, + { + invalid: "oh no", + }, + ], + }, + () => {}, + ); + }).should.throw({ + message: + 'Option columns missing name: property "name" is required at position 1 when column is an object literal', + code: "CSV_OPTION_COLUMNS_MISSING_NAME", + }); + }); + + it("check the columns options is not empty", function () { + (() => { + parse("", { columns: {} }, () => {}); + }).should.throw({ + message: + "Invalid option columns: expect an array, a function or true, got {}", + code: "CSV_INVALID_OPTION_COLUMNS", + }); + }); + + it("check the columns is not a boolean", function () { + (() => { + parse("", { columns: [{ name: "valid" }, true] }, () => {}); + }).should.throw({ + message: + "Invalid column definition: expect a string or a literal object, got true at position 1", + code: "CSV_INVALID_COLUMN_DEFINITION", + }); + }); + + it("must return an array of headers", function (next) { + parse( + "FIELD_1\nabc", + { + columns: () => { + return { FIELD: true }; + }, + }, + (err) => { + assert_error(err, { + message: + 'Invalid Column Mapping: expect an array from column function, got {"FIELD":true}', + code: "CSV_INVALID_COLUMN_MAPPING", + headers: { FIELD: true }, + }); + next(); + }, + ); + }); + }); +}); diff --git a/packages/csv-parse/test/option.columns.ts b/packages/csv-parse/test/option.columns.ts new file mode 100644 index 000000000..fba4030f3 --- /dev/null +++ b/packages/csv-parse/test/option.columns.ts @@ -0,0 +1,424 @@ +import "should"; +import { parse } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; + +describe("Option `columns`", function () { + describe("validation", function () { + it("skip columns with false value", function (next) { + parse( + "1,2,3,4\n5,6,7,8", + { + columns: ["a", false, "c", false], + }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: "1", c: "3" }, + { a: "5", c: "7" }, + ]); + } + next(err); + }, + ); + }); + + it("dont mutate options", function (next) { + const columns = ["a", "b", "c", "d"]; + parse( + "1,2,3,4\n5,6,7,8", + { + columns: columns, + }, + (err) => { + if (err) return next(err); + columns.should.eql(["a", "b", "c", "d"]); + next(); + }, + ); + }); + }); + + describe("duplicate column names", function () { + it("with true", function (next) { + parse( + "a,b,a,c\n1,2,3,4\n5,6,7,8", + { + columns: true, + }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: "3", b: "2", c: "4" }, + { a: "7", b: "6", c: "8" }, + ]); + } + next(err); + }, + ); + }); + + it("with array", function (next) { + const columns = ["a", "b", "a", "c"]; + parse( + "1,2,3,4\n5,6,7,8", + { + columns: columns, + }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: "3", b: "2", c: "4" }, + { a: "7", b: "6", c: "8" }, + ]); + } + next(err); + }, + ); + }); + + it("lines with empty column names", function (next) { + parse( + ",,,\n1,2,3,4\n5,6,7,8", + { + columns: true, + }, + (err, records) => { + if (!err) { + records.should.eql([{ "": "4" }, { "": "8" }]); + } + next(err); + }, + ); + }); + }); + + describe("boolean", function () { + it("read from first row if true", function (next) { + parse( + "FIELD_1,FIELD_2,FIELD_3,FIELD_4,FIELD_5,FIELD_6\n20322051544,1979,8.8017226E7,ABC,45,2000-01-01\n28392898392,1974,8.8392926E7,DEF,23,2050-11-27", + { + columns: true, + }, + (err, records) => { + if (!err) { + records.should.eql([ + { + FIELD_1: "20322051544", + FIELD_2: "1979", + FIELD_3: "8.8017226E7", + FIELD_4: "ABC", + FIELD_5: "45", + FIELD_6: "2000-01-01", + }, + { + FIELD_1: "28392898392", + FIELD_2: "1974", + FIELD_3: "8.8392926E7", + FIELD_4: "DEF", + FIELD_5: "23", + FIELD_6: "2050-11-27", + }, + ]); + } + next(err); + }, + ); + }); + + it("disabled if false", function (next) { + parse( + "a,b,c\nd,e,f", + { + columns: false, + }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c"], + ["d", "e", "f"], + ]); + } + next(err); + }, + ); + }); + + it("header detection honors skip_empty_lines", function (next) { + parse( + "\na,b,c\n1,2,3", + { + columns: true, + skip_empty_lines: true, + }, + (err, records) => { + if (!err) { + records.should.eql([{ a: "1", b: "2", c: "3" }]); + } + next(err); + }, + ); + }); + + it("header detection honors skip_records_with_empty_values", function (next) { + parse( + ",,\na,b,c\n1,2,3", + { + columns: true, + skip_records_with_empty_values: true, + }, + (err, records) => { + if (!err) { + records.should.eql([{ a: "1", b: "2", c: "3" }]); + } + next(err); + }, + ); + }); + }); + + describe("array", function () { + it("enforced by user if array", function (next) { + parse( + "20322051544,1979,8.8017226E7,ABC,45,2000-01-01\n28392898392,1974,8.8392926E7,DEF,23,2050-11-27", + { + columns: [ + "FIELD_1", + "FIELD_2", + "FIELD_3", + "FIELD_4", + "FIELD_5", + "FIELD_6", + ], + }, + (err, records) => { + if (!err) { + records.should.eql([ + { + FIELD_1: "20322051544", + FIELD_2: "1979", + FIELD_3: "8.8017226E7", + FIELD_4: "ABC", + FIELD_5: "45", + FIELD_6: "2000-01-01", + }, + { + FIELD_1: "28392898392", + FIELD_2: "1974", + FIELD_3: "8.8392926E7", + FIELD_4: "DEF", + FIELD_5: "23", + FIELD_6: "2050-11-27", + }, + ]); + } + next(err); + }, + ); + }); + + it("validate options column length on first line", function (next) { + parse( + "1,2,3\n4,5,6,x\n7,8,9,x", + { + columns: ["a", "b", "c", "d"], + }, + (err) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + "Invalid Record Length: columns length is 4, got 3 on line 1", + code: "CSV_RECORD_INCONSISTENT_COLUMNS", + }); + next(); + }, + ); + }); + + it("validate options column length on last line", function (next) { + parse( + "1,2,3,x\n4,5,6,x\n7,8,9", + { + columns: ["a", "b", "c", "d"], + }, + (err) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + "Invalid Record Length: columns length is 4, got 3 on line 3", + code: "CSV_RECORD_INCONSISTENT_COLUMNS", + }); + next(); + }, + ); + }); + + it("context column is null when cast force the context creation", function (next) { + parse( + "a\nb,\n", + { + columns: true, + cast: (value) => value, + }, + (err) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + "Invalid Record Length: columns length is 1, got 2 on line 2", + code: "CSV_RECORD_INCONSISTENT_COLUMNS", + column: null, + }); + next(); + }, + ); + }); + + it("context column is null when columns number inferieur to record length, fix regression #259", function (next) { + parse( + "a\nb,\n", + { + columns: true, + }, + (err) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + "Invalid Record Length: columns length is 1, got 2 on line 2", + code: "CSV_RECORD_INCONSISTENT_COLUMNS", + column: null, + }); + next(); + }, + ); + }); + + it("skips column names defined as undefined", function (next) { + parse( + "0,1,2,3,4\n5,6,7,8,9", + { + columns: ["a", undefined, undefined, undefined, "b"], + }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: "0", b: "4" }, + { a: "5", b: "9" }, + ]); + } + next(err); + }, + ); + }); + + it("skips column names defined as false", function (next) { + parse( + "0,1,2,3,4\n5,6,7,8,9", + { + columns: ["a", false, false, false, "b"], + }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: "0", b: "4" }, + { a: "5", b: "9" }, + ]); + } + next(err); + }, + ); + }); + + it("skips column names defined as null and last", function (next) { + parse( + "0,1,2\n3,4,5", + { + columns: ["a", null, null], + }, + (err, records) => { + if (!err) { + records.should.eql([{ a: "0" }, { a: "3" }]); + } + next(err); + }, + ); + }); + + it("illustrate bug with undefined values", function (next) { + parse( + "0,1,2\n3,4,5", + { + columns: ["a", undefined, undefined], + }, + (err, records) => { + if (!err) { + records.should.eql([{ a: "0" }, { a: "3" }]); + } + next(err); + }, + ); + }); + + it("last column value ignore when `null`", function (next) { + parse( + "col_a,col_b,col_c\nfoo,bar\nfoo,bar,baz", + { + columns: ["a", "b", null], + }, + (err) => { + if (!err) return next(Error("Invalid assessment")); + err.code.should.eql("CSV_RECORD_INCONSISTENT_COLUMNS"); + next(); + }, + ); + }); + }); + + describe("function", function () { + it("takes first line as argument", function (next) { + parse( + "FIELD_1,FIELD_2,FIELD_3,FIELD_4,FIELD_5,FIELD_6\n20322051544,1979,8.8017226E7,ABC,45,2000-01-01\n28392898392,1974,8.8392926E7,DEF,23,2050-11-27", + { + columns: (record) => record.map((column) => column.toLowerCase()), + }, + (err, records) => { + if (!err) { + records.should.eql([ + { + field_1: "20322051544", + field_2: "1979", + field_3: "8.8017226E7", + field_4: "ABC", + field_5: "45", + field_6: "2000-01-01", + }, + { + field_1: "28392898392", + field_2: "1974", + field_3: "8.8392926E7", + field_4: "DEF", + field_5: "23", + field_6: "2050-11-27", + }, + ]); + } + next(err); + }, + ); + }); + + it("catch thrown errors", function (next) { + parse( + "FIELD_1,FIELD_2,FIELD_3,FIELD_4\nabc,123,def,456\nhij,789,klm,0", + { + columns: () => { + throw Error("Catchme"); + }, + }, + (err) => { + if (!err) return next(Error("Invalid assessment")); + err.message.should.eql("Catchme"); + next(); + }, + ); + }); + }); +}); diff --git a/packages/csv-parse/test/option.columns_duplicates_to_array.coffee b/packages/csv-parse/test/option.columns_duplicates_to_array.coffee deleted file mode 100644 index cf9f0c582..000000000 --- a/packages/csv-parse/test/option.columns_duplicates_to_array.coffee +++ /dev/null @@ -1,51 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'Option `group_columns_by_name`', -> - - it 'validate', -> - (-> - parse "", group_columns_by_name: 'invalid' - ).should.throw - code: 'CSV_INVALID_OPTION_GROUP_COLUMNS_BY_NAME' - message: [ - 'Invalid option group_columns_by_name:' - 'expect an boolean, got "invalid"' - ].join ' ' - - it 'require columns to be active', -> - (-> - parse "", group_columns_by_name: true - ).should.throw - code: 'CSV_INVALID_OPTION_GROUP_COLUMNS_BY_NAME' - message: [ - 'Invalid option group_columns_by_name:' - 'the `columns` mode must be activated.' - ].join ' ' - - it 'when false', (next) -> - parse """ - FIELD_1,FIELD_1 - ABC,DEF - GHI,JKL - """, columns: true, group_columns_by_name: false, (err, records) -> - records.should.eql [ - 'FIELD_1': 'DEF' - , - 'FIELD_1': 'JKL' - ] unless err - next err - - it 'when true', (next) -> - parse """ - FIELD_1,FIELD_1 - ABC,DEF - GHI,JKL - """, columns: true, group_columns_by_name: true, (err, records) -> - records.should.eql [ - 'FIELD_1': ['ABC', 'DEF'] - , - 'FIELD_1': ['GHI', 'JKL'] - ] unless err - next err diff --git a/packages/csv-parse/test/option.columns_duplicates_to_array.js b/packages/csv-parse/test/option.columns_duplicates_to_array.js new file mode 100644 index 000000000..b5a58ba4d --- /dev/null +++ b/packages/csv-parse/test/option.columns_duplicates_to_array.js @@ -0,0 +1,14 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `group_columns_by_name`", function () { + it("validate", function () { + (() => { + parse("", { group_columns_by_name: "invalid" }); + }).should.throw({ + code: "CSV_INVALID_OPTION_GROUP_COLUMNS_BY_NAME", + message: + 'Invalid option group_columns_by_name: expect an boolean, got "invalid"', + }); + }); +}); diff --git a/packages/csv-parse/test/option.columns_duplicates_to_array.ts b/packages/csv-parse/test/option.columns_duplicates_to_array.ts new file mode 100644 index 000000000..f70cb5a27 --- /dev/null +++ b/packages/csv-parse/test/option.columns_duplicates_to_array.ts @@ -0,0 +1,49 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `group_columns_by_name`", function () { + it("require columns to be active", function () { + (() => { + parse("", { group_columns_by_name: true }); + }).should.throw({ + code: "CSV_INVALID_OPTION_GROUP_COLUMNS_BY_NAME", + message: + "Invalid option group_columns_by_name: the `columns` mode must be activated.", + }); + }); + + it("when false", function (next) { + parse( + "FIELD_1,FIELD_1\nABC,DEF\nGHI,JKL", + { + columns: true, + group_columns_by_name: false, + }, + (err, records) => { + if (!err) { + records.should.eql([{ FIELD_1: "DEF" }, { FIELD_1: "JKL" }]); + } + next(err); + }, + ); + }); + + it("when true", function (next) { + parse( + "FIELD_1,FIELD_1\nABC,DEF\nGHI,JKL", + { + columns: true, + group_columns_by_name: true, + }, + (err, records) => { + if (!err) { + records.should.eql([ + { FIELD_1: ["ABC", "DEF"] }, + { FIELD_1: ["GHI", "JKL"] }, + ]); + } + next(err); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/option.comment.coffee b/packages/csv-parse/test/option.comment.coffee deleted file mode 100644 index 82da4f18a..000000000 --- a/packages/csv-parse/test/option.comment.coffee +++ /dev/null @@ -1,105 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `comment`', -> - - it 'validation', -> - parse '', comment: undefined, (->) - parse '', comment: null, (->) - parse '', comment: false, (->) - parse '', comment: '', (->) - (-> - parse '', comment: true, (->) - ).should.throw - message: 'Invalid option comment: comment must be a buffer or a string, got true' - code: 'CSV_INVALID_OPTION_COMMENT' - (-> - parse '', comment: 2, (->) - ).should.throw - message: 'Invalid option comment: comment must be a buffer or a string, got 2' - code: 'CSV_INVALID_OPTION_COMMENT' - - it 'single comment line', (next) -> - parse '# comment', comment: '#', (err, records) -> - records.length.should.eql 0 - next err - - it 'single comment line with empty field', (next) -> - parse '""# comment', comment: '#', (err, records) -> - records.should.eql [['']] - next err - - it 'skip line starting by single comment char', (next) -> - parse """ - # skip this - "ABC","45" - "DEF","23" - # and this - "GHI","94" - # as well as that - """, comment: '#', (err, records) -> - records.should.eql [ - [ 'ABC','45' ] - [ 'DEF','23' ] - [ 'GHI','94' ] - ] unless err - next err - - it 'doent apply inside quotes', (next) -> - parse """ - "ABC","45" - "D#noEF","23"#yes - "GHI","94" - """, comment: '#', (err, records) -> - records.should.eql [ - [ 'ABC','45' ] - [ 'D#noEF','23' ] - [ 'GHI','94' ] - ] unless err - next err - - it 'is cancel if empty', (next) -> - parse """ - abc,#,def - 1,2,3 - """, comment: '', (err, records) -> - records.should.eql [ - [ 'abc','#','def' ] - [ '1','2', '3' ] - ] - next() - - it 'is cancel by default', (next) -> - parse """ - abc,#,def - 1,2,3 - """, (err, records) -> - records.should.eql [ - [ 'abc','#','def' ] - [ '1','2', '3' ] - ] - next() - - it 'accept multiple characters', (next) -> - parser = parse comment: '//', (err, records) -> - records.should.eql [ - [ 'abc','def' ] - [ '1','2' ] - ] - next() - data = """ - abc,def - // a comment - 1,2 - """ - parser.write char for char in data - parser.end() - - it 'accept quotes', (next) -> - parse """ - "Alaska","Site1","Rack1","RTU-1","192.168.1.3" - # Contains double-quote: " - """, - comment: "#" - , (err, content) -> - next err diff --git a/packages/csv-parse/test/option.comment.js b/packages/csv-parse/test/option.comment.js new file mode 100644 index 000000000..d22c5b205 --- /dev/null +++ b/packages/csv-parse/test/option.comment.js @@ -0,0 +1,14 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `comment`", function () { + it("validation", function () { + (() => { + parse("", { comment: 2 }, () => {}); + }).should.throw({ + message: + "Invalid option comment: comment must be a buffer or a string, got 2", + code: "CSV_INVALID_OPTION_COMMENT", + }); + }); +}); diff --git a/packages/csv-parse/test/option.comment.ts b/packages/csv-parse/test/option.comment.ts new file mode 100644 index 000000000..70f499f4e --- /dev/null +++ b/packages/csv-parse/test/option.comment.ts @@ -0,0 +1,143 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; + +describe("Option `comment`", function () { + it("validation", function () { + parse("", { comment: undefined }, () => {}); + parse("", { comment: null }, () => {}); + parse("", { comment: false }, () => {}); + parse("", { comment: "" }, () => {}); + (() => { + parse("", { comment: true }, () => {}); + }).should.throw({ + message: + "Invalid option comment: comment must be a buffer or a string, got true", + code: "CSV_INVALID_OPTION_COMMENT", + }); + }); + + it("single comment line", function (next) { + parse("# comment", { comment: "#" }, (err, records) => { + records.length.should.eql(0); + next(err); + }); + }); + + it("single comment line with empty field", function (next) { + parse('""# comment', { comment: "#" }, (err, records) => { + records.should.eql([[""]]); + next(err); + }); + }); + + it("skip line starting by single comment char", function (next) { + parse( + dedent` + # skip this + "ABC","45" + "DEF","23" + # and this + "GHI","94" + # as well as that + `, + { + comment: "#", + }, + (err, records) => { + if (!err) { + records.should.eql([ + ["ABC", "45"], + ["DEF", "23"], + ["GHI", "94"], + ]); + } + next(err); + }, + ); + }); + + it("doent apply inside quotes", function (next) { + parse( + dedent` + "ABC","45" + "D#noEF","23"#yes + "GHI","94" + `, + { + comment: "#", + }, + (err, records) => { + if (!err) { + records.should.eql([ + ["ABC", "45"], + ["D#noEF", "23"], + ["GHI", "94"], + ]); + } + next(err); + }, + ); + }); + + it("is cancel if empty", function (next) { + parse( + dedent` + abc,#,def + 1,2,3 + `, + { + comment: "", + }, + (err, records) => { + records.should.eql([ + ["abc", "#", "def"], + ["1", "2", "3"], + ]); + next(); + }, + ); + }); + + it("is cancel by default", function (next) { + parse("abc,#,def\n1,2,3", (err, records) => { + records.should.eql([ + ["abc", "#", "def"], + ["1", "2", "3"], + ]); + next(); + }); + }); + + it("accept multiple characters", function (next) { + const parser = parse({ comment: "//" }, (err, records) => { + records.should.eql([ + ["abc", "def"], + ["1", "2"], + ]); + next(); + }); + const data = dedent` + abc,def + // a comment + 1,2 + `; + for (const char of data) { + parser.write(char); + } + parser.end(); + }); + + it("accept quotes", function (next) { + parse( + dedent` + "Alaska","Site1","Rack1","RTU-1","192.168.1.3" + # Contains double-quote: " + `, + { + comment: "#", + }, + (err) => next(err), + ); + }); +}); diff --git a/packages/csv-parse/test/option.comment_no_infix.coffee b/packages/csv-parse/test/option.comment_no_infix.coffee deleted file mode 100644 index fbdcd03aa..000000000 --- a/packages/csv-parse/test/option.comment_no_infix.coffee +++ /dev/null @@ -1,47 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `comment_no_infix`', -> - - it 'validation', -> - parse '', comment_no_infix: undefined, (->) - parse '', comment_no_infix: null, (->) - parse '', comment_no_infix: false, (->) - parse '', comment_no_infix: true, (->) - (-> - parse '', comment_no_infix: '', (->) - ).should.throw - message: 'Invalid option comment_no_infix: value must be a boolean, got ""' - code: 'CSV_INVALID_OPTION_COMMENT' - (-> - parse '', comment_no_infix: 2, (->) - ).should.throw - message: 'Invalid option comment_no_infix: value must be a boolean, got 2' - code: 'CSV_INVALID_OPTION_COMMENT' - - it 'with `true`, field starting with comment', (next) -> - parse ''' - a,#,c - ''', comment: '#', comment_no_infix: true, (err, records) -> - records.should.eql [ - ['a', '#', 'c'] - ] unless err - next err - - it 'with `true`, field not starting with comment', (next) -> - parse ''' - a,b#,c - ''', comment: '#', comment_no_infix: true, (err, records) -> - records.should.eql [ - ['a', 'b#', 'c'] - ] unless err - next err - - it 'with `false`', (next) -> - parse ''' - a,b#,c - ''', comment: '#', comment_no_infix: false, (err, records) -> - records.should.eql [ - ['a', 'b'] - ] unless err - next err diff --git a/packages/csv-parse/test/option.comment_no_infix.js b/packages/csv-parse/test/option.comment_no_infix.js new file mode 100644 index 000000000..f9659a005 --- /dev/null +++ b/packages/csv-parse/test/option.comment_no_infix.js @@ -0,0 +1,21 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `comment_no_infix`", function () { + it("validation", function () { + (() => { + parse("", { comment_no_infix: "" }, () => {}); + }).should.throw({ + message: + 'Invalid option comment_no_infix: value must be a boolean, got ""', + code: "CSV_INVALID_OPTION_COMMENT", + }); + (() => { + parse("", { comment_no_infix: 2 }, () => {}); + }).should.throw({ + message: + "Invalid option comment_no_infix: value must be a boolean, got 2", + code: "CSV_INVALID_OPTION_COMMENT", + }); + }); +}); diff --git a/packages/csv-parse/test/option.comment_no_infix.ts b/packages/csv-parse/test/option.comment_no_infix.ts new file mode 100644 index 000000000..0bb21e291 --- /dev/null +++ b/packages/csv-parse/test/option.comment_no_infix.ts @@ -0,0 +1,59 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `comment_no_infix`", function () { + it("validation", function () { + parse("", { comment_no_infix: undefined }, () => {}); + parse("", { comment_no_infix: null }, () => {}); + parse("", { comment_no_infix: false }, () => {}); + parse("", { comment_no_infix: true }, () => {}); + }); + + it("with `true`, field starting with comment", function (next) { + parse( + "a,#,c", + { + comment: "#", + comment_no_infix: true, + }, + (err, records) => { + if (!err) { + records.should.eql([["a", "#", "c"]]); + } + next(err); + }, + ); + }); + + it("with `true`, field not starting with comment", function (next) { + parse( + "a,b#,c", + { + comment: "#", + comment_no_infix: true, + }, + (err, records) => { + if (!err) { + records.should.eql([["a", "b#", "c"]]); + } + next(err); + }, + ); + }); + + it("with `false`", function (next) { + parse( + "a,b#,c", + { + comment: "#", + comment_no_infix: false, + }, + (err, records) => { + if (!err) { + records.should.eql([["a", "b"]]); + } + next(err); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/option.delimiter.coffee b/packages/csv-parse/test/option.delimiter.coffee deleted file mode 100644 index 0789d08e4..000000000 --- a/packages/csv-parse/test/option.delimiter.coffee +++ /dev/null @@ -1,135 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `delimiter`', -> - - it 'validation', -> - parse '', delimiter: ',', (->) - parse '', delimiter: Buffer.from(','), (->) - (-> - parse '', delimiter: '', (->) - ).should.throw - message: 'Invalid option delimiter: delimiter must be a non empty string or buffer or array of string|buffer, got ""' - code: 'CSV_INVALID_OPTION_DELIMITER' - (-> - parse '', delimiter: Buffer.from(''), (->) - ).should.throw - message: 'Invalid option delimiter: delimiter must be a non empty string or buffer or array of string|buffer, got {"type":"Buffer","data":[]}' - code: 'CSV_INVALID_OPTION_DELIMITER' - (-> - parse '', delimiter: true, (->) - ).should.throw - message: 'Invalid option delimiter: delimiter must be a non empty string or buffer or array of string|buffer, got true' - code: 'CSV_INVALID_OPTION_DELIMITER' - (-> - parse '', delimiter: [], (->) - ).should.throw - message: 'Invalid option delimiter: delimiter must be a non empty string or buffer or array of string|buffer, got []' - code: 'CSV_INVALID_OPTION_DELIMITER' - (-> - parse '', delimiter: [''], (->) - ).should.throw - message: 'Invalid option delimiter: delimiter must be a non empty string or buffer or array of string|buffer, got [""]' - code: 'CSV_INVALID_OPTION_DELIMITER' - (-> - parse '', delimiter: [',',''], (->) - ).should.throw - message: 'Invalid option delimiter: delimiter must be a non empty string or buffer or array of string|buffer, got [",",""]' - code: 'CSV_INVALID_OPTION_DELIMITER' - - it 'is compatible with buffer size', (next) -> - parser = parse delimiter: [':::'], (err, records) -> - records.should.eql [ - [ '1', '2', '3' ] - [ 'b', 'c', 'd' ] - ] - next err - parser.write c for c in """ - 1:::2:::3 - b:::c:::d - """ - parser.end() - - it 'using default comma', (next) -> - parse """ - abc,,123, - ,def,, - """, (err, records) -> - return next err if err - records.should.eql [ - [ 'abc','','123',''] - [ '','def','',''] - ] - next() - - it 'using tab', (next) -> - parse """ - abc\t\tde\tf\t - \thij\tklm\t\t - """, delimiter: '\t', (err, records) -> - return next err if err - records.should.eql [ - [ 'abc','','de','f',''] - [ '','hij','klm','',''] - ] - next() - - it 'multiple chars empty fields only', (next) -> - parse """ - !# - !# - """, delimiter: '!#', (err, records) -> - return next err if err - records.should.eql [ - [ '', ''] - [ '', ''] - ] - next() - - it 'multiple chars mixed fields', (next) -> - parse """ - 20322051544!#!#8.8017226E7!#45!# - !#1974!#8.8392926E7!#!# - """, delimiter: '!#', (err, records) -> - return next err if err - records.should.eql [ - [ '20322051544','','8.8017226E7','45',''] - [ '','1974','8.8392926E7','',''] - ] - next() - - it 'using array of a single delimiter', (next) -> - parse """ - abc,,123, - ,def,, - """, delimiter: [','], (err, records) -> - return next err if err - records.should.eql [ - [ 'abc','','123',''] - [ '','def','',''] - ] - next() - - it 'using array of a single delimiter of multiple characters', (next) -> - parse """ - !# - !# - """, delimiter: ['!#'], (err, records) -> - return next err if err - records.should.eql [ - [ '', ''] - [ '', ''] - ] - next() - - it 'using array of a multiple delimiters of variable length', (next) -> - parse """ - abc,;;123;; - ;;def;;, - """, delimiter: [',', ';;'], (err, records) -> - return next err if err - records.should.eql [ - [ 'abc','','123',''] - [ '','def','',''] - ] - next() diff --git a/packages/csv-parse/test/option.delimiter.js b/packages/csv-parse/test/option.delimiter.js new file mode 100644 index 000000000..7c4c88962 --- /dev/null +++ b/packages/csv-parse/test/option.delimiter.js @@ -0,0 +1,14 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `delimiter`", function () { + it("validation", function () { + (() => { + parse("", { delimiter: true }, () => {}); + }).should.throw({ + message: + "Invalid option delimiter: delimiter must be a non empty string or buffer or array of string|buffer, got true", + code: "CSV_INVALID_OPTION_DELIMITER", + }); + }); +}); diff --git a/packages/csv-parse/test/option.delimiter.ts b/packages/csv-parse/test/option.delimiter.ts new file mode 100644 index 000000000..568ae1b49 --- /dev/null +++ b/packages/csv-parse/test/option.delimiter.ts @@ -0,0 +1,171 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `delimiter`", function () { + it("validation", function () { + parse("", { delimiter: "," }, () => {}); + parse("", { delimiter: Buffer.from(",") }, () => {}); + (() => { + parse("", { delimiter: "" }, () => {}); + }).should.throw({ + message: + 'Invalid option delimiter: delimiter must be a non empty string or buffer or array of string|buffer, got ""', + code: "CSV_INVALID_OPTION_DELIMITER", + }); + (() => { + parse("", { delimiter: Buffer.from("") }, () => {}); + }).should.throw({ + message: + 'Invalid option delimiter: delimiter must be a non empty string or buffer or array of string|buffer, got {"type":"Buffer","data":[]}', + code: "CSV_INVALID_OPTION_DELIMITER", + }); + (() => { + parse("", { delimiter: [] }, () => {}); + }).should.throw({ + message: + "Invalid option delimiter: delimiter must be a non empty string or buffer or array of string|buffer, got []", + code: "CSV_INVALID_OPTION_DELIMITER", + }); + (() => { + parse("", { delimiter: [""] }, () => {}); + }).should.throw({ + message: + 'Invalid option delimiter: delimiter must be a non empty string or buffer or array of string|buffer, got [""]', + code: "CSV_INVALID_OPTION_DELIMITER", + }); + (() => { + parse("", { delimiter: [",", ""] }, () => {}); + }).should.throw({ + message: + 'Invalid option delimiter: delimiter must be a non empty string or buffer or array of string|buffer, got [",",""]', + code: "CSV_INVALID_OPTION_DELIMITER", + }); + }); + + it("is compatible with buffer size", function (next) { + const parser = parse({ delimiter: [":::"] }, (err, records) => { + records.should.eql([ + ["1", "2", "3"], + ["b", "c", "d"], + ]); + next(err); + }); + for (const c of "1:::2:::3\nb:::c:::d") { + parser.write(c); + } + parser.end(); + }); + + it("using default comma", function (next) { + parse("abc,,123,\n,def,,", (err, records) => { + if (err) return next(err); + records.should.eql([ + ["abc", "", "123", ""], + ["", "def", "", ""], + ]); + next(); + }); + }); + + it("using tab", function (next) { + parse( + "abc\t\tde\tf\t\n\thij\tklm\t\t", + { + delimiter: "\t", + }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["abc", "", "de", "f", ""], + ["", "hij", "klm", "", ""], + ]); + next(); + }, + ); + }); + + it("multiple chars empty fields only", function (next) { + parse( + "!#\n!#", + { + delimiter: "!#", + }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["", ""], + ["", ""], + ]); + next(); + }, + ); + }); + + it("multiple chars mixed fields", function (next) { + parse( + "20322051544!#!#8.8017226E7!#45!#\n!#1974!#8.8392926E7!#!#", + { + delimiter: "!#", + }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["20322051544", "", "8.8017226E7", "45", ""], + ["", "1974", "8.8392926E7", "", ""], + ]); + next(); + }, + ); + }); + + it("using array of a single delimiter", function (next) { + parse( + "abc,,123,\n,def,,", + { + delimiter: [","], + }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["abc", "", "123", ""], + ["", "def", "", ""], + ]); + next(); + }, + ); + }); + + it("using array of a single delimiter of multiple characters", function (next) { + parse( + "!#\n!#", + { + delimiter: ["!#"], + }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["", ""], + ["", ""], + ]); + next(); + }, + ); + }); + + it("using array of a multiple delimiters of variable length", function (next) { + parse( + "abc,;;123;;\n;;def;;,", + { + delimiter: [",", ";;"], + }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["abc", "", "123", ""], + ["", "def", "", ""], + ]); + next(); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/option.encoding.coffee b/packages/csv-parse/test/option.encoding.coffee deleted file mode 100644 index 77cfa9542..000000000 --- a/packages/csv-parse/test/option.encoding.coffee +++ /dev/null @@ -1,114 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `encoding`', -> - - describe 'validation & normalization', -> - - it 'boolean true convert to default', -> - parse(encoding: true).options.encoding.should.eql 'utf8' - - it 'boolean false convert to null', -> - (parse(encoding: false).options.encoding is null).should.be.true() - - it 'integer throw invalid encoding', -> - (-> - parse 'whocare', encoding: 666, (->) - ).should.throw - code: 'CSV_INVALID_OPTION_ENCODING' - message: [ - 'Invalid option encoding:', - 'encoding must be a string or null to return a buffer,', - 'got 666' - ].join ' ' - - describe 'definition', -> - - it 'with delimiter', (next) -> - parse Buffer.from('x:x', 'utf16le'), - delimiter: ':' - encoding: 'utf16le' - , (err, records) -> - records.should.eql [['x', 'x']] unless err - next err - - it 'with escape equals quote', (next) -> - parse Buffer.from( """ - a,b,c - 1,"2 ""3"" 4",5 - """, 'utf16le' - ), - encoding: 'utf16le' - , (err, records) -> - records.should.eql [ - [ 'a', 'b', 'c' ] - [ '1', '2 "3" 4', '5' ] - ] unless err - next err - - it 'null return buffer', (next) -> - parse Buffer.from( 'a,b\n1,2' ), - encoding: null - , (err, records) -> - records.should.eql [ - [ Buffer.from('a'), Buffer.from('b') ] - [ Buffer.from('1'), Buffer.from('2') ] - ] unless err - next err - - describe 'with BOM', -> - - it 'utf16le auto detected', (next) -> - parser = parse bom: true, encoding: 'utf16le', (err, records) -> - records.should.eql [ - ['a', 'b', 'c'] - ['d', 'e', 'f'] - ] - next() - parser.write Buffer.from "\ufeffa,b,c\n", 'utf16le' - parser.write Buffer.from 'd,e,f', 'utf16le' - parser.end() - - it 'utf16le auto detected with quote', (next) -> - parser = parse bom: true, (err, records) -> - records.should.eql [ - ['a', 'b', 'c'] - ['d', 'e', 'f'] - ] unless err - next err - parser.write Buffer.from '\ufeffa,"b",c\n', 'utf16le' - parser.write Buffer.from 'd,"e",f', 'utf16le' - parser.end() - - it 'utf16le auto detected with delimiter', (next) -> - parser = parse bom: true, delimiter: 'ф', (err, records) -> - records.should.eql [ - ['a', 'b', 'c'] - ['d', 'e', 'f'] - ] unless err - next err - parser.write Buffer.from '\ufeffaфbфc\n', 'utf16le' - parser.write Buffer.from 'dфeфf', 'utf16le' - parser.end() - - it 'utf16le auto detected with escape', (next) -> - parser = parse bom: true, escape: 'ф', (err, records) -> - records.should.eql [ - ['a', '"b', 'c'] - ['d', '"e', 'f'] - ] unless err - next err - parser.write Buffer.from '\ufeffa,"ф"b",c\n', 'utf16le' - parser.write Buffer.from 'd,"ф"e",f', 'utf16le' - parser.end() - - it 'utf16le auto detected with record_delimiter', (next) -> - parser = parse bom: true, record_delimiter: 'ф', (err, records) -> - records.should.eql [ - ['a', 'b', 'c'] - ['d', 'e', 'f'] - ] unless err - next err - parser.write Buffer.from '\ufeffa,b,cф', 'utf16le' - parser.write Buffer.from 'd,e,f', 'utf16le' - parser.end() diff --git a/packages/csv-parse/test/option.encoding.js b/packages/csv-parse/test/option.encoding.js new file mode 100644 index 000000000..bf9ca71ae --- /dev/null +++ b/packages/csv-parse/test/option.encoding.js @@ -0,0 +1,16 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `encoding`", function () { + describe("validation & normalization", function () { + it("integer throw invalid encoding", function () { + (() => { + parse("whocare", { encoding: 666 }, () => {}); + }).should.throw({ + code: "CSV_INVALID_OPTION_ENCODING", + message: + "Invalid option encoding: encoding must be a string or null to return a buffer, got 666", + }); + }); + }); +}); diff --git a/packages/csv-parse/test/option.encoding.ts b/packages/csv-parse/test/option.encoding.ts new file mode 100644 index 000000000..7961ab114 --- /dev/null +++ b/packages/csv-parse/test/option.encoding.ts @@ -0,0 +1,147 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `encoding`", function () { + describe("validation & normalization", function () { + it("boolean true convert to default", function () { + parse({ encoding: true }).options.encoding?.should.eql("utf8"); + }); + + it("boolean false convert to null", function () { + (parse({ encoding: false }).options.encoding === null).should.be.true(); + }); + }); + + describe("definition", function () { + it("with delimiter", function (next) { + parse( + Buffer.from("x:x", "utf16le"), + { + delimiter: ":", + encoding: "utf16le", + }, + (err, records) => { + if (!err) records.should.eql([["x", "x"]]); + next(err); + }, + ); + }); + + it("with escape equals quote", function (next) { + parse( + Buffer.from('a,b,c\n1,"2 ""3"" 4",5', "utf16le"), + { + encoding: "utf16le", + }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c"], + ["1", '2 "3" 4', "5"], + ]); + } + next(err); + }, + ); + }); + + it("null return buffer", function (next) { + parse( + Buffer.from("a,b\n1,2"), + { + encoding: null, + }, + (err, records) => { + if (!err) { + records.should.eql([ + [Buffer.from("a"), Buffer.from("b")], + [Buffer.from("1"), Buffer.from("2")], + ]); + } + next(err); + }, + ); + }); + }); + + describe("with BOM", function () { + it("utf16le auto detected", function (next) { + const parser = parse( + { bom: true, encoding: "utf16le" }, + (err, records) => { + records.should.eql([ + ["a", "b", "c"], + ["d", "e", "f"], + ]); + next(); + }, + ); + parser.write(Buffer.from("\ufeffa,b,c\n", "utf16le")); + parser.write(Buffer.from("d,e,f", "utf16le")); + parser.end(); + }); + + it("utf16le auto detected with quote", function (next) { + const parser = parse({ bom: true }, (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c"], + ["d", "e", "f"], + ]); + } + next(err); + }); + parser.write(Buffer.from('\ufeffa,"b",c\n', "utf16le")); + parser.write(Buffer.from('d,"e",f', "utf16le")); + parser.end(); + }); + + it("utf16le auto detected with delimiter", function (next) { + const parser = parse({ bom: true, delimiter: "ф" }, (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c"], + ["d", "e", "f"], + ]); + } + next(err); + }); + parser.write(Buffer.from("\ufeffaфbфc\n", "utf16le")); + parser.write(Buffer.from("dфeфf", "utf16le")); + parser.end(); + }); + + it("utf16le auto detected with escape", function (next) { + const parser = parse({ bom: true, escape: "ф" }, (err, records) => { + if (!err) { + records.should.eql([ + ["a", '"b', "c"], + ["d", '"e', "f"], + ]); + } + next(err); + }); + parser.write(Buffer.from('\ufeffa,"ф"b",c\n', "utf16le")); + parser.write(Buffer.from('d,"ф"e",f', "utf16le")); + parser.end(); + }); + + it("utf16le auto detected with record_delimiter", function (next) { + const parser = parse( + { bom: true, record_delimiter: "ф" }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c"], + ["d", "e", "f"], + ]); + } + next(err); + }, + ); + parser.write(Buffer.from("\ufeffa,b,cф", "utf16le")); + parser.write(Buffer.from("d,e,f", "utf16le")); + parser.end(); + }); + }); +}); diff --git a/packages/csv-parse/test/option.escape.coffee b/packages/csv-parse/test/option.escape.coffee deleted file mode 100644 index 50466560a..000000000 --- a/packages/csv-parse/test/option.escape.coffee +++ /dev/null @@ -1,157 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `escape`', -> - - describe 'normalisation, coercion & validation', -> - - it 'default', -> - parse().options.escape.should.eql Buffer.from('"') - parse(escape: undefined).options.escape.should.eql Buffer.from('"') - parse(escape: true).options.escape.should.eql Buffer.from('"') - - it 'custom', -> - parse(escape: '\\').options.escape.should.eql Buffer.from('\\') - parse(escape: Buffer.from('\\')).options.escape.should.eql Buffer.from('\\') - - it 'disabled', -> - (parse(escape: null).options.escape is null).should.be.true() - (parse(escape: false).options.escape is null).should.be.true() - - it 'invalid', -> - (-> - parse escape: 1 - ).should.throw 'Invalid Option: escape must be a buffer, a string or a boolean, got 1' - # (-> - # parse escape: 'abc' - # ).should.throw 'Invalid Option Length: escape must be one character, got 3' - - it 'is compatible with buffer size', (next) -> - parser = parse escape: '::::::', (err, records) -> - records.should.eql [ - [ '1', '2"2', '3' ] - [ '4', '5', '6"' ] - [ 'b', 'c', 'd' ] - ] unless err - next err - parser.write c for c in """ - 1,"2::::::"2",3 - 4,5,"6::::::"" - b,c,d - """ - parser.end() - - describe 'disabled', -> - - it 'when null', (next) -> - parse ''' - a"b - '1"2' - ''', escape: null, quote: '\'', (err, records) -> - return next err if err - records.should.eql [ - [ 'a"b' ],[ '1"2' ] - ] - next() - - describe 'same as quote', -> - - it 'length is 1 char', (next) -> - parse ''' - aa,"b1""b2","c""d""e" - "f""g",h,"i1""i2" - ''', escape: '"', (err, records) -> - return next err if err - records.should.eql [ - [ 'aa','b1"b2','c"d"e' ] - [ 'f"g','h','i1"i2' ] - ] - next() - - it 'length is multiple char', (next) -> - parse ''' - aa,$$b1$$$$b2$$,$$c$$$$d$$$$e$$ - $$f$$$$g$$,h,$$i1$$$$i2$$ - ''', escape: '$$', quote: '$$', (err, records) -> - return next err if err - records.should.eql [ - [ 'aa','b1$$b2','c$$d$$e' ] - [ 'f$$g','h','i1$$i2' ] - ] - next() - - describe 'different than quote', -> - - it 'apply to quote char', (next) -> - parse ''' - aa,"b1\\"b2","c\\"d\\"e" - "f\\"g",h,"i1\\"i2" - ''', escape: '\\', (err, records) -> - return next err if err - records.should.eql [ - [ 'aa','b1"b2','c"d"e' ] - [ 'f"g','h','i1"i2' ] - ] - next() - - it 'apply to quote char', (next) -> - parse ''' - aa,"b1$$"b2","c$$"d$$"e" - "f$$"g",h,"i1$$"i2" - ''', escape: '$$', (err, records) -> - return next err if err - records.should.eql [ - [ 'aa','b1"b2','c"d"e' ] - [ 'f"g','h','i1"i2' ] - ] - next() - - it 'apply to escape char', (next) -> - parse ''' - aa,"b1\\\\b2","c\\\\d\\\\e" - "f\\\\g",h,"i1\\\\i2" - ''', escape: '\\', (err, records) -> - return next err if err - records.should.eql [ - [ 'aa','b1\\b2','c\\d\\e' ] - [ 'f\\g','h','i1\\i2' ] - ] - next() - - it 'does not apply outside quoted field', (next) -> - parse ''' - aa,b1\\\\b2,c\\\\d\\\\e - f\\\\g,h,i1\\\\i2 - ''', escape: '\\', (err, records) -> - return next err if err - records.should.eql [ - [ 'aa','b1\\\\b2','c\\\\d\\\\e' ] - [ 'f\\\\g','h','i1\\\\i2' ] - ] - next() - - it 'does not apply to delimiter', (next) -> - parse ''' - aa\\,bb - ''', escape: '\\', (err, records) -> - return next err if err - records.should.eql [ - [ 'aa\\','bb' ] - ] - next() - - it 'handle non continuous chunks', (next) -> - records = [] - parser = parse escape: '\\' - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'end', -> - records.should.eql [ - [ 'abc " def' ] - ] - next() - parser.write chr for chr in ''' - "abc \\" def" - ''' - parser.end() diff --git a/packages/csv-parse/test/option.escape.js b/packages/csv-parse/test/option.escape.js new file mode 100644 index 000000000..8bafea9d1 --- /dev/null +++ b/packages/csv-parse/test/option.escape.js @@ -0,0 +1,14 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `escape`", function () { + describe("normalisation, coercion & validation", function () { + it("invalid", function () { + (() => { + parse({ escape: 1 }); + }).should.throw( + "Invalid Option: escape must be a buffer, a string or a boolean, got 1", + ); + }); + }); +}); diff --git a/packages/csv-parse/test/option.escape.ts b/packages/csv-parse/test/option.escape.ts new file mode 100644 index 000000000..989445ad5 --- /dev/null +++ b/packages/csv-parse/test/option.escape.ts @@ -0,0 +1,203 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; + +describe("Option `escape`", function () { + describe("normalisation, coercion & validation", function () { + it("default", function () { + parse().options.escape?.should.eql(Buffer.from('"')); + parse({ escape: undefined }).options.escape?.should.eql(Buffer.from('"')); + parse({ escape: true }).options.escape?.should.eql(Buffer.from('"')); + }); + + it("custom", function () { + parse({ escape: "\\" }).options.escape?.should.eql(Buffer.from("\\")); + parse({ escape: Buffer.from("\\") }).options.escape?.should.eql( + Buffer.from("\\"), + ); + }); + + it("disabled", function () { + (parse({ escape: null }).options.escape === null).should.be.true(); + (parse({ escape: false }).options.escape === null).should.be.true(); + }); + + it("is compatible with buffer size", function (next) { + const parser = parse({ escape: "::::::" }, (err, records) => { + if (!err) { + records.should.eql([ + ["1", '2"2', "3"], + ["4", "5", '6"'], + ["b", "c", "d"], + ]); + } + next(err); + }); + for (const c of dedent` + 1,"2::::::"2",3 + 4,5,"6::::::"" + b,c,d + `) { + parser.write(c); + } + parser.end(); + }); + }); + + describe("disabled", function () { + it("when null", function (next) { + parse( + "a\"b\n'1\"2'", + { + escape: null, + quote: "'", + }, + (err, records) => { + if (err) return next(err); + records.should.eql([['a"b'], ['1"2']]); + next(); + }, + ); + }); + }); + + describe("same as quote", function () { + it("length is 1 char", function (next) { + parse( + 'aa,"b1""b2","c""d""e"\n"f""g",h,"i1""i2"', + { + escape: '"', + }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["aa", 'b1"b2', 'c"d"e'], + ['f"g', "h", 'i1"i2'], + ]); + next(); + }, + ); + }); + + it("length is multiple char", function (next) { + parse( + "aa,$$b1$$$$b2$$,$$c$$$$d$$$$e$$\n$$f$$$$g$$,h,$$i1$$$$i2$$", + { + escape: "$$", + quote: "$$", + }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["aa", "b1$$b2", "c$$d$$e"], + ["f$$g", "h", "i1$$i2"], + ]); + next(); + }, + ); + }); + }); + + describe("different than quote", function () { + it("apply to quote char", function (next) { + parse( + 'aa,"b1\\"b2","c\\"d\\"e"\n"f\\"g",h,"i1\\"i2"', + { + escape: "\\", + }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["aa", 'b1"b2', 'c"d"e'], + ['f"g', "h", 'i1"i2'], + ]); + next(); + }, + ); + }); + + it("apply to quote char with custom char", function (next) { + parse( + 'aa,"b1$$"b2","c$$"d$$"e"\n"f$$"g",h,"i1$$"i2"', + { + escape: "$$", + }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["aa", 'b1"b2', 'c"d"e'], + ['f"g', "h", 'i1"i2'], + ]); + next(); + }, + ); + }); + + it("apply to escape char with escape", function (next) { + parse( + 'aa,"b1\\\\b2","c\\\\d\\\\e"\n"f\\\\g",h,"i1\\\\i2"', + { + escape: "\\", + }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["aa", "b1\\b2", "c\\d\\e"], + ["f\\g", "h", "i1\\i2"], + ]); + next(); + }, + ); + }); + + it("does not apply outside quoted field", function (next) { + parse( + "aa,b1\\\\b2,c\\\\d\\\\e\nf\\\\g,h,i1\\\\i2", + { + escape: "\\", + }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["aa", "b1\\\\b2", "c\\\\d\\\\e"], + ["f\\\\g", "h", "i1\\\\i2"], + ]); + next(); + }, + ); + }); + + it("does not apply to delimiter", function (next) { + parse( + "aa\\,bb", + { + escape: "\\", + }, + (err, records) => { + if (err) return next(err); + records.should.eql([["aa\\", "bb"]]); + next(); + }, + ); + }); + + it("handle non continuous chunks", function (next) { + const records: string[] = []; + const parser = parse({ escape: "\\" }); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + records.should.eql([['abc " def']]); + next(); + }); + for (const chr of '"abc \\" def"') { + parser.write(chr); + } + parser.end(); + }); + }); +}); diff --git a/packages/csv-parse/test/option.from.coffee b/packages/csv-parse/test/option.from.coffee deleted file mode 100644 index 1382b751c..000000000 --- a/packages/csv-parse/test/option.from.coffee +++ /dev/null @@ -1,69 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `from`', -> - - it 'validation', -> - parse '', from: 10, (->) - parse '', from: "10", (->) - (-> - parse '', from: -1, (->) - ).should.throw 'Invalid Option: from must be a positive integer, got -1' - (-> - parse '', from: '-1', (->) - ).should.throw 'Invalid Option: from must be a positive integer, got "-1"' - (-> - parse '', from: true, (->) - ).should.throw 'Invalid Option: from must be an integer, got true' - (-> - parse '', from: false, (->) - ).should.throw 'Invalid Option: from must be an integer, got false' - (-> - parse '', from: 'oh no', (->) - ).should.throw 'Invalid Option: from must be an integer, got "oh no"' - - it 'start at defined position', (next) -> - parse """ - 1,2,3 - 4,5,6 - 7,8,9 - """, from: 3, (err, records) -> - records.should.eql [ - [ '7','8','9' ] - ] unless err - next err - - it 'dont count headers', (next) -> - parse """ - a,b,c - 1,2,3 - 4,5,6 - 7,8,9 - """, columns: true, from: 3, (err, records) -> - records.should.eql [ - {a:'7',b:'8',c:'9'} - ] unless err - next err - - it 'not influenced by lines', (next) -> - parse """ - 1,2," - 3" - 4,5," - 6" - 7,8," - 9" - """, from: 3, (err, records) -> - records.should.eql [ - [ '7','8','\n9' ] - ] unless err - next err - - it 'not influenced by record delimiter', (next) -> - parse """ - 1,2,3:4,5,6:7,8,9 - """, from: 3, record_delimiter: ':', (err, records) -> - records.should.eql [ - [ '7','8','9' ] - ] unless err - next err diff --git a/packages/csv-parse/test/option.from.js b/packages/csv-parse/test/option.from.js new file mode 100644 index 000000000..e1c680820 --- /dev/null +++ b/packages/csv-parse/test/option.from.js @@ -0,0 +1,13 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `from`", function () { + it("validation", function () { + (() => { + parse("", { from: true }, () => {}); + }).should.throw("Invalid Option: from must be an integer, got true"); + (() => { + parse("", { from: false }, () => {}); + }).should.throw("Invalid Option: from must be an integer, got false"); + }); +}); diff --git a/packages/csv-parse/test/option.from.ts b/packages/csv-parse/test/option.from.ts new file mode 100644 index 000000000..9e79542ce --- /dev/null +++ b/packages/csv-parse/test/option.from.ts @@ -0,0 +1,91 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; + +describe("Option `from`", function () { + it("validation", function () { + parse("", { from: 10 }, () => {}); + parse("", { from: "10" }, () => {}); + (() => { + parse("", { from: -1 }, () => {}); + }).should.throw("Invalid Option: from must be a positive integer, got -1"); + (() => { + parse("", { from: "-1" }, () => {}); + }).should.throw( + 'Invalid Option: from must be a positive integer, got "-1"', + ); + (() => { + parse("", { from: "oh no" }, () => {}); + }).should.throw('Invalid Option: from must be an integer, got "oh no"'); + }); + + it("start at defined position", function (next) { + parse( + dedent` + 1,2,3 + 4,5,6 + 7,8,9 + `, + { from: 3 }, + (err, records) => { + if (!err) { + records.should.eql([["7", "8", "9"]]); + } + next(err); + }, + ); + }); + + it("dont count headers", function (next) { + parse( + dedent` + a,b,c + 1,2,3 + 4,5,6 + 7,8,9 + `, + { columns: true, from: 3 }, + (err, records) => { + if (!err) { + records.should.eql([{ a: "7", b: "8", c: "9" }]); + } + next(err); + }, + ); + }); + + it("not influenced by lines", function (next) { + parse( + dedent` + 1,2," + 3" + 4,5," + 6" + 7,8," + 9" + `, + { from: 3 }, + (err, records) => { + if (!err) { + records.should.eql([["7", "8", "\n9"]]); + } + next(err); + }, + ); + }); + + it("not influenced by record delimiter", function (next) { + parse( + dedent` + 1,2,3:4,5,6:7,8,9 + `, + { from: 3, record_delimiter: ":" }, + (err, records) => { + if (!err) { + records.should.eql([["7", "8", "9"]]); + } + next(err); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/option.from_line.coffee b/packages/csv-parse/test/option.from_line.coffee deleted file mode 100644 index e93830b78..000000000 --- a/packages/csv-parse/test/option.from_line.coffee +++ /dev/null @@ -1,130 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `from_line`', -> - - it 'validation', -> - parse '', from_line: 10, (->) - parse '', from_line: "10", (->) - parse '', from_line: null, (->) - parse '', from_line: undefined, (->) - (-> - parse '', from_line: -1, (->) - ).should.throw 'Invalid Option: from_line must be a positive integer greater than 0, got -1' - (-> - parse '', from_line: 0, (->) - ).should.throw 'Invalid Option: from_line must be a positive integer greater than 0, got 0' - (-> - parse '', from_line: "0", (->) - ).should.throw 'Invalid Option: from_line must be a positive integer greater than 0, got "0"' - (-> - parse '', from_line: true, (->) - ).should.throw 'Invalid Option: from_line must be an integer, got true' - (-> - parse '', from_line: false, (->) - ).should.throw 'Invalid Option: from_line must be an integer, got false' - (-> - parse '', from_line: 'oh no', (->) - ).should.throw 'Invalid Option: from_line must be an integer, got "oh no"' - - it 'start at defined position', (next) -> - parse """ - 1,2,3 - 4,5,6 - 7,8,9 - """, from_line: 3, (err, records) -> - records.should.eql [ - [ '7','8','9' ] - ] unless err - next err - - it 'handle lines with inconsistent number of fields', (next) -> - parse """ - a - 1,2,3 - """, from_line: 2, (err, records) -> - records.should.eql [ - ['1', '2', '3'] - ] unless err - next err - - it 'records with quoted line at the begining of line', (next) -> - parse """ - 1,2," - - 3" - 4,5," - 6" - 7,8," - 9" - """, from_line: 4, (err, records) -> - records.should.eql [ - [ '4','5','\n6' ] - [ '7','8','\n9' ] - ] unless err - next err - - it 'records with quoted line in the middle of line', (next) -> - parse """ - 1,2," - - 3" - 4,5," - 6" - 7,8," - 9" - """, from_line: 2, (err, records) -> - records.should.eql [ - [ '4','5','\n6' ] - [ '7','8','\n9' ] - ] unless err - next err - - it 'not influenced by `record_delimiter` option', (next) -> - parse """ - a,b,c:1,2, - 3:d,e,f:4,5, - 6:g,h,i:7,8, - 9 - """, from_line: 3, record_delimiter: ':', (err, records) -> - records.should.eql [ - [ 'g','h','i' ] - [ '7','8','\n9' ] - ] unless err - next err - - it 'no influenced by skip_empty_lines option', (next) -> - parse """ - a,b,c - - 1,2,3 - - 4,5,6 - - 7,8,9 - """, from_line: 5, skip_empty_lines: true, (err, records) -> - records.should.eql [ - ['4', '5', '6'] - ['7', '8', '9'] - ] unless err - next err - - it 'handle multiple bytes record delimiters', (next) -> - parse """ - a,b\r\nc,d\r\ne,f - """, from_line: 2, (err, records) -> - records.should.eql [ - [ 'c','d' ] - [ 'e','f' ] - ] unless err - next err - - it 'honors header', (next) -> - parse """ - x,y,z - x,y,z - a,b,c - 4,5,6 - """, from_line: 3, columns: true, (err, records) -> - records.should.eql [{ a: '4', b: '5', c: '6' }] unless err - next err diff --git a/packages/csv-parse/test/option.from_line.js b/packages/csv-parse/test/option.from_line.js new file mode 100644 index 000000000..ae2820261 --- /dev/null +++ b/packages/csv-parse/test/option.from_line.js @@ -0,0 +1,169 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; + +describe("Option `from_line`", function () { + it("validation", function () { + (() => { + parse("", { from_line: true }, () => {}); + }).should.throw("Invalid Option: from_line must be an integer, got true"); + (() => { + parse("", { from_line: false }, () => {}); + }).should.throw("Invalid Option: from_line must be an integer, got false"); + }); + + it("start at defined position", function (next) { + parse( + dedent` + 1,2,3 + 4,5,6 + 7,8,9 + `, + { from_line: 3 }, + (err, records) => { + if (!err) { + records.should.eql([["7", "8", "9"]]); + } + next(err); + }, + ); + }); + + it("handle lines with inconsistent number of fields", function (next) { + parse( + dedent` + a + 1,2,3 + `, + { from_line: 2 }, + (err, records) => { + if (!err) { + records.should.eql([["1", "2", "3"]]); + } + next(err); + }, + ); + }); + + it("records with quoted line at the begining of line", function (next) { + parse( + dedent`1,2," + + 3" + 4,5," + 6" + 7,8," + 9" + `, + { from_line: 4 }, + (err, records) => { + if (!err) { + records.should.eql([ + ["4", "5", "\n6"], + ["7", "8", "\n9"], + ]); + } + next(err); + }, + ); + }); + + it("records with quoted line in the middle of line", function (next) { + parse( + dedent` + 1,2," + + 3" + 4,5," + 6" + 7,8," + 9" + `, + { from_line: 2 }, + (err, records) => { + if (!err) { + records.should.eql([ + ["4", "5", "\n6"], + ["7", "8", "\n9"], + ]); + } + next(err); + }, + ); + }); + + it("not influenced by `record_delimiter` option", function (next) { + parse( + dedent` + a,b,c:1,2, + 3:d,e,f:4,5, + 6:g,h,i:7,8, + 9 + `, + { from_line: 3, record_delimiter: ":" }, + (err, records) => { + if (!err) { + records.should.eql([ + ["g", "h", "i"], + ["7", "8", "\n9"], + ]); + } + next(err); + }, + ); + }); + + it("no influenced by skip_empty_lines option", function (next) { + parse( + dedent` + a,b,c + + 1,2,3 + + 4,5,6 + + 7,8,9 + `, + { from_line: 5, skip_empty_lines: true }, + (err, records) => { + if (!err) { + records.should.eql([ + ["4", "5", "6"], + ["7", "8", "9"], + ]); + } + next(err); + }, + ); + }); + + it("handle multiple bytes record delimiters", function (next) { + parse(`a,b\r\nc,d\r\ne,f`, { from_line: 2 }, (err, records) => { + if (!err) { + records.should.eql([ + ["c", "d"], + ["e", "f"], + ]); + } + next(err); + }); + }); + + it("honors header", function (next) { + parse( + dedent` + x,y,z + x,y,z + a,b,c + 4,5,6 + `, + { from_line: 3, columns: true }, + (err, records) => { + if (!err) { + records.should.eql([{ a: "4", b: "5", c: "6" }]); + } + next(err); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/option.from_line.ts b/packages/csv-parse/test/option.from_line.ts new file mode 100644 index 000000000..d06b34717 --- /dev/null +++ b/packages/csv-parse/test/option.from_line.ts @@ -0,0 +1,187 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; + +describe("Option `from_line`", function () { + it("validation", function () { + parse("", { from_line: 10 }, () => {}); + parse("", { from_line: "10" }, () => {}); + parse("", { from_line: null }, () => {}); + parse("", { from_line: undefined }, () => {}); + (() => { + parse("", { from_line: -1 }, () => {}); + }).should.throw( + "Invalid Option: from_line must be a positive integer greater than 0, got -1", + ); + (() => { + parse("", { from_line: 0 }, () => {}); + }).should.throw( + "Invalid Option: from_line must be a positive integer greater than 0, got 0", + ); + (() => { + parse("", { from_line: "0" }, () => {}); + }).should.throw( + 'Invalid Option: from_line must be a positive integer greater than 0, got "0"', + ); + (() => { + parse("", { from_line: "oh no" }, () => {}); + }).should.throw( + 'Invalid Option: from_line must be an integer, got "oh no"', + ); + }); + + it("start at defined position", function (next) { + parse( + dedent` + 1,2,3 + 4,5,6 + 7,8,9 + `, + { from_line: 3 }, + (err, records) => { + if (!err) { + records.should.eql([["7", "8", "9"]]); + } + next(err); + }, + ); + }); + + it("handle lines with inconsistent number of fields", function (next) { + parse( + dedent` + a + 1,2,3 + `, + { from_line: 2 }, + (err, records) => { + if (!err) { + records.should.eql([["1", "2", "3"]]); + } + next(err); + }, + ); + }); + + it("records with quoted line at the begining of line", function (next) { + parse( + dedent`1,2," + + 3" + 4,5," + 6" + 7,8," + 9" + `, + { from_line: 4 }, + (err, records) => { + if (!err) { + records.should.eql([ + ["4", "5", "\n6"], + ["7", "8", "\n9"], + ]); + } + next(err); + }, + ); + }); + + it("records with quoted line in the middle of line", function (next) { + parse( + dedent` + 1,2," + + 3" + 4,5," + 6" + 7,8," + 9" + `, + { from_line: 2 }, + (err, records) => { + if (!err) { + records.should.eql([ + ["4", "5", "\n6"], + ["7", "8", "\n9"], + ]); + } + next(err); + }, + ); + }); + + it("not influenced by `record_delimiter` option", function (next) { + parse( + dedent` + a,b,c:1,2, + 3:d,e,f:4,5, + 6:g,h,i:7,8, + 9 + `, + { from_line: 3, record_delimiter: ":" }, + (err, records) => { + if (!err) { + records.should.eql([ + ["g", "h", "i"], + ["7", "8", "\n9"], + ]); + } + next(err); + }, + ); + }); + + it("no influenced by skip_empty_lines option", function (next) { + parse( + dedent` + a,b,c + + 1,2,3 + + 4,5,6 + + 7,8,9 + `, + { from_line: 5, skip_empty_lines: true }, + (err, records) => { + if (!err) { + records.should.eql([ + ["4", "5", "6"], + ["7", "8", "9"], + ]); + } + next(err); + }, + ); + }); + + it("handle multiple bytes record delimiters", function (next) { + parse(`a,b\r\nc,d\r\ne,f`, { from_line: 2 }, (err, records) => { + if (!err) { + records.should.eql([ + ["c", "d"], + ["e", "f"], + ]); + } + next(err); + }); + }); + + it("honors header", function (next) { + parse( + dedent` + x,y,z + x,y,z + a,b,c + 4,5,6 + `, + { from_line: 3, columns: true }, + (err, records) => { + if (!err) { + records.should.eql([{ a: "4", b: "5", c: "6" }]); + } + next(err); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/option.ignore_last_delimiters.coffee b/packages/csv-parse/test/option.ignore_last_delimiters.coffee deleted file mode 100644 index c2683f4ba..000000000 --- a/packages/csv-parse/test/option.ignore_last_delimiters.coffee +++ /dev/null @@ -1,63 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `ignore_last_delimiters`', -> - - describe 'validation & normalization', -> - - it 'default to `false`', -> - parse().options.ignore_last_delimiters.should.eql false - - it 'boolean', -> - parse(ignore_last_delimiters: true, columns: true).options.ignore_last_delimiters.should.eql true - parse(ignore_last_delimiters: false, columns: true).options.ignore_last_delimiters.should.eql false - - it 'integer', -> - parse(ignore_last_delimiters: 1).options.ignore_last_delimiters.should.eql 1 - parse(ignore_last_delimiters: 0).options.ignore_last_delimiters.should.eql false - - it 'throw error with invalid type', -> - (-> - parse(ignore_last_delimiters: 'invalid') - ).should.throw - code: 'CSV_INVALID_OPTION_IGNORE_LAST_DELIMITERS' - message: [ - 'Invalid option `ignore_last_delimiters`:' - 'the value must be a boolean value or an integer,' - 'got "invalid"' - ].join ' ' - - it 'requires columns', -> - (-> - parse(ignore_last_delimiters: true) - ).should.throw - code: 'CSV_IGNORE_LAST_DELIMITERS_REQUIRES_COLUMNS' - message: [ - 'The option `ignore_last_delimiters`' - 'requires the activation of the `columns` option' - ].join ' ' - - describe 'usage', -> - - it 'if true, get field number from columns', (next) -> - parse ''' - a,b,c - 1,2,3,4,5 - 11,22,33,44 - ''', ignore_last_delimiters: true, columns: true, (err, records) -> - records.should.eql [ - {a: '1', b: '2', c: '3,4,5'} - {a: '11', b: '22', c: '33,44'} - ] unless err - next err - - it 'if number, no need for columns', (next) -> - parse ''' - 1,2,3,4,5 - 11,22,33,44 - ''', ignore_last_delimiters: 3, (err, records) -> - records.should.eql [ - ['1','2','3,4,5'] - ['11','22','33,44'] - ] unless err - next err diff --git a/packages/csv-parse/test/option.ignore_last_delimiters.js b/packages/csv-parse/test/option.ignore_last_delimiters.js new file mode 100644 index 000000000..31fddd1f2 --- /dev/null +++ b/packages/csv-parse/test/option.ignore_last_delimiters.js @@ -0,0 +1,19 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `ignore_last_delimiters`", function () { + describe("validation & normalization", function () { + it("throw error with invalid type", function () { + (() => { + parse({ ignore_last_delimiters: "invalid" }); + }).should.throw({ + code: "CSV_INVALID_OPTION_IGNORE_LAST_DELIMITERS", + message: [ + "Invalid option `ignore_last_delimiters`:", + "the value must be a boolean value or an integer,", + 'got "invalid"', + ].join(" "), + }); + }); + }); +}); diff --git a/packages/csv-parse/test/option.ignore_last_delimiters.ts b/packages/csv-parse/test/option.ignore_last_delimiters.ts new file mode 100644 index 000000000..7dae52cfb --- /dev/null +++ b/packages/csv-parse/test/option.ignore_last_delimiters.ts @@ -0,0 +1,84 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; + +describe("Option `ignore_last_delimiters`", function () { + describe("validation & normalization", function () { + it("default to `false`", function () { + parse().options.ignore_last_delimiters.should.eql(false); + }); + + it("boolean", function () { + parse({ + ignore_last_delimiters: true, + columns: true, + }).options.ignore_last_delimiters.should.eql(true); + parse({ + ignore_last_delimiters: false, + columns: true, + }).options.ignore_last_delimiters.should.eql(false); + }); + + it("integer", function () { + parse({ + ignore_last_delimiters: 1, + }).options.ignore_last_delimiters.should.eql(1); + parse({ + ignore_last_delimiters: 0, + }).options.ignore_last_delimiters.should.eql(false); + }); + + it("requires columns", function () { + (() => { + parse({ ignore_last_delimiters: true }); + }).should.throw({ + code: "CSV_IGNORE_LAST_DELIMITERS_REQUIRES_COLUMNS", + message: [ + "The option `ignore_last_delimiters`", + "requires the activation of the `columns` option", + ].join(" "), + }); + }); + }); + + describe("usage", function () { + it("if true, get field number from columns", function (next) { + parse( + dedent` + a,b,c + 1,2,3,4,5 + 11,22,33,44 + `, + { ignore_last_delimiters: true, columns: true }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: "1", b: "2", c: "3,4,5" }, + { a: "11", b: "22", c: "33,44" }, + ]); + } + next(err); + }, + ); + }); + + it("if number, no need for columns", function (next) { + parse( + dedent` + 1,2,3,4,5 + 11,22,33,44 + `, + { ignore_last_delimiters: 3 }, + (err, records) => { + if (!err) { + records.should.eql([ + ["1", "2", "3,4,5"], + ["11", "22", "33,44"], + ]); + } + next(err); + }, + ); + }); + }); +}); diff --git a/packages/csv-parse/test/option.info.coffee b/packages/csv-parse/test/option.info.coffee deleted file mode 100644 index 3ab2fbde7..000000000 --- a/packages/csv-parse/test/option.info.coffee +++ /dev/null @@ -1,88 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `info`', -> - - describe 'validation', -> - - it 'check the columns value', -> - (-> - parse "", info: 'ok', (->) - ).should.throw 'Invalid Option: info must be true, got "ok"' - - describe 'true', -> - - it 'return info and records', (next) -> - parse ''' - a,b,c - d,e,f - g,h,i - ''', info: true, (err, records) -> - records.map ({record, info}) -> - should(record).be.an.Array() - should(info).be.an.Object() - next err - - it 'info properties', (next) -> - parse ''' - a,b,c - ''', info: true, (err, records) -> - {info} = records[0] - Object.keys(info).sort().should.eql [ - 'bytes', - 'columns', 'comment_lines', 'empty_lines', 'error', 'header', - 'index', 'invalid_field_length', 'lines', 'raw', 'records' - ] - next err - - it 'validate the `lines` and `bytes` properties', (next) -> - parse ''' - a,b,c - d,e,f - g,h,i - ''', info: true, (err, records) -> - records.map( - ({info}) -> [info.lines, info.bytes] - ).should.eql [[1, 6], [2, 12], [3, 17]] unless err - next err - - it 'with skip_empty_lines', (next) -> - parse ''' - - a,b,c - - d,e,f - - g,h,i - ''', info: true, skip_empty_lines: true, (err, records) -> - records.map( - ({info}) -> [info.lines, info.bytes] - ).should.eql [[2, 7], [4, 14], [6, 20]] unless err - next err - - it 'with comment', (next) -> - parse ''' - # line 1 - a,b,c - # line 2 - d,e,f - # line 3 - g,h,i - ''', info: true, comment: '#', (err, records) -> - records.map( - ({info}) -> [info.lines, info.bytes] - ).should.eql [[2, 15], [4, 30], [6, 44]] unless err - next err - - it 'with multiline records', (next) -> - parse ''' - a,b,c - d,"e - ",f - g,h,i - ''', info: true, (err, records) -> - records.map( - ({info}) -> [info.lines, info.bytes] - ).should.eql [[1, 6], [3, 15], [4, 20]] unless err - next err - diff --git a/packages/csv-parse/test/option.info.js b/packages/csv-parse/test/option.info.js new file mode 100644 index 000000000..9ff34615a --- /dev/null +++ b/packages/csv-parse/test/option.info.js @@ -0,0 +1,11 @@ +import { parse } from "../lib/index.js"; + +describe("Option `info`", function () { + describe("validation", function () { + it("check the columns value", function () { + (() => { + parse("", { info: "ok" }, () => {}); + }).should.throw('Invalid Option: info must be true, got "ok"'); + }); + }); +}); diff --git a/packages/csv-parse/test/option.info.ts b/packages/csv-parse/test/option.info.ts new file mode 100644 index 000000000..541685c3b --- /dev/null +++ b/packages/csv-parse/test/option.info.ts @@ -0,0 +1,149 @@ +import should from "should"; +import dedent from "dedent"; +import { parse, Info } from "../lib/index.js"; + +describe("Option `info`", function () { + describe("true", function () { + it("return info and records", function (next) { + parse( + dedent` + a,b,c + d,e,f + g,h,i + `, + { info: true }, + (err, records) => { + // @todo: improve type definition, setting option.info as true shal + // be reflected in the return records array. + (records as unknown as { record: string[]; info: Info }[]).map( + ({ record, info }) => { + should(record).be.an.Array(); + should(info).be.an.Object(); + }, + ); + next(err); + }, + ); + }); + + it("info properties", function (next) { + parse(`a,b,c`, { info: true }, (err, records) => { + const { info } = records[0] as unknown as { + record: string[]; + info: Info; + }; + Object.keys(info) + .sort() + .should.eql([ + "bytes", + "columns", + "comment_lines", + "empty_lines", + "error", + "header", + "index", + "invalid_field_length", + "lines", + "raw", + "records", + ]); + next(err); + }); + }); + + it("validate the `lines` and `bytes` properties", function (next) { + parse( + dedent` + a,b,c + d,e,f + g,h,i + `, + { info: true }, + (err, records) => { + if (err) return next(err); + (records as unknown as { record: string[]; info: Info }[]) + .map(({ info }) => [info.lines, info.bytes]) + .should.eql([ + [1, 6], + [2, 12], + [3, 17], + ]); + next(); + }, + ); + }); + + it("with skip_empty_lines", function (next) { + parse( + "\n" + + dedent` + a,b,c + + d,e,f + + g,h,i + `, + { info: true, skip_empty_lines: true }, + (err, records) => { + if (err) next(err); + (records as unknown as { record: string[]; info: Info }[]) + .map(({ info }) => [info.lines, info.bytes]) + .should.eql([ + [2, 7], + [4, 14], + [6, 20], + ]); + next(); + }, + ); + }); + + it("with comment", function (next) { + parse( + dedent` + # line 1 + a,b,c + # line 2 + d,e,f + # line 3 + g,h,i + `, + { info: true, comment: "#" }, + (err, records) => { + if (err) next(err); + (records as unknown as { record: string[]; info: Info }[]) + .map(({ info }) => [info.lines, info.bytes]) + .should.eql([ + [2, 15], + [4, 30], + [6, 44], + ]); + next(); + }, + ); + }); + + it("with multiline records", function (next) { + parse( + dedent` + a,b,c + d,"e + ",f + g,h,i + `, + { info: true }, + (err, records) => { + if (err) return next(err); + (records as unknown as { record: string[]; info: Info }[]) + .map(({ info }) => [info.lines, info.bytes]) + .should.eql([ + [1, 6], + [3, 15], + [4, 20], + ]); + next(); + }, + ); + }); + }); +}); diff --git a/packages/csv-parse/test/option.ltrim.coffee b/packages/csv-parse/test/option.ltrim.coffee deleted file mode 100644 index 3c9d2d1ee..000000000 --- a/packages/csv-parse/test/option.ltrim.coffee +++ /dev/null @@ -1,81 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'Option `ltrim`', -> - - it 'plain text', (next) -> - parse """ - a b, c d - e f, g h - """, quote: "'", escape: "'", trim: true, (err, records) -> - records.should.eql [['a b', 'c d'],['e f', 'g h']] unless err - next err - - it 'before quote', (next) -> - data = ''' - 'a', 'b' - 'c', 'd' - ''' - parser = parse quote: "'", escape: "'", trim: true, (err, records) -> - records.should.eql [["a", "b"],["c", "d"]] unless err - next err - parser.write chr for chr in data - parser.end() - - it 'quote followed by escape', (next) -> - # 1st line: with start of file - # 2nd line: with field delimiter - # 3rd line: with record delimiter - parse """ - '''a','''b' - '''c', '''d' - '''e','''f' - """, quote: "'", escape: "'", trim: true, (err, records) -> - records.should.eql [["'a", "'b"],["'c", "'d"],["'e", "'f"]] unless err - next err - - it 'with whitespaces around quotes', (next) -> - data = ''' - " a b", " c d" - " e f", " g h" - ''' - parser = parse ltrim: true, (err, records) -> - records.should.eql [[' a b', ' c d'],[' e f', ' g h']] unless err - next err - parser.write chr for chr in data - parser.end() - - it 'with char after whitespaces', (next) -> - data = ''' - x " a b",x " c d" - x " e f", x " g h" - ''' - parser = parse ltrim: true, (err) -> - assert_error err, - message: 'Invalid Opening Quote: a quote is found on field 0 at line 1, value is "x "' - code: 'INVALID_OPENING_QUOTE' - field: 'x ' - next() - parser.write chr for chr in data - parser.end() - - it 'should work on last field', (next) -> - records = [] - parser = parse ltrim: true - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'end', -> - records.should.eql [ - [ 'FIELD_1','FIELD_2' ] - [ '20322051544','a' ] - [ '28392898392',' ' ] - ] - next() - parser.write """ - FIELD_1, FIELD_2 - 20322051544, a - 28392898392, " " - """ - parser.end() diff --git a/packages/csv-parse/test/option.ltrim.js b/packages/csv-parse/test/option.ltrim.js new file mode 100644 index 000000000..57f39168b --- /dev/null +++ b/packages/csv-parse/test/option.ltrim.js @@ -0,0 +1,13 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `ltrim`", function () { + it("validation", function () { + (() => { + parse("", { ltrim: 1 }, () => {}); + }).should.throw("Invalid Option: ltrim must be a boolean, got 1"); + (() => { + parse("", { ltrim: "true" }, () => {}); + }).should.throw('Invalid Option: ltrim must be a boolean, got "true"'); + }); +}); diff --git a/packages/csv-parse/test/option.ltrim.ts b/packages/csv-parse/test/option.ltrim.ts new file mode 100644 index 000000000..7e404b281 --- /dev/null +++ b/packages/csv-parse/test/option.ltrim.ts @@ -0,0 +1,133 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; + +describe("Option `ltrim`", function () { + it("validation", function () { + parse("", { ltrim: true }, () => {}); + parse("", { ltrim: false }, () => {}); + parse("", { ltrim: null }, () => {}); + parse("", { ltrim: undefined }, () => {}); + }); + + it("plain text", function (next) { + parse( + ` a b, c d\n e f, g h`, + { quote: "'", escape: "'", trim: true }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a b", "c d"], + ["e f", "g h"], + ]); + } + next(err); + }, + ); + }); + + it("before quote", function (next) { + const data = ` 'a', 'b'\n 'c', 'd'`; + const parser = parse( + { quote: "'", escape: "'", trim: true }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b"], + ["c", "d"], + ]); + } + next(err); + }, + ); + for (const chr of data) { + parser.write(chr); + } + parser.end(); + }); + + it("quote followed by escape", function (next) { + // 1st line: with start of file + // 2nd line: with field delimiter + // 3rd line: with record delimiter + parse( + dedent` + '''a','''b' + '''c', '''d' + '''e','''f' + `, + { quote: "'", escape: "'", trim: true }, + (err, records) => { + if (!err) { + records.should.eql([ + ["'a", "'b"], + ["'c", "'d"], + ["'e", "'f"], + ]); + } + next(err); + }, + ); + }); + + it("with whitespaces around quotes", function (next) { + const data = ` " a b", " c d"\n " e f", " g h"`; + const parser = parse({ ltrim: true }, (err, records) => { + if (!err) { + records.should.eql([ + [" a b", " c d"], + [" e f", " g h"], + ]); + } + next(err); + }); + for (const chr of data) { + parser.write(chr); + } + parser.end(); + }); + + it("with char after whitespaces", function (next) { + const data = ` x " a b",x " c d"\nx " e f", x " g h"`; + const parser = parse({ ltrim: true }, (err) => { + if (!err) return Error("Invalid assertion"); + assert_error(err, { + message: + 'Invalid Opening Quote: a quote is found on field 0 at line 1, value is "x "', + code: "INVALID_OPENING_QUOTE", + field: "x ", + }); + next(); + }); + for (const chr of data) { + parser.write(chr); + } + parser.end(); + }); + + it("should work on last field", function (next) { + const records: string[] = []; + const parser = parse({ ltrim: true }); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + records.should.eql([ + ["FIELD_1", "FIELD_2"], + ["20322051544", "a"], + ["28392898392", " "], + ]); + next(); + }); + parser.write(dedent` + FIELD_1, FIELD_2 + 20322051544, a + 28392898392, " " + `); + parser.end(); + }); +}); diff --git a/packages/csv-parse/test/option.max_record_size.coffee b/packages/csv-parse/test/option.max_record_size.coffee deleted file mode 100644 index edd6dd495..000000000 --- a/packages/csv-parse/test/option.max_record_size.coffee +++ /dev/null @@ -1,32 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'Option `max_record_size`', -> - - it 'validation', -> - parse '', max_record_size: 10, (->) - parse '', max_record_size: "10", (->) - (-> - parse '', max_record_size: -1, (->) - ).should.throw 'Invalid Option: max_record_size must be a positive integer, got -1' - (-> - parse '', max_record_size: true, (->) - ).should.throw 'Invalid Option: max_record_size must be a positive integer, got true' - (-> - parse '', max_record_size: 'oh no', (->) - ).should.throw 'Invalid Option: max_record_size must be a positive integer, got "oh no"' - - it 'field exceed limit', (next) -> - parse ''' - 12,34,56 - ab,cd,ef - hi,xxxxxxxxxxxxxxx,jk - lm,no,pq - ''', max_record_size: 10, (err) -> - assert_error err, - message: 'Max Record Size: record exceed the maximum number of tolerated bytes of 10 at line 3' - code: 'CSV_MAX_RECORD_SIZE' - column: 1, empty_lines: 0, header: false, index: 1, invalid_field_length: 0, - quoting: false, lines: 3, records: 2 - next() diff --git a/packages/csv-parse/test/option.max_record_size.js b/packages/csv-parse/test/option.max_record_size.js new file mode 100644 index 000000000..cf3e3e161 --- /dev/null +++ b/packages/csv-parse/test/option.max_record_size.js @@ -0,0 +1,12 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `max_record_size`", function () { + it("validation", function () { + (() => { + parse("", { max_record_size: true }, () => {}); + }).should.throw( + "Invalid Option: max_record_size must be a positive integer, got true", + ); + }); +}); diff --git a/packages/csv-parse/test/option.max_record_size.ts b/packages/csv-parse/test/option.max_record_size.ts new file mode 100644 index 000000000..2ce6d4014 --- /dev/null +++ b/packages/csv-parse/test/option.max_record_size.ts @@ -0,0 +1,50 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; + +describe("Option `max_record_size`", function () { + it("validation", function () { + parse("", { max_record_size: 10 }, () => {}); + parse("", { max_record_size: "10" }, () => {}); + (() => { + parse("", { max_record_size: -1 }, () => {}); + }).should.throw( + "Invalid Option: max_record_size must be a positive integer, got -1", + ); + (() => { + parse("", { max_record_size: "oh no" }, () => {}); + }).should.throw( + 'Invalid Option: max_record_size must be a positive integer, got "oh no"', + ); + }); + + it("field exceed limit", function (next) { + parse( + dedent` + 12,34,56 + ab,cd,ef + hi,xxxxxxxxxxxxxxx,jk + lm,no,pq + `, + { max_record_size: 10 }, + (err) => { + if (!err) return Error("Invalid assertion"); + assert_error(err, { + message: + "Max Record Size: record exceed the maximum number of tolerated bytes of 10 at line 3", + code: "CSV_MAX_RECORD_SIZE", + column: 1, + empty_lines: 0, + header: false, + index: 1, + invalid_field_length: 0, + quoting: false, + lines: 3, + records: 2, + }); + next(); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/option.objname.coffee b/packages/csv-parse/test/option.objname.coffee deleted file mode 100644 index a3b914d9f..000000000 --- a/packages/csv-parse/test/option.objname.coffee +++ /dev/null @@ -1,147 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `objname`', -> - - describe 'validation', -> - - it 'basic', -> - parse '', objname: 'sth', columns: true, (->) - parse '', objname: Buffer.from('sth'), columns: true, (->) - parse '', objname: 1, (->) - parse '', objname: null, (->) - parse '', objname: undefined, (->) - (-> - parse '', objname: '', (->) - ).should.throw 'Invalid Option: objname must be a non empty string' - (-> - parse '', objname: Buffer.from(''), (->) - ).should.throw 'Invalid Option: objname must be a non empty buffer' - (-> - parse '', objname: true, (->) - ).should.throw 'Invalid Option: objname must be a string or a buffer, got true' - - it 'field require columns', -> - (-> - parse '', objname: 'field', (->) - ).should.throw [ - 'Invalid Option:' - 'objname field must be combined with columns' - 'or be defined as an index' - ].join ' ' - - it 'index incompatible with columns', -> - (-> - parse '', objname: 1, columns: true, (->) - ).should.throw [ - 'Invalid Option:' - 'objname index cannot be combined with columns' - 'or be defined as a field' - ].join ' ' - - describe 'map to a field', -> - - it 'convert a buffer to a column name', (next) -> - parse ''' - a,b,c - ''', objname: Buffer.from('h1'), columns: ['h1', 'h2', 'h3'], (err, records) -> - records.should.eql( - 'a': - 'h1': 'a' - 'h2': 'b' - 'h3': 'c' - ) unless err - next err - - it 'should print object of objects with properties using value of given column from columns', (next) -> - parse ''' - a,b,c - d,e,f - ''', objname: "FIELD_1", columns: ['FIELD_1', 'FIELD_2', 'FIELD_3'], (err, records) -> - return next err if err - records.should.eql - 'a': - 'FIELD_1': 'a' - 'FIELD_2': 'b' - 'FIELD_3': 'c' - 'd': - 'FIELD_1': 'd' - 'FIELD_2': 'e' - 'FIELD_3': 'f' - next err - - it 'should print object of objects with properties using value of given column from header record', (next) -> - parse ''' - FIELD_1,FIELD_2,FIELD_3 - a,b,c - d,e,f - ''', objname: "FIELD_1", columns: true, (err, records) -> - return next err if err - records.should.eql - 'a': - 'FIELD_1': 'a' - 'FIELD_2': 'b' - 'FIELD_3': 'c' - 'd': - 'FIELD_1': 'd' - 'FIELD_2': 'e' - 'FIELD_3': 'f' - next() - - it 'combined with info', (next) -> - parse ''' - FIELD_1,FIELD_2,FIELD_3 - a,b,c - d,e,f - ''', objname: 'FIELD_2', columns: true, info: true, (err, records) -> - return next err if err - records.should.match - 'b': - record: - 'FIELD_1': 'a' - 'FIELD_2': 'b' - 'FIELD_3': 'c' - info: - bytes: 30 - lines: 2 - 'e': - record: - 'FIELD_1': 'd' - 'FIELD_2': 'e' - 'FIELD_3': 'f' - info: - bytes: 35 - lines: 3 - next() - - describe 'map to an index', -> - - it 'get value associated with index', (next) -> - parse ''' - a,b,c - d,e,f - ''', objname: 1, (err, records) -> - return next err if err - records.should.eql - 'b': [ 'a', 'b', 'c' ] - 'e': [ 'd', 'e', 'f' ] - next() - - it 'combined with info', (next) -> - parse ''' - a,b,c - d,e,f - ''', objname: 1, info: true, (err, records) -> - return next err if err - records.should.match - 'b': - record: [ 'a', 'b', 'c' ] - info: - bytes: 6 - lines: 1 - 'e': - record: [ 'd', 'e', 'f' ] - info: - bytes: 11 - lines: 2 - next() diff --git a/packages/csv-parse/test/option.objname.js b/packages/csv-parse/test/option.objname.js new file mode 100644 index 000000000..5329dbdda --- /dev/null +++ b/packages/csv-parse/test/option.objname.js @@ -0,0 +1,14 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `objname`", function () { + describe("validation", function () { + it("does not accept boolean", function () { + (() => { + parse("", { objname: true }, () => {}); + }).should.throw( + "Invalid Option: objname must be a string or a buffer, got true", + ); + }); + }); +}); diff --git a/packages/csv-parse/test/option.objname.ts b/packages/csv-parse/test/option.objname.ts new file mode 100644 index 000000000..cdaa7f261 --- /dev/null +++ b/packages/csv-parse/test/option.objname.ts @@ -0,0 +1,208 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; + +describe("Option `objname`", function () { + describe("validation", function () { + it("basic", function () { + parse("", { objname: "sth", columns: true }, () => {}); + parse("", { objname: Buffer.from("sth"), columns: true }, () => {}); + parse("", { objname: 1 }, () => {}); + parse("", { objname: null }, () => {}); + parse("", { objname: undefined }, () => {}); + (() => { + parse("", { objname: "" }, () => {}); + }).should.throw("Invalid Option: objname must be a non empty string"); + (() => { + parse("", { objname: Buffer.from("") }, () => {}); + }).should.throw("Invalid Option: objname must be a non empty buffer"); + }); + + it("field require columns", function () { + (() => { + parse("", { objname: "field" }, () => {}); + }).should.throw( + [ + "Invalid Option:", + "objname field must be combined with columns", + "or be defined as an index", + ].join(" "), + ); + }); + + it("index incompatible with columns", function () { + (() => { + parse("", { objname: 1, columns: true }, () => {}); + }).should.throw( + [ + "Invalid Option:", + "objname index cannot be combined with columns", + "or be defined as a field", + ].join(" "), + ); + }); + }); + + describe("map to a field", function () { + it("convert a buffer to a column name", function (next) { + parse( + `a,b,c`, + { objname: Buffer.from("h1"), columns: ["h1", "h2", "h3"] }, + (err, records) => { + if (!err) { + records.should.eql({ + a: { + h1: "a", + h2: "b", + h3: "c", + }, + }); + } + next(err); + }, + ); + }); + + it("should print object of objects with properties using value of given column from columns", function (next) { + parse( + dedent` + a,b,c + d,e,f + `, + { objname: "FIELD_1", columns: ["FIELD_1", "FIELD_2", "FIELD_3"] }, + (err, records) => { + if (err) return next(err); + records.should.eql({ + a: { + FIELD_1: "a", + FIELD_2: "b", + FIELD_3: "c", + }, + d: { + FIELD_1: "d", + FIELD_2: "e", + FIELD_3: "f", + }, + }); + next(err); + }, + ); + }); + + it("should print object of objects with properties using value of given column from header record", function (next) { + parse( + dedent` + FIELD_1,FIELD_2,FIELD_3 + a,b,c + d,e,f + `, + { objname: "FIELD_1", columns: true }, + (err, records) => { + if (err) return next(err); + records.should.eql({ + a: { + FIELD_1: "a", + FIELD_2: "b", + FIELD_3: "c", + }, + d: { + FIELD_1: "d", + FIELD_2: "e", + FIELD_3: "f", + }, + }); + next(); + }, + ); + }); + + it("combined with info", function (next) { + parse( + dedent` + FIELD_1,FIELD_2,FIELD_3 + a,b,c + d,e,f + `, + { objname: "FIELD_2", columns: true, info: true }, + (err, records) => { + if (err) return next(err); + records.should.match({ + b: { + record: { + FIELD_1: "a", + FIELD_2: "b", + FIELD_3: "c", + }, + info: { + bytes: 30, + lines: 2, + }, + }, + e: { + record: { + FIELD_1: "d", + FIELD_2: "e", + FIELD_3: "f", + }, + info: { + bytes: 35, + lines: 3, + }, + }, + }); + next(); + }, + ); + }); + }); + + describe("map to an index", function () { + it("get value associated with index", function (next) { + parse( + dedent` + a,b,c + d,e,f + `, + { objname: 1 }, + (err, records) => { + if (err) return next(err); + records.should.eql({ + b: ["a", "b", "c"], + e: ["d", "e", "f"], + }); + next(); + }, + ); + }); + + it("combined with info", function (next) { + parse( + dedent` + a,b,c + d,e,f + `, + { objname: 1, info: true }, + (err, records) => { + if (err) return next(err); + records.should.match({ + b: { + record: ["a", "b", "c"], + info: { + bytes: 6, + lines: 1, + }, + }, + e: { + record: ["d", "e", "f"], + info: { + bytes: 11, + lines: 2, + }, + }, + }); + next(); + }, + ); + }); + }); +}); diff --git a/packages/csv-parse/test/option.on_record.coffee b/packages/csv-parse/test/option.on_record.coffee deleted file mode 100644 index 18ae6ec3b..000000000 --- a/packages/csv-parse/test/option.on_record.coffee +++ /dev/null @@ -1,105 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'Option `on_record`', -> - - it 'validate', -> - (-> - parse on_record: true - ).should.throw - message: 'Invalid option `on_record`: expect a function, got true' - code: 'CSV_INVALID_OPTION_ON_RECORD' - - describe 'usage', -> - - it 'alter records', (next) -> - parse "a,b", on_record: (record) -> - [record[1], record[0]] - , (err, records) -> - records.should.eql [ ['b', 'a'] ] unless err - next err - - it 'filter records', (next) -> - parse "a,b\nc,d\ne,f", on_record: (record, {lines}) -> - if lines is 2 then null else record - , (err, records) -> - records.should.eql [ ['a', 'b'], ['e', 'f'] ] unless err - next err - - it 'errors with callback', (next) -> - parse "a,b\nc,d\ne,f", - on_record: (record, {lines}) -> - if lines is 2 then throw Error 'Error thrown on line 2' else record - , (err, records) -> - err.message.should.eql 'Error thrown on line 2' - next() - - it 'errors with events', (next) -> - parser = parse "a,a,a\nc,d\ne,f" - parser.on 'error', (err) -> - err.message.should.eql 'Invalid Record Length: expect 3, got 2 on line 2' - next() - parser.on 'end', () -> - next Error 'Should not be called' - - it 'errors not handled by skip_records_with_error', (next) -> - parse "a,b\nc,d\ne,f", - on_record: (record, {lines}) -> - if lines is 2 then throw Error 'Error thrown on line 2' else record - skip_records_with_error: true - , (err, records) -> - err.message.should.eql 'Error thrown on line 2' - next() - - describe 'context', -> - - it 'properties', (next) -> - parse "a,b", - on_record: (record, context) -> - should(context.raw).be.undefined() - Object.keys(context).sort() - skip_records_with_error: true - , (err, records) -> - records.should.eql [[ - 'bytes', - 'columns', 'comment_lines', 'empty_lines', 'error', 'header', - 'index', 'invalid_field_length', 'lines', 'raw', 'records' - ]] - next() - - it 'properties with `columns: true` and `raw: true`', (next) -> - parse "a,b\n1,2\n3,4", - columns: true - raw: true - on_record: (record, context) -> - if context.lines is 2 - context.raw.should.eql '1,2\n' - else if context.lines is 3 - context.raw.should.eql '3,4' - Object.keys(context).sort() - skip_records_with_error: true - , (err, records) -> - records.shift().should.eql [ - 'bytes', - 'columns', 'comment_lines', 'empty_lines', 'error', 'header', - 'index', 'invalid_field_length', 'lines', 'raw', 'records' - ] - next() - - it 'values', (next) -> - parse "a,b\nc,d", - on_record: (record, context) -> - context - skip_records_with_error: true - , (err, records) -> - records.should.eql [ - bytes: 4, - columns: false, comment_lines: 0, empty_lines: 0, error: undefined, header: false - index: 2, invalid_field_length: 0, lines: 1, raw: undefined, records: 1 - , - bytes: 7, - columns: false, comment_lines: 0, empty_lines: 0, error: undefined, header: false - index: 2, invalid_field_length: 0, lines: 2, raw: undefined, records: 2 - ] - next() diff --git a/packages/csv-parse/test/option.on_record.js b/packages/csv-parse/test/option.on_record.js new file mode 100644 index 000000000..078ec6650 --- /dev/null +++ b/packages/csv-parse/test/option.on_record.js @@ -0,0 +1,13 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `on_record`", function () { + it("validate", function () { + (() => { + parse({ on_record: true }); + }).should.throw({ + message: "Invalid option `on_record`: expect a function, got true", + code: "CSV_INVALID_OPTION_ON_RECORD", + }); + }); +}); diff --git a/packages/csv-parse/test/option.on_record.ts b/packages/csv-parse/test/option.on_record.ts new file mode 100644 index 000000000..7f3718b7e --- /dev/null +++ b/packages/csv-parse/test/option.on_record.ts @@ -0,0 +1,208 @@ +import should from "should"; +import { parse, CastingContext } from "../lib/index.js"; + +describe("Option `on_record`", function () { + describe("usage", function () { + it("alter records", function (next) { + parse( + "a,b", + { + on_record: (record) => { + return [record[1], record[0]]; + }, + }, + (err, records) => { + if (!err) { + records.should.eql([["b", "a"]]); + } + next(err); + }, + ); + }); + + it("filter records", function (next) { + parse( + "a,b\nc,d\ne,f", + { + on_record: (record, { lines }) => { + if (lines === 2) return null; + else return record; + }, + }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b"], + ["e", "f"], + ]); + } + next(err); + }, + ); + }); + + it("errors with callback", function (next) { + parse( + "a,b\nc,d\ne,f", + { + on_record: (record, { lines }) => { + if (lines === 2) throw Error("Error thrown on line 2"); + else return record; + }, + }, + (err) => { + if (!err) return next("Invalid assertion"); + err.message.should.eql("Error thrown on line 2"); + next(); + }, + ); + }); + + it("errors with events", function (next) { + const parser = parse("a,a,a\nc,d\ne,f"); + parser.on("error", (err) => { + err.message.should.eql( + "Invalid Record Length: expect 3, got 2 on line 2", + ); + next(); + }); + parser.on("end", () => { + next(Error("Should not be called")); + }); + }); + + it("errors not handled by skip_records_with_error", function (next) { + parse( + "a,b\nc,d\ne,f", + { + on_record: (record, { lines }) => { + if (lines === 2) throw Error("Error thrown on line 2"); + else return record; + }, + skip_records_with_error: true, + }, + (err) => { + if (!err) return next("Invalid assertion"); + err.message.should.eql("Error thrown on line 2"); + next(); + }, + ); + }); + }); + + describe("context", function () { + it("properties", function (next) { + parse( + "a,b", + { + on_record: (record, context) => { + should(context.raw).be.undefined(); + return Object.keys(context).sort(); + }, + skip_records_with_error: true, + }, + (err, records) => { + records.should.eql([ + [ + "bytes", + "columns", + "comment_lines", + "empty_lines", + "error", + "header", + "index", + "invalid_field_length", + "lines", + "raw", + "records", + ], + ]); + next(); + }, + ); + }); + + it("properties with `columns: true` and `raw: true`", function (next) { + parse( + "a,b\n1,2\n3,4", + { + columns: true, + raw: true, + on_record: (record, context) => { + if (context.lines === 2) { + context.raw?.should.eql("1,2\n"); + } else if (context.lines === 3) { + context.raw?.should.eql("3,4"); + } + return Object.keys(context).sort(); + }, + skip_records_with_error: true, + }, + (err, records) => { + if (err) return next(err); + (records as unknown[] as { record: string; raw: string }[]) + .shift() + ?.should.eql([ + "bytes", + "columns", + "comment_lines", + "empty_lines", + "error", + "header", + "index", + "invalid_field_length", + "lines", + "raw", + "records", + ]); + next(); + }, + ); + }); + + it("values", function (next) { + parse( + "a,b\n1,2\n3,4", + { + on_record: (record, context) => { + record; + return context; + }, + columns: true, // todo, required to satisfy TS type + skip_records_with_error: true, + }, + (err, records) => { + records.should.eql([ + { + bytes: 8, + columns: [{ name: "a" }, { name: "b" }], + comment_lines: 0, + empty_lines: 0, + error: undefined, + header: false, + index: 2, + invalid_field_length: 0, + lines: 2, + raw: undefined, + records: 1, + }, + { + bytes: 11, + columns: [{ name: "a" }, { name: "b" }], + comment_lines: 0, + empty_lines: 0, + error: undefined, + header: false, + index: 2, + invalid_field_length: 0, + lines: 3, + raw: undefined, + records: 2, + }, + ]); + next(); + }, + ); + }); + }); +}); diff --git a/packages/csv-parse/test/option.on_skip.coffee b/packages/csv-parse/test/option.on_skip.coffee deleted file mode 100644 index 2948bc06d..000000000 --- a/packages/csv-parse/test/option.on_skip.coffee +++ /dev/null @@ -1,36 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'Option `on_skip`', -> - - it 'validation', -> - parse '', on_skip: (->), (->) - (-> - parse '', on_skip: 1, (->) - ).should.throw 'Invalid Option: on_skip must be a function, got 1' - - it 'handle "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH" with bom (fix #411)', (next) -> - errors = 0 - parser = parse - bom: true - skip_records_with_error: true - on_skip: (err) -> - assert_error err, - message: 'Invalid Record Length: expect 4, got 3 on line 2' - code: 'CSV_RECORD_INCONSISTENT_FIELDS_LENGTH' - record: ['1', '2', '3'] - errors++ - , (err, records) -> - records.should.eql [ - ['a', 'b', 'c', 'd'] - ['e', 'f', 'g', 'h'] - ] unless err - errors.should.eql 1 - next err - parser.write ''' - a,b,c,d - 1,2,3 - e,f,g,h - ''' - parser.end() diff --git a/packages/csv-parse/test/option.on_skip.js b/packages/csv-parse/test/option.on_skip.js new file mode 100644 index 000000000..e30b58d2e --- /dev/null +++ b/packages/csv-parse/test/option.on_skip.js @@ -0,0 +1,10 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `on_skip`", function () { + it("validation", function () { + (() => { + parse("", { on_skip: 1 }, () => {}); + }).should.throw("Invalid Option: on_skip must be a function, got 1"); + }); +}); diff --git a/packages/csv-parse/test/option.on_skip.ts b/packages/csv-parse/test/option.on_skip.ts new file mode 100644 index 000000000..42cb23352 --- /dev/null +++ b/packages/csv-parse/test/option.on_skip.ts @@ -0,0 +1,69 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; + +describe("Option `on_skip`", function () { + it("validation", function () { + parse("", { on_skip: () => {} }, () => {}); + }); + + it("catch thrown error", function (next) { + parse( + dedent` + a,b,c,d + invalid + e,f,g,h + `, + { + bom: true, + skip_records_with_error: true, + on_skip: () => { + throw Error("Catchme"); + }, + }, + (err) => { + if (!err) return next(new Error("Invalid assessment")); + err.message.should.eql("Catchme"); + next(); + }, + ); + }); + + it('handle "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH" with bom (fix #411)', function (next) { + let errors = 0; + const parser = parse( + { + bom: true, + skip_records_with_error: true, + on_skip: (err) => { + if (!err) throw Error("Invalid assessment"); + assert_error(err, { + message: "Invalid Record Length: expect 4, got 3 on line 2", + code: "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", + record: ["1", "2", "3"], + }); + errors++; + }, + }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c", "d"], + ["e", "f", "g", "h"], + ]); + } + errors.should.eql(1); + next(err); + }, + ); + parser.write( + dedent` + a,b,c,d + 1,2,3 + e,f,g,h + `, + ); + parser.end(); + }); +}); diff --git a/packages/csv-parse/test/option.quote.coffee b/packages/csv-parse/test/option.quote.coffee deleted file mode 100644 index f3b0dc93c..000000000 --- a/packages/csv-parse/test/option.quote.coffee +++ /dev/null @@ -1,224 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'Option `quote`', -> - - it 'is compatible with buffer size', (next) -> - parser = parse escape: '$', quote: '::::::', (err, data) -> - data.should.eql [ - [ '1', '2::::::2', '3' ] - [ 'b', 'c', 'd' ] - ] - next err - parser.write c for c in """ - 1,::::::2$::::::2::::::,3 - b,c,d - """ - parser.end() - - it 'default', -> - parser = parse() - parser.options.quote.should.eql Buffer.from('"') - - it 'normalize', -> - parser = parse quote: true - parser.options.quote.should.eql Buffer.from('"') - parser = parse quote: false - (parser.options.quote is null).should.be.true() - parser = parse quote: null - (parser.options.quote is null).should.be.true() - - it 'with default', (next) -> - data = ''' - abc,"123",def,"456" - hij,klm,"789",nop - ''' - parser = parse (err, records) -> - return next err if err - records.should.eql [ - [ 'abc','123','def','456' ] - [ 'hij','klm','789','nop' ] - ] - next() - parser.write chr for chr in data - parser.end() - - it 'with fields containing delimiters', (next) -> - parse """ - 20322051544,",1979.0,8.8017226E7,ABC,45,2000-01-01",1,2,3,4 - 28392898392,1974.0,8.8392926E7,DEF,23,2050-11-27 - "28392898392,1974.0","8.8392926E7","DEF,23,2050-11-27,",4,5,6 - """, (err, records) -> - return next err if err - records.should.eql [ - [ '20322051544',',1979.0,8.8017226E7,ABC,45,2000-01-01','1','2','3','4' ] - [ '28392898392','1974.0','8.8392926E7','DEF','23','2050-11-27' ] - [ '28392898392,1974.0','8.8392926E7','DEF,23,2050-11-27,','4','5','6' ] - ] - next() - - it 'empty value', (next) -> - parse """ - 20322051544,"",8.8017226E7,45,"" - "",1974,8.8392926E7,"","" - """, (err, records) -> - return next err if err - records.should.eql [ - [ '20322051544','','8.8017226E7','45','' ] - [ '','1974','8.8392926E7','','' ] - ] - next() - - it 'values containing quotes and double quotes escape', (next) -> - parse ''' - AB,"""",CD,"""hi""" - "",JK,"","" - ''', (err, records) -> - return next err if err - records.should.eql [ - [ 'AB','"','CD','"hi"' ] - [ '','JK','','' ] - ] - next() - - it 'only containing quotes and double quotes escape', (next) -> - data = ''' - """" - """" - ''' - parser = parse (err, records) -> - return next err if err - records.should.eql [ - [ '"' ] - [ '"' ] - ] - next() - parser.write chr for chr in data - parser.end() - - it 'line breaks inside quotes', (next) -> - parse """ - 20322051544," - ",8.8017226E7,45," - ok - " - " - ",1974,8.8392926E7,""," - " - """, (err, records) -> - records.should.eql [ - [ '20322051544','\n','8.8017226E7','45','\nok\n' ] - [ '\n','1974','8.8392926E7','','\n' ] - ] unless err - next err - - describe 'disabled', -> - - it 'if empty', (next) -> - parse """ - a,b,c - 1,r"2"d"2",3 - """, quote: '', (err, records) -> - records.should.eql [['a','b','c'],['1','r"2"d"2"','3']] unless err - next err - - it 'if null', (next) -> - parse """ - a,b,c - 1,r"2"d"2",3 - """, quote: null, (err, records) -> - records.should.eql [['a','b','c'],['1','r"2"d"2"','3']] unless err - next err - - it 'if false', (next) -> - parse """ - a,b,c - 1,r"2"d"2",3 - """, quote: null, (err, records) -> - records.should.eql [['a','b','c'],['1','r"2"d"2"','3']] unless err - next err - - describe 'options', -> - - it 'with multiple chars', (next) -> - parse """ - $$a$$,b,$$c$$ - 1,$$2$$,3 - """, quote: '$$', (err, records) -> - records.should.eql [['a','b','c'],['1','2','3']] unless err - next err - - it 'with columns', (next) -> - parse """ - a,"b",c - 1,"2",3 - """, quote: true, columns: true, (err, records) -> - records.should.eql [ { a: '1', b: '2', c: '3' } ] unless err - next err - - describe 'error "Quoted field not terminated"', -> - - it 'when unclosed', (next) -> - parse """ - "",1974,8.8392926E7,""," - """, (err) -> - assert_error err, - message: 'Quote Not Closed: the parsing is finished with an opening quote at line 1' - code: 'CSV_QUOTE_NOT_CLOSED' - next() - - describe 'error "Invalid Closing Quote"', -> - - it 'when followed by a character', (next) -> - parse '""!', quote: '"', escape: '"', (err) -> - assert_error err, - message: 'Invalid Closing Quote: got "!" at line 1 instead of delimiter, record delimiter, trimable character (if activated) or comment' - code: 'CSV_INVALID_CLOSING_QUOTE' - next() - - it 'no throw followed by a comment', (next) -> - parse '""# A comment', quote: '"', escape: '"', comment: '#', (err) -> - next err - - it 'no throw followed by a delimiter', (next) -> - parse '""|BB', quote: '"', escape: '"', delimiter: '|', (err) -> - next err - - it 'no throw followed by a record delimiter', (next) -> - parse '""|BB', quote: '"', escape: '"', record_delimiter: '|', (err) -> - next err - - it 'no throw followed by a trimable character', (next) -> - parse '"" ', quote: '"', escape: '"', rtrim: true, (err) -> - next err - - describe 'error "Invalid opening quotes"', -> - - it 'on indexed columns', (next) -> - parse """ - "this","line","is",valid - "this","line",is,"also,valid" - this,"line",is,invalid h"ere" - "and",valid,line,follows... - """, (err, records) -> - assert_error err, - message: 'Invalid Opening Quote: a quote is found on field 3 at line 3, value is "invalid h"' - code: 'INVALID_OPENING_QUOTE' - field: 'invalid h' - (records == undefined).should.be.true - next() - - it 'on indexed columns', (next) -> - parse """ - "a","b","c","d" - "11","12",13,"14" - 21,"22",23,2"4" - """, columns: true, (err, records) -> - assert_error err, - message: 'Invalid Opening Quote: a quote is found on field "d" at line 3, value is "2"' - code: 'INVALID_OPENING_QUOTE' - field: '2' - (records == undefined).should.be.true - next() - diff --git a/packages/csv-parse/test/option.quote.ts b/packages/csv-parse/test/option.quote.ts new file mode 100644 index 000000000..0db458e25 --- /dev/null +++ b/packages/csv-parse/test/option.quote.ts @@ -0,0 +1,349 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; + +describe("Option `quote`", function () { + it("is compatible with buffer size", function (next) { + const parser = parse({ escape: "$", quote: "::::::" }, (err, data) => { + data.should.eql([ + ["1", "2::::::2", "3"], + ["b", "c", "d"], + ]); + next(err); + }); + for (const c of "1,::::::2$::::::2::::::,3\nb,c,d") { + parser.write(c); + } + parser.end(); + }); + + it("default", function () { + const parser = parse(); + parser.options.quote?.should.eql(Buffer.from('"')); + }); + + it("normalize", function () { + let parser = parse({ quote: true }); + parser.options.quote?.should.eql(Buffer.from('"')); + parser = parse({ quote: false }); + (parser.options.quote === null).should.be.true(); + parser = parse({ quote: null }); + (parser.options.quote === null).should.be.true(); + }); + + it("with default", function (next) { + const data = 'abc,"123",def,"456"\nhij,klm,"789",nop'; + const parser = parse((err, records) => { + if (err) return next(err); + records.should.eql([ + ["abc", "123", "def", "456"], + ["hij", "klm", "789", "nop"], + ]); + next(); + }); + for (const chr of data) { + parser.write(chr); + } + parser.end(); + }); + + it("with fields containing delimiters", function (next) { + parse( + dedent` + 20322051544,",1979.0,8.8017226E7,ABC,45,2000-01-01",1,2,3,4 + 28392898392,1974.0,8.8392926E7,DEF,23,2050-11-27 + "28392898392,1974.0","8.8392926E7","DEF,23,2050-11-27,",4,5,6 + `, + (err, records) => { + if (err) return next(err); + records.should.eql([ + [ + "20322051544", + ",1979.0,8.8017226E7,ABC,45,2000-01-01", + "1", + "2", + "3", + "4", + ], + ["28392898392", "1974.0", "8.8392926E7", "DEF", "23", "2050-11-27"], + [ + "28392898392,1974.0", + "8.8392926E7", + "DEF,23,2050-11-27,", + "4", + "5", + "6", + ], + ]); + next(); + }, + ); + }); + + it("empty value", function (next) { + parse( + dedent` + 20322051544,"",8.8017226E7,45,"" + "",1974,8.8392926E7,"","" + `, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["20322051544", "", "8.8017226E7", "45", ""], + ["", "1974", "8.8392926E7", "", ""], + ]); + next(); + }, + ); + }); + + it("values containing quotes and double quotes escape", function (next) { + parse('AB,"""",CD,"""hi"""\n"",JK,"",""\n', (err, records) => { + if (err) return next(err); + records.should.eql([ + ["AB", '"', "CD", '"hi"'], + ["", "JK", "", ""], + ]); + next(); + }); + }); + + it("only containing quotes and double quotes escape", function (next) { + const data = '""""\n""""\n'; + const parser = parse((err, records) => { + if (err) return next(err); + records.should.eql([['"'], ['"']]); + next(); + }); + for (const chr of data) { + parser.write(chr); + } + parser.end(); + }); + + it("line breaks inside quotes", function (next) { + parse( + dedent` + 20322051544," + ",8.8017226E7,45," + ok + " + " + ",1974,8.8392926E7,""," + " + `, + (err, records) => { + if (!err) { + records.should.eql([ + ["20322051544", "\n", "8.8017226E7", "45", "\nok\n"], + ["\n", "1974", "8.8392926E7", "", "\n"], + ]); + } + next(err); + }, + ); + }); + + describe("disabled", function () { + it("if empty", function (next) { + parse( + dedent` + a,b,c + 1,r"2"d"2",3 + `, + { quote: "" }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c"], + ["1", 'r"2"d"2"', "3"], + ]); + } + next(err); + }, + ); + }); + + it("if null", function (next) { + parse( + dedent` + a,b,c + 1,r"2"d"2",3 + `, + { quote: null }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c"], + ["1", 'r"2"d"2"', "3"], + ]); + } + next(err); + }, + ); + }); + + it("if false", function (next) { + parse( + dedent` + a,b,c + 1,r"2"d"2",3 + `, + { quote: null }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c"], + ["1", 'r"2"d"2"', "3"], + ]); + } + next(err); + }, + ); + }); + }); + + describe("options", function () { + it("with multiple chars", function (next) { + parse( + dedent` + $$a$$,b,$$c$$ + 1,$$2$$,3 + `, + { quote: "$$" }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c"], + ["1", "2", "3"], + ]); + } + next(err); + }, + ); + }); + + it("with columns", function (next) { + parse( + dedent` + a,"b",c + 1,"2",3 + `, + { quote: true, columns: true }, + (err, records) => { + if (!err) { + records.should.eql([{ a: "1", b: "2", c: "3" }]); + } + next(err); + }, + ); + }); + }); + + describe('error "Quoted field not terminated"', function () { + it("when unclosed", function (next) { + parse(`"",1974,8.8392926E7,"","`, (err) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + "Quote Not Closed: the parsing is finished with an opening quote at line 1", + code: "CSV_QUOTE_NOT_CLOSED", + }); + next(); + }); + }); + }); + + describe('error "Invalid Closing Quote"', function () { + it("when followed by a character", function (next) { + parse('""!', { quote: '"', escape: '"' }, (err) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + 'Invalid Closing Quote: got "!" at line 1 instead of delimiter, record delimiter, trimable character (if activated) or comment', + code: "CSV_INVALID_CLOSING_QUOTE", + }); + next(); + }); + }); + + it("no throw followed by a comment", function (next) { + parse( + '""# A comment', + { quote: '"', escape: '"', comment: "#" }, + (err) => { + next(err); + }, + ); + }); + + it("no throw followed by a delimiter", function (next) { + parse('""|BB', { quote: '"', escape: '"', delimiter: "|" }, (err) => { + next(err); + }); + }); + + it("no throw followed by a record delimiter", function (next) { + parse( + '""|BB', + { quote: '"', escape: '"', record_delimiter: "|" }, + (err) => { + next(err); + }, + ); + }); + + it("no throw followed by a trimable character", function (next) { + parse('"" ', { quote: '"', escape: '"', rtrim: true }, (err) => { + next(err); + }); + }); + }); + + describe('error "Invalid opening quotes"', function () { + it("with indexed columns", function (next) { + parse( + dedent` + "this","line","is",valid + "this","line",is,"also,valid" + this,"line",is,invalid h"ere" + "and",valid,line,follows... + `, + (err, records) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + 'Invalid Opening Quote: a quote is found on field 3 at line 3, value is "invalid h"', + code: "INVALID_OPENING_QUOTE", + field: "invalid h", + }); + (records === undefined).should.be.true; + next(); + }, + ); + }); + + it("with named columns", function (next) { + parse( + dedent` + "a","b","c","d" + "11","12",13,"14" + 21,"22",23,2"4" + `, + { columns: true }, + (err, records) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + 'Invalid Opening Quote: a quote is found on field "d" at line 3, value is "2"', + code: "INVALID_OPENING_QUOTE", + field: "2", + }); + (records === undefined).should.be.true; + next(); + }, + ); + }); + }); +}); diff --git a/packages/csv-parse/test/option.raw.coffee b/packages/csv-parse/test/option.raw.coffee deleted file mode 100644 index 072777c73..000000000 --- a/packages/csv-parse/test/option.raw.coffee +++ /dev/null @@ -1,55 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `raw`', -> - - it 'validation', -> - parse '', raw: undefined, (->) - parse '', raw: null, (->) - parse '', raw: false, (->) - (-> - parse '', raw: '', (->) - ).should.throw 'Invalid Option: raw must be true, got ""' - (-> - parse '', raw: 2, (->) - ).should.throw 'Invalid Option: raw must be true, got 2' - - it 'includes escape chars', (next) -> - str = """ - "hello""world",LOL - """ - parse str, raw: true, escape: '"', (err, records) -> - records[0].raw.should.eql str unless err - records[0].record.should.eql [ 'hello"world', 'LOL' ] unless err - next err - - it 'includes line breaks', (next) -> - parse """ - hello - my - friend - """, raw: true, escape: '"', (err, records) -> - records[1].raw.should.match /\n$/ unless err - next err - - it 'has the inner line breaks', (next) -> - str = """ - foo,"b - a - r" - """ - parse str, raw: true, escape: '"', (err, records) -> - records[0].raw.should.eql str unless err - next err - - it 'preserve columns', (next) -> - parse """ - name,last name - Boudreau,Jonathan - """, raw: true, columns: ['FIELD_1', false], (err, records) -> - records[0].raw.should.eql 'name,last name\n' unless err - records[0].record.should.eql FIELD_1: 'name' unless err - next err - - - diff --git a/packages/csv-parse/test/option.raw.js b/packages/csv-parse/test/option.raw.js new file mode 100644 index 000000000..f64cddc23 --- /dev/null +++ b/packages/csv-parse/test/option.raw.js @@ -0,0 +1,13 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `raw`", function () { + it("validation", function () { + (() => parse("", { raw: "" }, () => {})).should.throw( + 'Invalid Option: raw must be true, got ""', + ); + (() => parse("", { raw: 2 }, () => {})).should.throw( + "Invalid Option: raw must be true, got 2", + ); + }); +}); diff --git a/packages/csv-parse/test/option.raw.ts b/packages/csv-parse/test/option.raw.ts new file mode 100644 index 000000000..a6fdccfc9 --- /dev/null +++ b/packages/csv-parse/test/option.raw.ts @@ -0,0 +1,78 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; + +describe("Option `raw`", function () { + it("validation", function () { + parse("", { raw: undefined }, () => {}); + parse("", { raw: null }, () => {}); + parse("", { raw: false }, () => {}); + }); + + it("includes escape chars", function (next) { + const str = dedent` + "hello""world",LOL + `; + parse(str, { raw: true, escape: '"' }, (err, records) => { + if (err) return next(err); + const record = records[0] as unknown as { record: string[]; raw: string }; + record.raw.should.eql(str); + record.record.should.eql(['hello"world', "LOL"]); + next(); + }); + }); + + it("includes line breaks", function (next) { + parse( + dedent` + hello + my + friend + `, + { raw: true, escape: '"' }, + (err, records) => { + if (err) return next(err); + const record = records[1] as unknown as { + record: string[]; + raw: string; + }; + record.raw.should.match(/\n$/); + next(); + }, + ); + }); + + it("has the inner line breaks", function (next) { + const str = dedent` + foo,"b + a + r" + `; + parse(str, { raw: true, escape: '"' }, (err, records) => { + if (err) return next(err); + const record = records[0] as unknown as { record: string[]; raw: string }; + record.raw.should.eql(str); + next(); + }); + }); + + it("preserve columns", function (next) { + parse( + dedent` + name,last name + Boudreau,Jonathan + `, + { raw: true, columns: ["FIELD_1", false] }, + (err, records) => { + if (err) return next(err); + const record = records[0] as unknown as { + record: string[]; + raw: string; + }; + record.raw.should.eql("name,last name\n"); + record.record.should.eql({ FIELD_1: "name" }); + next(); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/option.record_delimiter.coffee b/packages/csv-parse/test/option.record_delimiter.coffee deleted file mode 100644 index c7609840f..000000000 --- a/packages/csv-parse/test/option.record_delimiter.coffee +++ /dev/null @@ -1,407 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `record_delimiter`', -> - - describe 'validation', -> - - it 'accepted types', -> - parse 'a,b,c', record_delimiter: undefined, (->) - parse 'a,b,c', record_delimiter: 'string', (->) - parse 'a,b,c', record_delimiter: ['string'], (->) - parse 'a,b,c', record_delimiter: Buffer.from('string'), (->) - parse 'a,b,c', record_delimiter: [Buffer.from('string')], (->) - - it 'non accepted types', -> - (-> - parse 'a,b,c', record_delimiter: '', (->) - ).should.throw - message: [ - 'Invalid option `record_delimiter`:' - 'value must be a non empty string or buffer,' - 'got ""' - ].join ' ' - code: 'CSV_INVALID_OPTION_RECORD_DELIMITER' - (-> - parse 'a,b,c', record_delimiter: Buffer.from(''), (->) - ).should.throw - message: [ - 'Invalid option `record_delimiter`:' - 'value must be a non empty string or buffer,' - 'got {"type":"Buffer","data":[]}' - ].join ' ' - code: 'CSV_INVALID_OPTION_RECORD_DELIMITER' - (-> - parse 'a,b,c', record_delimiter: null, (->) - ).should.throw - message: [ - 'Invalid option `record_delimiter`:' - 'value must be a string, a buffer or array of string|buffer,' - 'got null' - ].join ' ' - code: 'CSV_INVALID_OPTION_RECORD_DELIMITER' - (-> - parse 'a,b,c', record_delimiter: ['a', '', 'b'], (->) - ).should.throw - message: [ - 'Invalid option `record_delimiter`:' - 'value must be a non empty string or buffer' - 'at index 1,' - 'got ""' - ].join ' ' - code: 'CSV_INVALID_OPTION_RECORD_DELIMITER' - (-> - parse 'a,b,c', record_delimiter: ['a', null, 'b'], (->) - ).should.throw - message: [ - 'Invalid option `record_delimiter`:' - 'value must be a string, a buffer or array of string|buffer' - 'at index 1,' - 'got null' - ].join ' ' - code: 'CSV_INVALID_OPTION_RECORD_DELIMITER' - - describe 'usage', -> - - it 'as a string', (next) -> - parse """ - ABC,45::DEF,23 - """, record_delimiter: '::', (err, records) -> - return next err if err - records.should.eql [ - [ 'ABC','45' ] - [ 'DEF','23' ] - ] - next() - - it 'as an array', (next) -> - parse """ - ABC,45::DEF,23\n50,60 - """, record_delimiter: ['::','\n'], (err, records) -> - return next err if err - records.should.eql [ - [ 'ABC','45' ] - [ 'DEF','23' ] - [ '50', '60'] - ] - next() - - describe 'details', -> - - it 'is compatible with buffer size', (next) -> - parser = parse record_delimiter: ['::::::'], (err, records) -> - records.should.eql [ - [ '1', '2', '3' ] - [ 'b', 'c', 'd' ] - ] - next err - parser.write c for c in """ - 1,2,3::::::b,c,d - """ - parser.end() - - it 'ensure that delimiter and record_delimiter doesnt match', (next) -> - parse """ - a;b - 11;22; - 33;33; - - """, - delimiter: ';' - record_delimiter: [';\n', '\n'] - , (err, records) -> - records.should.eql [ - [ 'a', 'b' ] - [ '11', '22' ] - [ '33', '33' ] - ] unless err - next err - - it 'handle new line preceded by a quote when record_delimiter is a string', (next) -> - parse """ - "ABC","45"::"DEF","23"::"GHI","94" - """, record_delimiter: '::', (err, records) -> - return next err if err - records.should.eql [ - [ 'ABC','45' ] - [ 'DEF','23' ] - [ 'GHI','94' ] - ] - next() - - it 'handle new line preceded by a quote when record_delimiter is an array', (next) -> - parse """ - "ABC","45"::"DEF","23"::"GHI","94"\r\n"JKL","13" - """, record_delimiter: ['::', '\r\n'], (err, records) -> - return next err if err - records.should.eql [ - [ 'ABC','45' ] - [ 'DEF','23' ] - [ 'GHI','94' ] - [ 'JKL','13' ] - ] - next() - - it 'handle chunks of multiple chars when record_delimiter is a string', (next) -> - records = [] - parser = parse record_delimiter: '::' - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'end', -> - records.should.eql [ - [ 'ABC','45' ] - [ 'DEF','23' ] - [ 'GHI','94' ] - [ 'JKL','02' ] - ] - next() - parser.write '"ABC","45"' - parser.write '::"DEF","23":' - parser.write ':"GHI","94"::' - parser.write '"JKL","02"' - parser.end() - - it 'handle chunks of multiple chars when record_delimiter is an array', (next) -> - records = [] - parser = parse record_delimiter: ['::', '\r'] - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'end', -> - records.should.eql [ - [ 'ABC','45' ] - [ 'DEF','23' ] - [ 'GHI','94' ] - [ 'JKL','02' ] - [ 'MNO','13' ] - ] - next() - parser.write '"ABC","45"' - parser.write '::"DEF","23":' - parser.write ':"GHI","94"::' - parser.write '"JKL","02"\r' - parser.write '"MNO","13"' - parser.end() - - it 'handle chunks of multiple chars without quotes when record_delimiter is a string', (next) -> - records = [] - parser = parse record_delimiter: '::' - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'end', -> - records.should.eql [ - [ 'ABC','45' ] - [ 'DEF','23' ] - [ 'GHI','94' ] - [ 'JKL','02' ] - ] - next() - parser.write 'ABC,45' - parser.write '::DEF,23:' - parser.write ':GHI,94::' - parser.write 'JKL,02' - parser.end() - - it 'handle chunks of multiple chars without quotes when record_delimiter is an array', (next) -> - records = [] - parser = parse record_delimiter: ['::','\n','\r\n'] - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'end', -> - records.should.eql [ - [ 'ABC','45' ] - [ 'DEF','23' ] - [ 'GHI','94' ] - [ 'JKL','02' ] - ] - next() - parser.write 'ABC,45\n' - parser.write 'DEF,23:' - parser.write ':GHI,94\r' - parser.write '\nJKL,02' - parser.end() - - describe 'auto', -> - - it 'No record', (next) -> - # not sure if the current behavior is right, - # the new behavior is proposing [['']] - # which kind of look more appropriate - parse "", (err, records) -> - records.should.eql [] unless err - next err - - it 'handle chunks in autodiscovery', (next) -> - records = [] - parser = parse() - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'end', -> - records.should.eql [ - [ 'ABC','45' ] - [ 'DEF','23' ] - [ 'GHI','94' ] - [ 'JKL','02' ] - ] - next() - parser.write '"ABC","45"' - parser.write '\n"DEF","23"\n' - parser.write '"GHI","94"\n' - parser.write '"JKL","02"' - parser.end() - - it 'write aggressively', (next) -> - records = [] - parser = parse() - parser.on 'readable', -> - while(d = parser.read()) - records.push d - parser.on 'end', -> - records.should.eql [ - [ 'abc', '123' ] - [ 'def', '456' ] - ] - next() - parser.write 'abc,123' - parser.write '\n' - parser.write 'def,456' - parser.end() - - it 'Test line ends with field delimiter and without record delimiter', (next) -> - parse '"a","b","c",', delimiter: ',', (err, records) -> - return next err if err - records.should.eql [ - [ 'a','b','c','' ] - ] - next() - - it 'ensure autodiscovery support chunck between lines', (next) -> - records = [] - parser = parse() - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'end', -> - records.should.eql [ - [ 'ABC','45' ] - [ 'DEF','23' ] - [ 'GHI','94' ] - [ 'JKL','02' ] - ] - next() - parser.write 'ABC,45' - parser.write '\r\nDEF,23\r' - parser.write '\nGHI,94\r\n' - parser.write 'JKL,02\r\n' - parser.end() - - it 'skip default record delimiters when quoted', (next) -> - parser = parse (err, records) -> - records.should.eql [ - ['1', '2', '\n'] - ['3', '4', ''] - ] unless err - next err - parser.write c for c in '1,2,"\n"\r\n3,4,' - parser.end() - - it 'with skip empty lines', (next) -> - parse """ - ABC\r\n\r\nDEF\r\n\r\n - """, skip_empty_lines: true, (err, records) -> - records.should.eql [ - [ 'ABC' ] - [ 'DEF' ] - ] unless err - next err - - it 'support utf8 no bom with windows line ending', (next) -> - parser = parse encoding: 'utf8', (err, records) -> - records.should.eql [ - ['a', 'b'] - ['1', '2'] - ] unless err - next err - parser.write Buffer.from([c]) for c in Buffer.from('a,b\r\n1,2', 'utf8') - parser.end() - - it 'support utf8 no bom with mac os 9 line ending', (next) -> - parser = parse encoding: 'utf8', (err, records) -> - records.should.eql [ - ['a', 'b'] - ['1', '2'] - ] unless err - next err - parser.write Buffer.from([c]) for c in Buffer.from('a,b\r1,2', 'utf8') - parser.end() - - it 'support utf8 no bom with unix line ending', (next) -> - parser = parse encoding: 'utf8', (err, records) -> - records.should.eql [ - ['a', 'b'] - ['1', '2'] - ] unless err - next err - parser.write Buffer.from([c]) for c in Buffer.from('a,b\n1,2', 'utf8') - parser.end() - - it 'support utf8 with bom with windows line ending', (next) -> - parser = parse bom: true, (err, records) -> - records.should.eql [ - ['a', 'b'] - ['1', '2'] - ] unless err - next err - parser.write Buffer.from([c]) for c in Buffer.concat([ - Buffer.from([239, 187, 191]), - Buffer.from('a,b\r\n1,2', 'utf8') - ]) - parser.end() - - it 'support utf16le no bom with windows line ending', (next) -> - parser = parse encoding: 'utf16le', (err, records) -> - records.should.eql [ - ['a', 'b'] - ['1', '2'] - ] unless err - next err - parser.write Buffer.from([c]) for c in Buffer.from('a,b\r\n1,2', 'utf16le') - parser.end() - - it 'support utf16le no bom with mac os 9 line ending', (next) -> - parser = parse encoding: 'utf16le', (err, records) -> - records.should.eql [ - ['a', 'b'] - ['1', '2'] - ] unless err - next err - parser.write Buffer.from([c]) for c in Buffer.from('a,b\r1,2', 'utf16le') - parser.end() - - it 'support utf16le no bom with unix line ending', (next) -> - parser = parse encoding: 'utf16le', (err, records) -> - records.should.eql [ - ['a', 'b'] - ['1', '2'] - ] unless err - next err - parser.write Buffer.from([c]) for c in Buffer.from('a,b\n1,2', 'utf16le') - parser.end() - - it 'support utf16le with bom with windows line ending', (next) -> - parser = parse bom: true, (err, records) -> - records.should.eql [ - ['a', 'b'] - ['1', '2'] - ] unless err - next err - parser.write Buffer.from([c]) for c in Buffer.concat([ - Buffer.from([255, 254]), - Buffer.from('a,b\r\n1,2', 'utf16le') - ]) - parser.end() - diff --git a/packages/csv-parse/test/option.record_delimiter.ts b/packages/csv-parse/test/option.record_delimiter.ts new file mode 100644 index 000000000..0910faad5 --- /dev/null +++ b/packages/csv-parse/test/option.record_delimiter.ts @@ -0,0 +1,531 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `record_delimiter`", function () { + describe("validation", function () { + it("accepted types", function () { + parse("a,b,c", { record_delimiter: undefined }, () => {}); + parse("a,b,c", { record_delimiter: "string" }, () => {}); + parse("a,b,c", { record_delimiter: ["string"] }, () => {}); + parse("a,b,c", { record_delimiter: Buffer.from("string") }, () => {}); + parse("a,b,c", { record_delimiter: [Buffer.from("string")] }, () => {}); + }); + + it("non accepted types", function () { + (() => { + parse("a,b,c", { record_delimiter: "" }, () => {}); + }).should.throw({ + message: [ + "Invalid option `record_delimiter`:", + "value must be a non empty string or buffer,", + 'got ""', + ].join(" "), + code: "CSV_INVALID_OPTION_RECORD_DELIMITER", + }); + (() => { + parse("a,b,c", { record_delimiter: Buffer.from("") }, () => {}); + }).should.throw({ + message: [ + "Invalid option `record_delimiter`:", + "value must be a non empty string or buffer,", + 'got {"type":"Buffer","data":[]}', + ].join(" "), + code: "CSV_INVALID_OPTION_RECORD_DELIMITER", + }); + (() => { + parse("a,b,c", { record_delimiter: null }, () => {}); + }).should.throw({ + message: [ + "Invalid option `record_delimiter`:", + "value must be a string, a buffer or array of string|buffer,", + "got null", + ].join(" "), + code: "CSV_INVALID_OPTION_RECORD_DELIMITER", + }); + (() => { + parse("a,b,c", { record_delimiter: ["a", "", "b"] }, () => {}); + }).should.throw({ + message: [ + "Invalid option `record_delimiter`:", + "value must be a non empty string or buffer", + "at index 1,", + 'got ""', + ].join(" "), + code: "CSV_INVALID_OPTION_RECORD_DELIMITER", + }); + (() => { + parse("a,b,c", { record_delimiter: ["a", null, "b"] }, () => {}); + }).should.throw({ + message: [ + "Invalid option `record_delimiter`:", + "value must be a string, a buffer or array of string|buffer", + "at index 1,", + "got null", + ].join(" "), + code: "CSV_INVALID_OPTION_RECORD_DELIMITER", + }); + }); + }); + + describe("usage", function () { + it("as a string", function (next) { + parse("ABC,45::DEF,23", { record_delimiter: "::" }, (err, records) => { + if (err) return next(err); + records.should.eql([ + ["ABC", "45"], + ["DEF", "23"], + ]); + next(); + }); + }); + + it("as an array", function (next) { + parse( + "ABC,45::DEF,23\n50,60", + { record_delimiter: ["::", "\n"] }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["ABC", "45"], + ["DEF", "23"], + ["50", "60"], + ]); + next(); + }, + ); + }); + }); + + describe("details", function () { + it("is compatible with buffer size", function (next) { + const parser = parse({ record_delimiter: ["::::::"] }, (err, records) => { + records.should.eql([ + ["1", "2", "3"], + ["b", "c", "d"], + ]); + next(err); + }); + for (const c of "1,2,3::::::b,c,d") { + parser.write(c); + } + parser.end(); + }); + + it("ensure that delimiter and record_delimiter doesnt match", function (next) { + parse( + "a;b\n11;22;\n33;33;\n", + { + delimiter: ";", + record_delimiter: [";\n", "\n"], + }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b"], + ["11", "22"], + ["33", "33"], + ]); + } + next(err); + }, + ); + }); + + it("handle new line preceded by a quote when record_delimiter is a string", function (next) { + parse( + '"ABC","45"::"DEF","23"::"GHI","94"', + { record_delimiter: "::" }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["ABC", "45"], + ["DEF", "23"], + ["GHI", "94"], + ]); + next(); + }, + ); + }); + + it("handle new line preceded by a quote when record_delimiter is an array", function (next) { + parse( + '"ABC","45"::"DEF","23"::"GHI","94"\r\n"JKL","13"', + { record_delimiter: ["::", "\r\n"] }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["ABC", "45"], + ["DEF", "23"], + ["GHI", "94"], + ["JKL", "13"], + ]); + next(); + }, + ); + }); + + it("handle chunks of multiple chars when record_delimiter is a string", function (next) { + const records: string[] = []; + const parser = parse({ record_delimiter: "::" }); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + records.should.eql([ + ["ABC", "45"], + ["DEF", "23"], + ["GHI", "94"], + ["JKL", "02"], + ]); + next(); + }); + parser.write('"ABC","45"'); + parser.write('::"DEF","23":'); + parser.write(':"GHI","94"::'); + parser.write('"JKL","02"'); + parser.end(); + }); + + it("handle chunks of multiple chars when record_delimiter is an array", function (next) { + const records: string[] = []; + const parser = parse({ record_delimiter: ["::", "\r"] }); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + records.should.eql([ + ["ABC", "45"], + ["DEF", "23"], + ["GHI", "94"], + ["JKL", "02"], + ["MNO", "13"], + ]); + next(); + }); + parser.write('"ABC","45"'); + parser.write('::"DEF","23":'); + parser.write(':"GHI","94"::'); + parser.write('"JKL","02"\r'); + parser.write('"MNO","13"'); + parser.end(); + }); + + it("handle chunks of multiple chars without quotes when record_delimiter is a string", function (next) { + const records: string[] = []; + const parser = parse({ record_delimiter: "::" }); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + records.should.eql([ + ["ABC", "45"], + ["DEF", "23"], + ["GHI", "94"], + ["JKL", "02"], + ]); + next(); + }); + parser.write("ABC,45"); + parser.write("::DEF,23:"); + parser.write(":GHI,94::"); + parser.write("JKL,02"); + parser.end(); + }); + + it("handle chunks of multiple chars without quotes when record_delimiter is an array", function (next) { + const records: string[] = []; + const parser = parse({ record_delimiter: ["::", "\n", "\r\n"] }); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + records.should.eql([ + ["ABC", "45"], + ["DEF", "23"], + ["GHI", "94"], + ["JKL", "02"], + ]); + next(); + }); + parser.write("ABC,45\n"); + parser.write("DEF,23:"); + parser.write(":GHI,94\r"); + parser.write("\nJKL,02"); + parser.end(); + }); + }); + + describe("auto", function () { + it("No record", function (next) { + parse("", (err, records) => { + if (!err) { + records.should.eql([]); + } + next(err); + }); + }); + + it("handle chunks in autodiscovery", function (next) { + const records: string[] = []; + const parser = parse(); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + records.should.eql([ + ["ABC", "45"], + ["DEF", "23"], + ["GHI", "94"], + ["JKL", "02"], + ]); + next(); + }); + parser.write('"ABC","45"'); + parser.write('\n"DEF","23"\n'); + parser.write('"GHI","94"\n'); + parser.write('"JKL","02"'); + parser.end(); + }); + + it("write aggressively", function (next) { + const records: string[] = []; + const parser = parse(); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + records.should.eql([ + ["abc", "123"], + ["def", "456"], + ]); + next(); + }); + parser.write("abc,123"); + parser.write("\n"); + parser.write("def,456"); + parser.end(); + }); + + it("Test line ends with field delimiter and without record delimiter", function (next) { + parse('"a","b","c",', { delimiter: "," }, (err, records) => { + if (err) return next(err); + records.should.eql([["a", "b", "c", ""]]); + next(); + }); + }); + + it("ensure autodiscovery support chunck between lines", function (next) { + const records: string[] = []; + const parser = parse(); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + records.should.eql([ + ["ABC", "45"], + ["DEF", "23"], + ["GHI", "94"], + ["JKL", "02"], + ]); + next(); + }); + parser.write("ABC,45"); + parser.write("\r\nDEF,23\r"); + parser.write("\nGHI,94\r\n"); + parser.write("JKL,02\r\n"); + parser.end(); + }); + + it("skip default record delimiters when quoted", function (next) { + const parser = parse((err, records) => { + if (!err) { + records.should.eql([ + ["1", "2", "\n"], + ["3", "4", ""], + ]); + } + next(err); + }); + for (const c of '1,2,"\n"\r\n3,4,') { + parser.write(c); + } + parser.end(); + }); + + it("with skip empty lines", function (next) { + parse( + "ABC\r\n\r\nDEF\r\n\r\n", + { skip_empty_lines: true }, + (err, records) => { + if (!err) { + records.should.eql([["ABC"], ["DEF"]]); + } + next(err); + }, + ); + }); + + it("support utf8 no bom with windows line ending", function (next) { + const parser = parse({ encoding: "utf8" }, (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b"], + ["1", "2"], + ]); + } + next(err); + }); + const buf = Buffer.from("a,b\r\n1,2", "utf8"); + for (let i = 0; i < buf.length; i++) { + parser.write(Buffer.from([buf[i]])); + } + parser.end(); + }); + + it("support utf8 no bom with mac os 9 line ending", function (next) { + const parser = parse({ encoding: "utf8" }, (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b"], + ["1", "2"], + ]); + } + next(err); + }); + const buf = Buffer.from("a,b\r1,2", "utf8"); + for (let i = 0; i < buf.length; i++) { + parser.write(Buffer.from([buf[i]])); + } + parser.end(); + }); + + it("support utf8 no bom with unix line ending", function (next) { + const parser = parse({ encoding: "utf8" }, (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b"], + ["1", "2"], + ]); + } + next(err); + }); + const buf = Buffer.from("a,b\n1,2", "utf8"); + for (let i = 0; i < buf.length; i++) { + parser.write(Buffer.from([buf[i]])); + } + parser.end(); + }); + + it("support utf8 with bom with windows line ending", function (next) { + const parser = parse({ bom: true }, (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b"], + ["1", "2"], + ]); + } + next(err); + }); + const buf = Buffer.concat([ + Buffer.from([239, 187, 191]), + Buffer.from("a,b\r\n1,2", "utf8"), + ]); + for (let i = 0; i < buf.length; i++) { + parser.write(Buffer.from([buf[i]])); + } + parser.end(); + }); + + it("support utf16le no bom with windows line ending", function (next) { + const parser = parse({ encoding: "utf16le" }, (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b"], + ["1", "2"], + ]); + } + next(err); + }); + const buf = Buffer.from("a,b\r\n1,2", "utf16le"); + for (let i = 0; i < buf.length; i++) { + parser.write(Buffer.from([buf[i]])); + } + parser.end(); + }); + + it("support utf16le no bom with mac os 9 line ending", function (next) { + const parser = parse({ encoding: "utf16le" }, (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b"], + ["1", "2"], + ]); + } + next(err); + }); + const buf = Buffer.from("a,b\r1,2", "utf16le"); + for (let i = 0; i < buf.length; i++) { + parser.write(Buffer.from([buf[i]])); + } + parser.end(); + }); + + it("support utf16le no bom with unix line ending", function (next) { + const parser = parse({ encoding: "utf16le" }, (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b"], + ["1", "2"], + ]); + } + next(err); + }); + const buf = Buffer.from("a,b\n1,2", "utf16le"); + for (let i = 0; i < buf.length; i++) { + parser.write(Buffer.from([buf[i]])); + } + parser.end(); + }); + + it("support utf16le with bom with windows line ending", function (next) { + const parser = parse({ bom: true }, (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b"], + ["1", "2"], + ]); + } + next(err); + }); + const buf = Buffer.concat([ + Buffer.from([255, 254]), + Buffer.from("a,b\r\n1,2", "utf16le"), + ]); + for (let i = 0; i < buf.length; i++) { + parser.write(Buffer.from([buf[i]])); + } + parser.end(); + }); + }); +}); diff --git a/packages/csv-parse/test/option.relax_column_count.coffee b/packages/csv-parse/test/option.relax_column_count.coffee deleted file mode 100644 index 7b2fbfc16..000000000 --- a/packages/csv-parse/test/option.relax_column_count.coffee +++ /dev/null @@ -1,198 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'Option `relax_column_count`', -> - - it 'validation', -> - parse '', relax_column_count: true, (->) - parse '', relax_column_count: false, (->) - parse '', relax_column_count: null, (->) - parse '', relax_column_count: undefined, (->) - (-> - parse '', relax_column_count: 1, (->) - ).should.throw 'Invalid Option: relax_column_count must be a boolean, got 1' - (-> - parse '', relax_column_count: 'oh no', (->) - ).should.throw 'Invalid Option: relax_column_count must be a boolean, got "oh no"' - - it 'throw error by default', (next) -> - parse """ - 1,2,3 - 4,5 - """, (err) -> - assert_error err, - code: 'CSV_RECORD_INCONSISTENT_FIELDS_LENGTH' - message: 'Invalid Record Length: expect 3, got 2 on line 2' - record: ['4', '5'] - next() - - it 'emit single error when column count is invalid on multiple lines', (next) -> - parse """ - 1,2 - 1 - 3,4 - 5,6,7 - """ - , (err) -> - assert_error err, - code: 'CSV_RECORD_INCONSISTENT_FIELDS_LENGTH' - message: 'Invalid Record Length: expect 2, got 1 on line 2' - record: ['1'] - next() - - it 'dont throw error if true', (next) -> - parse """ - 1,2,3 - 4,5 - """, relax_column_count: true, (err, records) -> - records.should.eql [ - [ '1', '2', '3' ] - [ '4', '5' ] - ] unless err - next err - - it 'with columns bigger than records', (next) -> - parse """ - 1,2,3 - 4,5 - """, columns: ['a','b','c','d'], relax_column_count: true, (err, records) -> - records.should.eql [ - { "a":"1", "b":"2", "c":"3" } - { "a":"4", "b":"5" } - ] unless err - next err - - it 'with columns smaller than records', (next) -> - parse """ - 1,2,3,4 - 5,6,7 - """, columns: ['a','b','c'], relax_column_count: true, (err, records) -> - records.should.eql [ - { a: '1', b: '2', c: '3' } - { a: '5', b: '6', c: '7'} - ] unless err - next err - - it 'with columns and from, doesnt break count and relying options like from', (next) -> - parse """ - 1,2,3 - 4,5 - 6,7,8 - 9,10 - """, relax_column_count: true, columns: ['a','b','c','d'], from: 3, (err, records) -> - records.should.eql [ - { "a":"6", "b":"7", "c":"8" } - { "a":"9", "b":"10" } - ] unless err - next err - - describe 'relax_column_count_more', -> - - it 'when more', (next) -> - parse """ - 1,2,3 - a,b,c,d - """, relax_column_count_more: true, (err, records) -> - records.should.eql [ - ['1', '2', '3'] - ['a', 'b', 'c', 'd'] - ] unless err - next err - - it 'when less', (next) -> - parse """ - 1,2,3 - a,b - """, relax_column_count_more: true, (err) -> - assert_error err, - code: 'CSV_RECORD_INCONSISTENT_FIELDS_LENGTH' - message: 'Invalid Record Length: expect 3, got 2 on line 2' - record: ['a', 'b'] - next() - - describe 'relax_column_count_less', -> - - it 'when less', (next) -> - parse """ - 1,2,3 - a,b - """, relax_column_count_less: true, (err, records) -> - records.should.eql [ - ['1', '2', '3'] - ['a', 'b'] - ] unless err - next err - - it 'when more', (next) -> - parse """ - 1,2,3 - a,b,c,d - """, relax_column_count_less: true, (err) -> - assert_error err, - code: 'CSV_RECORD_INCONSISTENT_FIELDS_LENGTH' - message: 'Invalid Record Length: expect 3, got 4 on line 2' - record: ['a', 'b', 'c', 'd'] - next() - - describe 'with on_record', -> - - it 'and without columns', (next) -> - parse """ - 1,2 - in:va:lid - 3,4 - """, - relax_column_count: true, - raw: true, - on_record: ({raw, record}, {error}) -> - if error?.code is 'CSV_RECORD_INCONSISTENT_FIELDS_LENGTH' - raw.trim().split ':' - else - record - , (err, records) -> - records.should.eql [ - [ '1', '2' ] - [ 'in', 'va', 'lid' ] - [ '3', '4' ] - ] - next() - - it 'and with columns', (next) -> - parse """ - 1,2 - in:va:lid - 3,4 - """, - columns: ['a', 'b'], - relax_column_count: true, - raw: true, - on_record: ({raw, record}, {error}) -> - if error?.code is 'CSV_RECORD_INCONSISTENT_COLUMNS' - raw.trim().split ':' - else - record - , (err, records) -> - records.should.eql [ - { a: '1', b: '2' } - [ 'in', 'va', 'lid' ] - { a: '3', b: '4' } - ] - next() - - describe 'with skip_records_with_error', (next) -> - - it 'dont skip records', -> - parse """ - column_a - a,b - """, - skip_records_with_error: true - relax_column_count: true - , (err, records) -> - records.should.eql [ - [ 'column_a' ] - [ 'a', 'b' ] - ] - - diff --git a/packages/csv-parse/test/option.relax_column_count.js b/packages/csv-parse/test/option.relax_column_count.js new file mode 100644 index 000000000..e4f336b0a --- /dev/null +++ b/packages/csv-parse/test/option.relax_column_count.js @@ -0,0 +1,17 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `relax_column_count`", function () { + it("validation", function () { + (() => { + parse("", { relax_column_count: 1 }, () => {}); + }).should.throw( + "Invalid Option: relax_column_count must be a boolean, got 1", + ); + (() => { + parse("", { relax_column_count: "oh no" }, () => {}); + }).should.throw( + 'Invalid Option: relax_column_count must be a boolean, got "oh no"', + ); + }); +}); diff --git a/packages/csv-parse/test/option.relax_column_count.ts b/packages/csv-parse/test/option.relax_column_count.ts new file mode 100644 index 000000000..a615444aa --- /dev/null +++ b/packages/csv-parse/test/option.relax_column_count.ts @@ -0,0 +1,291 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; + +describe("Option `relax_column_count`", function () { + it("validation", function () { + parse("", { relax_column_count: true }, () => {}); + parse("", { relax_column_count: false }, () => {}); + parse("", { relax_column_count: null }, () => {}); + parse("", { relax_column_count: undefined }, () => {}); + }); + + it("throw error by default", function (next) { + parse( + dedent` + 1,2,3 + 4,5 + `, + (err) => { + if (!err) return next("Invalid assessment"); + assert_error(err, { + code: "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", + message: "Invalid Record Length: expect 3, got 2 on line 2", + record: ["4", "5"], + }); + next(); + }, + ); + }); + + it("emit single error when column count is invalid on multiple lines", function (next) { + parse( + dedent` + 1,2 + 1 + 3,4 + 5,6,7 + `, + (err) => { + if (!err) return next("Invalid assessment"); + assert_error(err, { + code: "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", + message: "Invalid Record Length: expect 2, got 1 on line 2", + record: ["1"], + }); + next(); + }, + ); + }); + + it("dont throw error if true", function (next) { + parse( + dedent` + 1,2,3 + 4,5 + `, + { relax_column_count: true }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["1", "2", "3"], + ["4", "5"], + ]); + next(); + }, + ); + }); + + it("with columns bigger than records", function (next) { + parse( + dedent` + 1,2,3 + 4,5 + `, + { columns: ["a", "b", "c", "d"], relax_column_count: true }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: "1", b: "2", c: "3" }, + { a: "4", b: "5" }, + ]); + } + next(err); + }, + ); + }); + + it("with columns smaller than records", function (next) { + parse( + dedent` + 1,2,3,4 + 5,6,7 + `, + { columns: ["a", "b", "c"], relax_column_count: true }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: "1", b: "2", c: "3" }, + { a: "5", b: "6", c: "7" }, + ]); + } + next(err); + }, + ); + }); + + it("with columns and from, doesnt break count and relying options like from", function (next) { + parse( + dedent` + 1,2,3 + 4,5 + 6,7,8 + 9,10 + `, + { relax_column_count: true, columns: ["a", "b", "c", "d"], from: 3 }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: "6", b: "7", c: "8" }, + { a: "9", b: "10" }, + ]); + } + next(err); + }, + ); + }); + + describe("relax_column_count_more", function () { + it("when more", function (next) { + parse( + dedent` + 1,2,3 + a,b,c,d + `, + { relax_column_count_more: true }, + (err, records) => { + if (!err) { + records.should.eql([ + ["1", "2", "3"], + ["a", "b", "c", "d"], + ]); + } + next(err); + }, + ); + }); + + it("when less", function (next) { + parse( + dedent` + 1,2,3 + a,b + `, + { relax_column_count_more: true }, + (err) => { + if (!err) return next("Invalid assessment"); + assert_error(err, { + code: "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", + message: "Invalid Record Length: expect 3, got 2 on line 2", + record: ["a", "b"], + }); + next(); + }, + ); + }); + }); + + describe("relax_column_count_less", function () { + it("when less", function (next) { + parse( + dedent` + 1,2,3 + a,b + `, + { relax_column_count_less: true }, + (err, records) => { + if (!err) { + records.should.eql([ + ["1", "2", "3"], + ["a", "b"], + ]); + } + next(err); + }, + ); + }); + + it("when more", function (next) { + parse( + dedent` + 1,2,3 + a,b,c,d + `, + { relax_column_count_less: true }, + (err) => { + if (!err) return next("Invalid assessment"); + assert_error(err, { + code: "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", + message: "Invalid Record Length: expect 3, got 4 on line 2", + record: ["a", "b", "c", "d"], + }); + next(); + }, + ); + }); + }); + + describe("with on_record", function () { + it("and without columns", function (next) { + parse( + dedent` + 1,2 + in:va:lid + 3,4 + `, + { + relax_column_count: true, + raw: true, + on_record: (data, { error }) => { + const { raw, record } = data as unknown as { + record: string[]; + raw: string; + }; + if (error?.code === "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH") { + return raw.trim().split(":"); + } else { + return record; + } + }, + }, + (err, records) => { + records.should.eql([ + ["1", "2"], + ["in", "va", "lid"], + ["3", "4"], + ]); + next(); + }, + ); + }); + + it("and with columns", function (next) { + parse( + dedent` + 1,2 + in:va:lid + 3,4 + `, + { + columns: ["a", "b"], + relax_column_count: true, + raw: true, + on_record: ({ raw, record }, { error }) => { + if (error?.code === "CSV_RECORD_INCONSISTENT_COLUMNS") { + return raw.trim().split(":"); + } else { + return record; + } + }, + }, + (err, records) => { + records.should.eql([ + { a: "1", b: "2" }, + ["in", "va", "lid"], + { a: "3", b: "4" }, + ]); + next(); + }, + ); + }); + }); + + describe("with skip_records_with_error", function () { + it("dont skip records", function () { + parse( + dedent` + column_a + a,b + `, + { + skip_records_with_error: true, + relax_column_count: true, + }, + (err, records) => { + records.should.eql([["column_a"], ["a", "b"]]); + }, + ); + }); + }); +}); diff --git a/packages/csv-parse/test/option.relax_quotes.coffee b/packages/csv-parse/test/option.relax_quotes.coffee deleted file mode 100644 index 98c2046df..000000000 --- a/packages/csv-parse/test/option.relax_quotes.coffee +++ /dev/null @@ -1,110 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'Option `relax_quotes`', -> - - it 'validation', -> - parse '', relax_quotes: true, (->) - parse '', relax_quotes: false, (->) - parse '', relax_quotes: null, (->) - parse '', relax_quotes: undefined, (->) - (-> - parse '', relax_quotes: 1, (->) - ).should.throw 'Invalid Option: relax_quotes must be a boolean, got 1' - (-> - parse '', relax_quotes: 'oh no', (->) - ).should.throw 'Invalid Option: relax_quotes must be a boolean, got "oh no"' - - it 'true with invalid quotes in the middle', (next) -> - # try with relax_quotes true - parse """ - 384682,the "SAMAY" Hostel,Jiron Florida 285 - """, relax_quotes: true, (err, records) -> - return next err if err - records.should.eql [ - [ '384682', 'the "SAMAY" Hostel', 'Jiron Florida 285' ] - ] - next() - - it 'false with invalid quotes in the middle', (next) -> - # try with relax_quotes false - parse """ - 384682,the "SAMAY" Hostel,Jiron Florida 285 - """, relax_quotes: false, (err) -> - assert_error err, - message: 'Invalid Opening Quote: a quote is found on field 1 at line 1, value is "the "' - code: 'INVALID_OPENING_QUOTE' - field: 'the ' - next() - - it 'true with invalid quotes on the left', (next) -> - parse """ - a,"b" c,d - a,""b" c,d - """, relax_quotes: true, (err, records) -> - return next err if err - records.should.eql [ - [ 'a', '"b" c', 'd' ] - [ 'a', '""b" c', 'd' ] - ] - next() - - it 'false with invalid quotes on the left', (next) -> - # transform is throwing instead of emiting error, skipping for now - i = 0 - parse """ - a,"b" c,d - """, relax_quotes: false, (err) -> - assert_error err, - message: 'Invalid Closing Quote: got " " at line 1 instead of delimiter, record delimiter, trimable character (if activated) or comment' - code: 'CSV_INVALID_CLOSING_QUOTE' - next() - - it 'true with two invalid quotes on the left', (next) -> - # try with relax_quotes true - parse """ - a,""b"" c,d - """, relax_quotes: true, (err, records) -> - return next err if err - records.should.eql [ - [ 'a', '""b"" c', 'd' ] - ] unless err - next err - - it 'false with two invalid quotes on the left', (next) -> - # try with relax_quotes false - parse """ - a,""b"" c,d - """, relax_quotes: false, (err) -> - # Change of implementation in version 4, was - # records.should.eql [ - # [ 'a', '"b" c', 'd' ] - # ] unless err - assert_error err, - message: 'Invalid Closing Quote: got "b" at line 1 instead of delimiter, record delimiter, trimable character (if activated) or comment' - code: 'CSV_INVALID_CLOSING_QUOTE' - next() - - it 'true with invalid quotes on the right', (next) -> - # TODO: we need to decide the strategy we want here - parse """ - a,b "c",d - Bob"","23",e - """, relax_quotes: true, (err, records) -> - return next err if err - records.should.eql [ - [ 'a', 'b "c"', 'd' ] - [ 'Bob""', '23','e' ] - ] - next() - - it 'false with invalid quotes on the right', (next) -> - parse """ - a,b "c" - """, relax_quotes: false, (err) -> - assert_error err, - message: 'Invalid Opening Quote: a quote is found on field 1 at line 1, value is "b "' - code: 'INVALID_OPENING_QUOTE' - field: 'b ' - next() diff --git a/packages/csv-parse/test/option.relax_quotes.js b/packages/csv-parse/test/option.relax_quotes.js new file mode 100644 index 000000000..a20be4052 --- /dev/null +++ b/packages/csv-parse/test/option.relax_quotes.js @@ -0,0 +1,15 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `relax_quotes`", function () { + it("validation", function () { + (() => { + parse("", { relax_quotes: 1 }, () => {}); + }).should.throw("Invalid Option: relax_quotes must be a boolean, got 1"); + (() => { + parse("", { relax_quotes: "oh no" }, () => {}); + }).should.throw( + 'Invalid Option: relax_quotes must be a boolean, got "oh no"', + ); + }); +}); diff --git a/packages/csv-parse/test/option.relax_quotes.ts b/packages/csv-parse/test/option.relax_quotes.ts new file mode 100644 index 000000000..e985408e2 --- /dev/null +++ b/packages/csv-parse/test/option.relax_quotes.ts @@ -0,0 +1,123 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; + +describe("Option `relax_quotes`", function () { + it("validation", function () { + parse("", { relax_quotes: true }, () => {}); + parse("", { relax_quotes: false }, () => {}); + parse("", { relax_quotes: null }, () => {}); + parse("", { relax_quotes: undefined }, () => {}); + }); + + it("true with invalid quotes in the middle", function (next) { + parse( + `384682,the "SAMAY" Hostel,Jiron Florida 285`, + { relax_quotes: true }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["384682", 'the "SAMAY" Hostel', "Jiron Florida 285"], + ]); + next(); + }, + ); + }); + + it("false with invalid quotes in the middle", function (next) { + parse( + `384682,the "SAMAY" Hostel,Jiron Florida 285`, + { relax_quotes: false }, + (err) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + 'Invalid Opening Quote: a quote is found on field 1 at line 1, value is "the "', + code: "INVALID_OPENING_QUOTE", + field: "the ", + }); + next(); + }, + ); + }); + + it("true with invalid quotes on the left", function (next) { + parse( + dedent` + a,"b" c,d + a,""b" c,d + `, + { relax_quotes: true }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["a", '"b" c', "d"], + ["a", '""b" c', "d"], + ]); + next(); + }, + ); + }); + + it("false with invalid quotes on the left", function (next) { + parse(`a,"b" c,d`, { relax_quotes: false }, (err) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + 'Invalid Closing Quote: got " " at line 1 instead of delimiter, record delimiter, trimable character (if activated) or comment', + code: "CSV_INVALID_CLOSING_QUOTE", + }); + next(); + }); + }); + + it("true with two invalid quotes on the left", function (next) { + parse(`a,""b"" c,d`, { relax_quotes: true }, (err, records) => { + if (err) return next(err); + records.should.eql([["a", '""b"" c', "d"]]); + next(err); + }); + }); + + it("false with two invalid quotes on the left", function (next) { + parse(`a,""b"" c,d`, { relax_quotes: false }, (err) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + 'Invalid Closing Quote: got "b" at line 1 instead of delimiter, record delimiter, trimable character (if activated) or comment', + code: "CSV_INVALID_CLOSING_QUOTE", + }); + next(); + }); + }); + + it("true with invalid quotes on the right", function (next) { + parse( + `a,b "c",d +Bob"","23",e`, + { relax_quotes: true }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["a", 'b "c"', "d"], + ['Bob""', "23", "e"], + ]); + next(); + }, + ); + }); + + it("false with invalid quotes on the right", function (next) { + parse(`a,b "c"`, { relax_quotes: false }, (err) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + 'Invalid Opening Quote: a quote is found on field 1 at line 1, value is "b "', + code: "INVALID_OPENING_QUOTE", + field: "b ", + }); + next(); + }); + }); +}); diff --git a/packages/csv-parse/test/option.rtrim.coffee b/packages/csv-parse/test/option.rtrim.coffee deleted file mode 100644 index 3e0d091e8..000000000 --- a/packages/csv-parse/test/option.rtrim.coffee +++ /dev/null @@ -1,73 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'Option `rtrim`', -> - - it 'plain text', (next) -> - parse """ - a b ,c d - e f ,g h - """, quote: "'", escape: "'", trim: true, (err, records) -> - records.should.eql [['a b', 'c d'],['e f', 'g h']] unless err - next err - - it 'after quote', (next) -> - data = ''' - 'a' ,'b' - 'c' ,'d' - ''' - parser = parse quote: "'", escape: "'", trim: true, (err, records) -> - records.should.eql [["a", "b"],["c", "d"]] unless err - next err - parser.write chr for chr in data - parser.end() - - it 'quote followed by escape', (next) -> - # 1st line: with field delimiter - # 2nd line: with record delimiter - # 3rd line: with end of file - parse """ - 'a''' ,'b''' - 'c''','d''' - 'e''','f''' - """, quote: "'", escape: "'", trim: true, (err, records) -> - records.should.eql [["a'", "b'"],["c'", "d'"],["e'", "f'"]] unless err - next err - - it 'with whitespaces around quotes', (next) -> - data = ''' - "a b " ,"c d " - "e f " ,"g h " - ''' - parser = parse rtrim: true, (err, records) -> - records.should.eql [['a b ', 'c d '],['e f ', 'g h ']] unless err - next err - parser.write chr for chr in data - parser.end() - - it 'with tags around quotes', (next) -> - data = ''' - "a\tb\t"\t\t\t,"c\td\t\t\t"\t - "e\tf\t"\t,"g\th\t\t\t"\t\t\t - ''' - parser = parse rtrim: true, (err, records) -> - records.should.eql [['a\tb\t', 'c\td\t\t\t'],['e\tf\t', 'g\th\t\t\t']] unless err - next err - parser.write chr for chr in data - parser.end() - - it 'with char after whitespaces', (next) -> - data = [ - '"a b " x ,"c d " x' - '"e f " x,"g h " x ' - ].join '\n' - parser = parse rtrim: true, (err) -> - assert_error err, - message: 'Invalid Closing Quote: found non trimable byte after quote at line 1' - code: 'CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE' - column: 0, empty_lines: 0, header: false, index: 0, invalid_field_length: 0, - quoting: true, lines: 1, records: 0 - next() - parser.write chr for chr in data - parser.end() diff --git a/packages/csv-parse/test/option.rtrim.js b/packages/csv-parse/test/option.rtrim.js new file mode 100644 index 000000000..2f485576f --- /dev/null +++ b/packages/csv-parse/test/option.rtrim.js @@ -0,0 +1,13 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `rtrim`", function () { + it("validation", function () { + (() => { + parse("", { rtrim: 1 }, () => {}); + }).should.throw("Invalid Option: rtrim must be a boolean, got 1"); + (() => { + parse("", { rtrim: "true" }, () => {}); + }).should.throw('Invalid Option: rtrim must be a boolean, got "true"'); + }); +}); diff --git a/packages/csv-parse/test/option.rtrim.ts b/packages/csv-parse/test/option.rtrim.ts new file mode 100644 index 000000000..920cdad14 --- /dev/null +++ b/packages/csv-parse/test/option.rtrim.ts @@ -0,0 +1,130 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; + +describe("Option `rtrim`", function () { + it("validation", function () { + parse("", { rtrim: true }, () => {}); + parse("", { rtrim: false }, () => {}); + parse("", { rtrim: null }, () => {}); + parse("", { rtrim: undefined }, () => {}); + }); + + it("plain text", function (next) { + parse( + dedent` + a b ,c d + e f ,g h + `, + { quote: "'", escape: "'", trim: true }, + (err, records) => { + if (!err) + records.should.eql([ + ["a b", "c d"], + ["e f", "g h"], + ]); + next(err); + }, + ); + }); + + it("after quote", function (next) { + const data = "'a' ,'b'\n'c' ,'d'"; + const parser = parse( + { quote: "'", escape: "'", trim: true }, + (err, records) => { + if (!err) + records.should.eql([ + ["a", "b"], + ["c", "d"], + ]); + next(err); + }, + ); + for (const chr of data) { + parser.write(chr); + } + parser.end(); + }); + + it("quote followed by escape", function (next) { + parse( + dedent` + 'a''' ,'b''' + 'c''','d''' + 'e''','f''' + `, + { quote: "'", escape: "'", trim: true }, + (err, records) => { + if (!err) + records.should.eql([ + ["a'", "b'"], + ["c'", "d'"], + ["e'", "f'"], + ]); + next(err); + }, + ); + }); + + it("with whitespaces around quotes", function (next) { + const data = '"a b " ,"c d "\n"e f " ,"g h "'; + const parser = parse({ rtrim: true }, (err, records) => { + if (!err) + records.should.eql([ + ["a b ", "c d "], + ["e f ", "g h "], + ]); + next(err); + }); + for (const chr of data) { + parser.write(chr); + } + parser.end(); + }); + + it("with tags around quotes", function (next) { + const data = [ + `"a\tb\t"\t\t\t,"c\td\t\t\t"\t`, + `"e\tf\t"\t,"g\th\t\t\t"\t\t\t`, + ].join("\n"); + const parser = parse({ rtrim: true }, (err, records) => { + if (!err) + records.should.eql([ + ["a\tb\t", "c\td\t\t\t"], + ["e\tf\t", "g\th\t\t\t"], + ]); + next(err); + }); + for (const chr of data) { + parser.write(chr); + } + parser.end(); + }); + + it("with char after whitespaces", function (next) { + const data = ['"a b " x ,"c d " x', '"e f " x,"g h " x '].join("\n"); + const parser = parse({ rtrim: true }, (err) => { + if (!err) return next(Error("Invalid assessment")); + assert_error(err, { + message: + "Invalid Closing Quote: found non trimable byte after quote at line 1", + code: "CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE", + column: 0, + empty_lines: 0, + header: false, + index: 0, + invalid_field_length: 0, + quoting: true, + lines: 1, + records: 0, + }); + next(); + }); + for (const chr of data) { + parser.write(chr); + } + parser.end(); + }); +}); diff --git a/packages/csv-parse/test/option.skip_empty_lines.coffee b/packages/csv-parse/test/option.skip_empty_lines.coffee deleted file mode 100644 index 38185810f..000000000 --- a/packages/csv-parse/test/option.skip_empty_lines.coffee +++ /dev/null @@ -1,92 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `skip_empty_lines`', -> - - it 'validation', -> - parse '', skip_empty_lines: true, (->) - parse '', skip_empty_lines: false, (->) - parse '', skip_empty_lines: null, (->) - parse '', skip_empty_lines: undefined, (->) - (-> - parse '', skip_empty_lines: 1, (->) - ).should.throw 'Invalid Option: skip_empty_lines must be a boolean, got 1' - (-> - parse '', skip_empty_lines: 'oh no', (->) - ).should.throw 'Invalid Option: skip_empty_lines must be a boolean, got "oh no"' - - describe 'false', -> - - it 'dont skip by default', (next) -> - parse ''' - ABC\n\nDEF - ''', (err, records) -> - records.should.eql [ - [ 'ABC' ] - [ '' ] - [ 'DEF' ] - ] unless err - next err - - describe 'usage', -> - - it 'skip', (next) -> - parse ''' - ABC\n\nDEF - ''', skip_empty_lines: true, (err, records) -> - records.should.eql [ - [ 'ABC' ] - [ 'DEF' ] - ] unless err - next err - - it 'quoted fields are not interpreted as empty', (next) -> - parse ''' - ABC\n""\nDEF - ''', skip_empty_lines: true, (err, records) -> - records.should.eql [ - [ 'ABC' ] - [ '' ] - [ 'DEF' ] - ] unless err - next err - - it 'skip respect parser.read', (next) -> - records = [] - parser = parse skip_empty_lines: true - parser.write ''' - - 20322051544,1979,8.8017226E7,ABC,45,2000-01-01 - - 28392898392,1974,8.8392926E7,DEF,23,2050-11-27 - - ''' - parser.on 'readable', -> - while(d = parser.read()) - records.push d - parser.on 'error', (err) -> - next err - parser.on 'end', -> - records.should.eql [ - ['20322051544', '1979', '8.8017226E7', 'ABC', '45', '2000-01-01'] - ['28392898392', '1974', '8.8392926E7', 'DEF', '23', '2050-11-27'] - ] - next() - parser.end() - - describe 'with other options', -> - - it 'used conjointly with trim to ignore whitespaces', (next) -> - parse ''' - a,b,c - \t - d,e,f - ''', - skip_empty_lines: true - trim: true - , (err, records) -> - records.should.eql [ - ['a', 'b', 'c'], - ['d', 'e', 'f'] - ] unless err - next err diff --git a/packages/csv-parse/test/option.skip_empty_lines.js b/packages/csv-parse/test/option.skip_empty_lines.js new file mode 100644 index 000000000..71e8fa40f --- /dev/null +++ b/packages/csv-parse/test/option.skip_empty_lines.js @@ -0,0 +1,17 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `skip_empty_lines`", function () { + it("validation", function () { + (() => { + parse("", { skip_empty_lines: 1 }, () => {}); + }).should.throw( + "Invalid Option: skip_empty_lines must be a boolean, got 1", + ); + (() => { + parse("", { skip_empty_lines: "oh no" }, () => {}); + }).should.throw( + 'Invalid Option: skip_empty_lines must be a boolean, got "oh no"', + ); + }); +}); diff --git a/packages/csv-parse/test/option.skip_empty_lines.ts b/packages/csv-parse/test/option.skip_empty_lines.ts new file mode 100644 index 000000000..79f4f76f6 --- /dev/null +++ b/packages/csv-parse/test/option.skip_empty_lines.ts @@ -0,0 +1,88 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `skip_empty_lines`", function () { + it("validation", function () { + parse("", { skip_empty_lines: true }, () => {}); + parse("", { skip_empty_lines: false }, () => {}); + parse("", { skip_empty_lines: null }, () => {}); + parse("", { skip_empty_lines: undefined }, () => {}); + }); + + describe("false", function () { + it("dont skip by default", function (next) { + parse("ABC\n\nDEF", (err, records) => { + if (!err) { + records.should.eql([["ABC"], [""], ["DEF"]]); + } + next(err); + }); + }); + }); + + describe("usage", function () { + it("skip", function (next) { + parse("ABC\n\nDEF", { skip_empty_lines: true }, (err, records) => { + if (!err) { + records.should.eql([["ABC"], ["DEF"]]); + } + next(err); + }); + }); + + it("quoted fields are not interpreted as empty", function (next) { + parse('ABC\n""\nDEF', { skip_empty_lines: true }, (err, records) => { + if (!err) { + records.should.eql([["ABC"], [""], ["DEF"]]); + } + next(err); + }); + }); + + it("skip respect parser.read", function (next) { + const records: string[] = []; + const parser = parse({ skip_empty_lines: true }); + parser.write( + "\n20322051544,1979,8.8017226E7,ABC,45,2000-01-01\n\n28392898392,1974,8.8392926E7,DEF,23,2050-11-27\n", + ); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("error", (err) => { + next(err); + }); + parser.on("end", () => { + records.should.eql([ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ]); + next(); + }); + parser.end(); + }); + }); + + describe("with other options", function () { + it("used conjointly with trim to ignore whitespaces", function (next) { + parse( + "a,b,c\n\t\nd,e,f", + { + skip_empty_lines: true, + trim: true, + }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c"], + ["d", "e", "f"], + ]); + } + next(err); + }, + ); + }); + }); +}); diff --git a/packages/csv-parse/test/option.skip_records_with_empty_values.coffee b/packages/csv-parse/test/option.skip_records_with_empty_values.coffee deleted file mode 100644 index 763b90b8e..000000000 --- a/packages/csv-parse/test/option.skip_records_with_empty_values.coffee +++ /dev/null @@ -1,83 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `skip_records_with_empty_values`', -> - - it 'validation', -> - parse '', skip_records_with_empty_values: true, (->) - parse '', skip_records_with_empty_values: false, (->) - parse '', skip_records_with_empty_values: null, (->) - parse '', skip_records_with_empty_values: undefined, (->) - (-> - parse '', skip_records_with_empty_values: 1, (->) - ).should.throw 'Invalid Option: skip_records_with_empty_values must be a boolean, got 1' - (-> - parse '', skip_records_with_empty_values: 'oh no', (->) - ).should.throw 'Invalid Option: skip_records_with_empty_values must be a boolean, got "oh no"' - - it 'dont skip by default', (next) -> - parse """ - ABC,DEF - , - IJK,LMN - """, (err, records) -> - return next err if err - records.should.eql [ - [ 'ABC', 'DEF' ] - [ '', '' ] - [ 'IJK', 'LMN' ] - ] - next() - - it 'skip', (next) -> - parse """ - ABC,DEF - , - IJK,LMN - , - """, skip_records_with_empty_values: true, (err, records) -> - return next err if err - records.should.eql [ - [ 'ABC', 'DEF' ] - [ 'IJK', 'LMN' ] - ] - next() - - it 'skip space and tabs', (next) -> - parse """ - ABC,DEF - \t , \t - IJK,LMN - \t , \t - """, skip_records_with_empty_values: true, (err, records) -> - return next err if err - records.should.eql [ - [ 'ABC', 'DEF' ] - [ 'IJK', 'LMN' ] - ] - next() - - it 'handle value which are casted to another type than string', (next) -> - parse """ - empty_buffer - boolean - integer - null - undefined - """, - skip_records_with_empty_values: true - cast: (value) -> - switch value - when 'empty_buffer' then Buffer.from '' - when 'boolean' then true - when 'integer' then 0 - when 'null' then null - when 'undefined' then undefined - else value - , (err, records) -> - return next err if err - records.should.eql [ - [ true ] - [ 0 ] - ] - next() diff --git a/packages/csv-parse/test/option.skip_records_with_empty_values.js b/packages/csv-parse/test/option.skip_records_with_empty_values.js new file mode 100644 index 000000000..f43b7f059 --- /dev/null +++ b/packages/csv-parse/test/option.skip_records_with_empty_values.js @@ -0,0 +1,17 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `skip_records_with_empty_values`", function () { + it("validation", function () { + (() => { + parse("", { skip_records_with_empty_values: 1 }, () => {}); + }).should.throw( + "Invalid Option: skip_records_with_empty_values must be a boolean, got 1", + ); + (() => { + parse("", { skip_records_with_empty_values: "oh no" }, () => {}); + }).should.throw( + 'Invalid Option: skip_records_with_empty_values must be a boolean, got "oh no"', + ); + }); +}); diff --git a/packages/csv-parse/test/option.skip_records_with_empty_values.ts b/packages/csv-parse/test/option.skip_records_with_empty_values.ts new file mode 100644 index 000000000..485471b97 --- /dev/null +++ b/packages/csv-parse/test/option.skip_records_with_empty_values.ts @@ -0,0 +1,95 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; + +describe("Option `skip_records_with_empty_values`", function () { + it("validation", function () { + parse("", { skip_records_with_empty_values: true }, () => {}); + parse("", { skip_records_with_empty_values: false }, () => {}); + parse("", { skip_records_with_empty_values: null }, () => {}); + parse("", { skip_records_with_empty_values: undefined }, () => {}); + }); + + it("dont skip by default", function (next) { + parse("ABC,DEF\n,\nIJK,LMN", (err, records) => { + if (err) return next(err); + records.should.eql([ + ["ABC", "DEF"], + ["", ""], + ["IJK", "LMN"], + ]); + next(); + }); + }); + + it("skip", function (next) { + parse( + dedent` + ABC,DEF + , + IJK,LMN + , + `, + { skip_records_with_empty_values: true }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["ABC", "DEF"], + ["IJK", "LMN"], + ]); + next(); + }, + ); + }); + + it("skip space and tabs", function (next) { + parse( + "ABC,DEF\n\t , \t\nIJK,LMN\n\t , \t\n", + { skip_records_with_empty_values: true }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["ABC", "DEF"], + ["IJK", "LMN"], + ]); + next(); + }, + ); + }); + + it("handle value which are casted to another type than string", function (next) { + parse( + dedent` + empty_buffer + boolean + integer + null + undefined + `, + { + skip_records_with_empty_values: true, + cast: (value) => { + switch (value) { + case "empty_buffer": + return Buffer.from(""); + case "boolean": + return true; + case "integer": + return 0; + case "null": + return null; + case "undefined": + return undefined; + default: + return value; + } + }, + }, + (err, records) => { + if (err) return next(err); + records.should.eql([[true], [0]]); + next(); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/option.skip_records_with_error.coffee b/packages/csv-parse/test/option.skip_records_with_error.coffee deleted file mode 100644 index 0599f79d2..000000000 --- a/packages/csv-parse/test/option.skip_records_with_error.coffee +++ /dev/null @@ -1,175 +0,0 @@ - -import { parse } from '../lib/index.js' -import { assert_error } from './api.assert_error.coffee' - -describe 'Option `skip_records_with_error`', -> - - it 'validation', -> - parse '', skip_records_with_error: true, (->) - parse '', skip_records_with_error: false, (->) - parse '', skip_records_with_error: null, (->) - parse '', skip_records_with_error: undefined, (->) - (-> - parse '', skip_records_with_error: 1, (->) - ).should.throw 'Invalid Option: skip_records_with_error must be a boolean, got 1' - (-> - parse '', skip_records_with_error: 'oh no', (->) - ).should.throw 'Invalid Option: skip_records_with_error must be a boolean, got "oh no"' - - it 'handle "Invalid closing quote"', (next) -> - errors = 0 - parser = parse skip_records_with_error: true, (err, records) -> - records.should.eql [ - ["a","b","c"] - ["one","two","three"] - ["seven","eight","nine"] - ] unless err - errors.should.eql 1 - next err - parser.on 'skip', (err) -> - assert_error err, - message: 'Invalid Closing Quote: got " " at line 3 instead of delimiter, record delimiter, trimable character (if activated) or comment' - code: 'CSV_INVALID_CLOSING_QUOTE' - errors++ - parser.write ''' - "a","b","c" - "one","two","three" - "four"," " ","six" - "seven","eight","nine" - ''' - parser.end() - - it 'handle "Invalid opening quote"', (next) -> - errors = [] - parser = parse skip_records_with_error: true, (err, records) -> - records.should.eql [ - ["line","1"] - ["line", "3"] - ] unless err - assert_error errors, [ - message: 'Invalid Opening Quote: a quote is found on field 1 at line 2, value is "invalid h"' - code: 'INVALID_OPENING_QUOTE' - field: 'invalid h' - , - message: 'Invalid Opening Quote: a quote is found on field 1 at line 2, value is "invalid h\\"ere"' - code: 'INVALID_OPENING_QUOTE' - field: 'invalid h"ere' - ] - errors.length.should.eql 2 - next err - parser.on 'skip', (err, context) -> - errors.push err - parser.write ''' - "line",1 - "line",invalid h"ere" - line,3 - ''' - parser.end() - - it 'handle "Quoted field not terminated"', (next) -> - errors = 0 - parser = parse skip_records_with_error: true, (err, records) -> - records.should.eql [ - ['a', 'b', 'c', 'd'] - ] unless err - errors.should.eql 1 - next err - parser.on 'skip', (err) -> - assert_error err, - message: 'Quote Not Closed: the parsing is finished with an opening quote at line 2' - code: 'CSV_QUOTE_NOT_CLOSED' - errors++ - parser.write ''' - "a",b,"c",d - "",1974,8.8392926E7,""," - ''' - parser.end() - - it 'handle "CSV_RECORD_INCONSISTENT_COLUMNS"', (next) -> - errors = 0 - parser = parse skip_records_with_error: true, columns: ["a", "b", "c", "d"], (err, records) -> - records.should.eql [ - { a: '4', b: '5', c: '6', d: 'x'} - { a: '7', b: '8', c: '9', d: 'y'} - ] unless err - errors.should.eql 1 - next err - parser.on 'skip', (err) -> - assert_error err, - message: 'Invalid Record Length: columns length is 4, got 3 on line 1' - code: 'CSV_RECORD_INCONSISTENT_COLUMNS' - record: ['1', '2', '3'] - errors++ - parser.write ''' - 1,2,3 - 4,5,6,x - 7,8,9,y - ''' - parser.end() - - it 'handle "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH"', (next) -> - errors = 0 - parser = parse skip_records_with_error: true, (err, records) -> - records.should.eql [ - ['a', 'b', 'c', 'd'] - ['e', 'f', 'g', 'h'] - ] unless err - errors.should.eql 1 - next err - parser.on 'skip', (err) -> - assert_error err, - message: 'Invalid Record Length: expect 4, got 3 on line 2' - code: 'CSV_RECORD_INCONSISTENT_FIELDS_LENGTH' - record: ['1', '2', '3'] - errors++ - parser.write ''' - a,b,c,d - 1,2,3 - e,f,g,h - ''' - parser.end() - - describe 'with `bom` option', -> - - it 'handle "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH" with bom (fix #411)', (next) -> - errors = 0 - parser = parse bom: true, skip_records_with_error: true, (err, records) -> - records.should.eql [ - ['a', 'b', 'c', 'd'] - ['e', 'f', 'g', 'h'] - ] unless err - errors.should.eql 1 - next err - parser.on 'skip', (err) -> - assert_error err, - message: 'Invalid Record Length: expect 4, got 3 on line 2' - code: 'CSV_RECORD_INCONSISTENT_FIELDS_LENGTH' - record: ['1', '2', '3'] - errors++ - parser.write ''' - \ufeffa,b,c,d - 1,2,3 - e,f,g,h - ''' - parser.end() - - describe 'with `raw` option', -> - - it 'print raw record', (next) -> - errors = 0 - parser = parse ''' - "a","b","c" - "one","two","three" - "four"," " ","six" - "seven","eight","nine" - ''' - , - skip_records_with_error: true - raw: true - , (err) -> - errors.should.eql 1 - next err - parser.on 'skip', (err, raw) -> - err.raw.should.eql '"four"," "' - raw.should.eql '"four"," "' - errors++ diff --git a/packages/csv-parse/test/option.skip_records_with_error.js b/packages/csv-parse/test/option.skip_records_with_error.js new file mode 100644 index 000000000..e283154f4 --- /dev/null +++ b/packages/csv-parse/test/option.skip_records_with_error.js @@ -0,0 +1,17 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `skip_records_with_error`", function () { + it("validation", function () { + (() => { + parse("", { skip_records_with_error: 1 }, () => {}); + }).should.throw( + "Invalid Option: skip_records_with_error must be a boolean, got 1", + ); + (() => { + parse("", { skip_records_with_error: "oh no" }, () => {}); + }).should.throw( + 'Invalid Option: skip_records_with_error must be a boolean, got "oh no"', + ); + }); +}); diff --git a/packages/csv-parse/test/option.skip_records_with_error.ts b/packages/csv-parse/test/option.skip_records_with_error.ts new file mode 100644 index 000000000..861050fcc --- /dev/null +++ b/packages/csv-parse/test/option.skip_records_with_error.ts @@ -0,0 +1,222 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; +import { assert_error } from "./api.assert_error.js"; +import { CsvError } from "../dist/cjs/index.cjs"; + +describe("Option `skip_records_with_error`", function () { + it("validation", function () { + parse("", { skip_records_with_error: true }, () => {}); + parse("", { skip_records_with_error: false }, () => {}); + parse("", { skip_records_with_error: null }, () => {}); + parse("", { skip_records_with_error: undefined }, () => {}); + }); + + it('handle "Invalid closing quote"', function (next) { + let errors = 0; + const parser = parse({ skip_records_with_error: true }, (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c"], + ["one", "two", "three"], + ["seven", "eight", "nine"], + ]); + } + errors.should.eql(1); + next(err); + }); + parser.on("skip", (err) => { + assert_error(err, { + message: + 'Invalid Closing Quote: got " " at line 3 instead of delimiter, record delimiter, trimable character (if activated) or comment', + code: "CSV_INVALID_CLOSING_QUOTE", + }); + errors++; + }); + parser.write( + dedent` + "a","b","c" + "one","two","three" + "four"," " ","six" + "seven","eight","nine" + `, + ); + parser.end(); + }); + + it('handle "Invalid opening quote"', function (next) { + const errors: CsvError[] = []; + const parser = parse({ skip_records_with_error: true }, (err, records) => { + if (!err) { + records.should.eql([ + ["line", "1"], + ["line", "3"], + ]); + } + assert_error(errors, [ + { + message: + 'Invalid Opening Quote: a quote is found on field 1 at line 2, value is "invalid h"', + code: "INVALID_OPENING_QUOTE", + field: "invalid h", + }, + { + message: + 'Invalid Opening Quote: a quote is found on field 1 at line 2, value is "invalid h\\"ere"', + code: "INVALID_OPENING_QUOTE", + field: 'invalid h"ere', + }, + ]); + errors.length.should.eql(2); + next(err); + }); + parser.on("skip", (err) => { + errors.push(err); + }); + parser.write(dedent` + "line",1 + "line",invalid h"ere" + line,3 + `); + parser.end(); + }); + + it('handle "Quoted field not terminated"', function (next) { + let errors = 0; + const parser = parse({ skip_records_with_error: true }, (err, records) => { + if (!err) { + records.should.eql([["a", "b", "c", "d"]]); + } + errors.should.eql(1); + next(err); + }); + parser.on("skip", (err) => { + assert_error(err, { + message: + "Quote Not Closed: the parsing is finished with an opening quote at line 2", + code: "CSV_QUOTE_NOT_CLOSED", + }); + errors++; + }); + parser.write(dedent` + "a",b,"c",d + "",1974,8.8392926E7,""," + `); + parser.end(); + }); + + it('handle "CSV_RECORD_INCONSISTENT_COLUMNS"', function (next) { + let errors = 0; + const parser = parse( + { skip_records_with_error: true, columns: ["a", "b", "c", "d"] }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: "4", b: "5", c: "6", d: "x" }, + { a: "7", b: "8", c: "9", d: "y" }, + ]); + } + errors.should.eql(1); + next(err); + }, + ); + parser.on("skip", (err) => { + assert_error(err, { + message: "Invalid Record Length: columns length is 4, got 3 on line 1", + code: "CSV_RECORD_INCONSISTENT_COLUMNS", + record: ["1", "2", "3"], + }); + errors++; + }); + parser.write(dedent` + 1,2,3 + 4,5,6,x + 7,8,9,y + `); + parser.end(); + }); + + it('handle "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH"', function (next) { + let errors = 0; + const parser = parse({ skip_records_with_error: true }, (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c", "d"], + ["e", "f", "g", "h"], + ]); + } + errors.should.eql(1); + next(err); + }); + parser.on("skip", (err) => { + assert_error(err, { + message: "Invalid Record Length: expect 4, got 3 on line 2", + code: "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", + record: ["1", "2", "3"], + }); + errors++; + }); + parser.write(dedent` + a,b,c,d + 1,2,3 + e,f,g,h + `); + parser.end(); + }); + + describe("with `bom` option", function () { + it('handle "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH" with bom (fix #411)', function (next) { + let errors = 0; + const parser = parse( + { bom: true, skip_records_with_error: true }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c", "d"], + ["e", "f", "g", "h"], + ]); + } + errors.should.eql(1); + next(err); + }, + ); + parser.on("skip", (err) => { + assert_error(err, { + message: "Invalid Record Length: expect 4, got 3 on line 2", + code: "CSV_RECORD_INCONSISTENT_FIELDS_LENGTH", + record: ["1", "2", "3"], + }); + errors++; + }); + parser.write("\ufeffa,b,c,d\n1,2,3\ne,f,g,h"); + parser.end(); + }); + }); + + describe("with `raw` option", function () { + it("print raw record", function (next) { + let errors = 0; + const parser = parse( + dedent` + "a","b","c" + "one","two","three" + "four"," " ","six" + "seven","eight","nine" + `, + { + skip_records_with_error: true, + raw: true, + }, + (err) => { + errors.should.eql(1); + next(err); + }, + ); + parser.on("skip", (err, raw) => { + err.raw.should.eql('"four"," "'); + raw.should.eql('"four"," "'); + errors++; + }); + }); + }); +}); diff --git a/packages/csv-parse/test/option.to.coffee b/packages/csv-parse/test/option.to.coffee deleted file mode 100644 index 02f2ccdbc..000000000 --- a/packages/csv-parse/test/option.to.coffee +++ /dev/null @@ -1,91 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `to`', -> - - it 'validation', -> - parse '', to: 10, (->) - parse '', to: "10", (->) - (-> - parse '', to: -1, (->) - ).should.throw 'Invalid Option: to must be a positive integer greater than 0, got -1' - (-> - parse '', to: 0, (->) - ).should.throw 'Invalid Option: to must be a positive integer greater than 0, got 0' - (-> - parse '', to: '0', (->) - ).should.throw 'Invalid Option: to must be a positive integer greater than 0, got "0"' - (-> - parse '', to: true, (->) - ).should.throw 'Invalid Option: to must be an integer, got true' - (-> - parse '', to: false, (->) - ).should.throw 'Invalid Option: to must be an integer, got false' - (-> - parse '', to: 'oh no', (->) - ).should.throw 'Invalid Option: to must be an integer, got "oh no"' - - it 'start at defined position', (next) -> - parse """ - 1,2,3 - 4,5,6 - 7,8,9 - """, to: 2, (err, records) -> - return next err if err - records.should.eql [ - [ '1','2','3' ] - [ '4','5','6' ] - ] - next() - - it 'dont count headers', (next) -> - parse """ - a,b,c - 1,2,3 - 4,5,6 - 7,8,9 - """, columns: true, to: 2, (err, records) -> - return next err if err - records.should.eql [ - {a:'1',b:'2',c:'3'} - {a:'4',b:'5',c:'6'} - ] - next() - - it 'end stream when "to" is reached, further lines are not parsed', (next) -> - parse """ - 1,2,3 - 4,5,6 - 7,8 - """, to: 2, (err, records) -> - return next err if err - records.should.eql [ - [ '1','2','3' ] - [ '4','5','6' ] - ] - next() - - it 'not influenced by lines', (next) -> - parse """ - 1,2," - 3" - 4,5," - 6" - 7,8," - 9" - """, to: 2, (err, records) -> - records.should.eql [ - [ '1','2','\n3' ] - [ '4','5','\n6' ] - ] unless err - next err - - it 'not influenced by record delimiter', (next) -> - parse """ - 1,2,3:4,5,6:7,8,9 - """, to: 2, record_delimiter: ':', (err, records) -> - records.should.eql [ - [ '1','2','3' ] - [ '4','5','6' ] - ] unless err - next err diff --git a/packages/csv-parse/test/option.to.js b/packages/csv-parse/test/option.to.js new file mode 100644 index 000000000..4b408c7f7 --- /dev/null +++ b/packages/csv-parse/test/option.to.js @@ -0,0 +1,13 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `to`", function () { + it("validation", function () { + (() => { + parse("", { to: true }, () => {}); + }).should.throw("Invalid Option: to must be an integer, got true"); + (() => { + parse("", { to: false }, () => {}); + }).should.throw("Invalid Option: to must be an integer, got false"); + }); +}); diff --git a/packages/csv-parse/test/option.to.ts b/packages/csv-parse/test/option.to.ts new file mode 100644 index 000000000..129eefedd --- /dev/null +++ b/packages/csv-parse/test/option.to.ts @@ -0,0 +1,126 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; + +describe("Option `to`", function () { + it("validation", function () { + parse("", { to: 10 }, () => {}); + parse("", { to: "10" }, () => {}); + parse("", { to: null }, () => {}); + (() => { + parse("", { to: -2 }, () => {}); + }).should.throw( + "Invalid Option: to must be a positive integer greater than 0, got -2", + ); + (() => { + parse("", { to: 0 }, () => {}); + }).should.throw( + "Invalid Option: to must be a positive integer greater than 0, got 0", + ); + (() => { + parse("", { to: "0" }, () => {}); + }).should.throw( + 'Invalid Option: to must be a positive integer greater than 0, got "0"', + ); + (() => { + parse("", { to: "oh no" }, () => {}); + }).should.throw('Invalid Option: to must be an integer, got "oh no"'); + }); + + it("start at defined position", function (next) { + parse( + dedent` + 1,2,3 + 4,5,6 + 7,8,9 + `, + { to: 2 }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["1", "2", "3"], + ["4", "5", "6"], + ]); + next(); + }, + ); + }); + + it("dont count headers", function (next) { + parse( + dedent` + a,b,c + 1,2,3 + 4,5,6 + 7,8,9 + `, + { columns: true, to: 2 }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + { a: "1", b: "2", c: "3" }, + { a: "4", b: "5", c: "6" }, + ]); + next(); + }, + ); + }); + + it('end stream when "to" is reached, further lines are not parsed', function (next) { + parse( + dedent` + 1,2,3\n4,5,6\n7,8 + `, + { to: 2 }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + ["1", "2", "3"], + ["4", "5", "6"], + ]); + next(); + }, + ); + }); + + it("not influenced by lines", function (next) { + parse( + dedent` + 1,2," + 3" + 4,5," + 6" + 7,8," + 9" + `, + { to: 2 }, + (err, records) => { + if (!err) { + records.should.eql([ + ["1", "2", "\n3"], + ["4", "5", "\n6"], + ]); + } + next(err); + }, + ); + }); + + it("not influenced by record delimiter", function (next) { + parse( + dedent` + 1,2,3:4,5,6:7,8,9 + `, + { to: 2, record_delimiter: ":" }, + (err, records) => { + if (!err) { + records.should.eql([ + ["1", "2", "3"], + ["4", "5", "6"], + ]); + } + next(err); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/option.to_line.coffee b/packages/csv-parse/test/option.to_line.coffee deleted file mode 100644 index 4337e1d08..000000000 --- a/packages/csv-parse/test/option.to_line.coffee +++ /dev/null @@ -1,101 +0,0 @@ - -import { Readable } from 'node:stream' -import { parse } from '../lib/index.js' -import { generate } from 'csv-generate' - -describe 'Option `to_line`', -> - - it 'validation', -> - parse '', to_line: 10, (->) - parse '', to_line: "10", (->) - parse '', to_line: null, (->) - parse '', to_line: undefined, (->) - (-> - parse '', to_line: -1, (->) - ).should.throw 'Invalid Option: to_line must be a positive integer greater than 0, got -1' - (-> - parse '', to_line: 0, (->) - ).should.throw 'Invalid Option: to_line must be a positive integer greater than 0, got 0' - (-> - parse '', to_line: "0", (->) - ).should.throw 'Invalid Option: to_line must be a positive integer greater than 0, got "0"' - (-> - parse '', to_line: true, (->) - ).should.throw 'Invalid Option: to_line must be an integer, got true' - (-> - parse '', to_line: false, (->) - ).should.throw 'Invalid Option: to_line must be an integer, got false' - (-> - parse '', to_line: 'oh no', (->) - ).should.throw 'Invalid Option: to_line must be an integer, got "oh no"' - - it 'start at defined position', (next) -> - parse """ - 1,2,3 - 4,5,6 - 7,8,9 - """, to_line: 2, (err, records) -> - records.should.eql [ - [ '1','2','3' ] - [ '4','5','6' ] - ] unless err - next err - - it 'count headers', (next) -> - parse """ - a,b,c - 1,2,3 - 4,5,6 - 7,8,9 - """, columns: true, to_line: 3, (err, records) -> - records.should.eql [ - {a: '1',b: '2',c: '3'} - {a: '4',b: '5',c: '6'} - ] unless err - next err - - it 'records with quoted line at the end of line', (next) -> - parse """ - 1,2," - - 3" - 4,5," - 6" - 7,8," - 9" - """, to_line: 5, (err, records) -> - records.should.eql [ - [ '1','2','\n\n3' ] - [ '4','5','\n6' ] - ] unless err - next err - - it 'records with quoted line in the middle of line', (next) -> - parse """ - 1,2," - - 3" - 4,5," - 6" - 7,8," - 9" - """, to_line: 6, (err, records) -> - records.should.eql [ - [ '1','2','\n\n3' ] - [ '4','5','\n6' ] - ] unless err - next err - - it 'not influenced by record delimiter', (next) -> - parse """ - a,b,c:1,2, - 3:d,e,f:4,5, - 6:g,h,i:7,8, - 9 - """, to_line: 2, record_delimiter: ':', (err, records) -> - records.should.eql [ - [ 'a','b','c' ] - [ '1','2','\n3' ] - [ 'd','e','f' ] - ] unless err - next err diff --git a/packages/csv-parse/test/option.to_line.js b/packages/csv-parse/test/option.to_line.js new file mode 100644 index 000000000..d3026ac41 --- /dev/null +++ b/packages/csv-parse/test/option.to_line.js @@ -0,0 +1,21 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `to_line`", function () { + it("validation", function () { + (() => { + parse("", { to_line: "0" }, () => {}); + }).should.throw( + 'Invalid Option: to_line must be a positive integer greater than 0, got "0"', + ); + (() => { + parse("", { to_line: true }, () => {}); + }).should.throw("Invalid Option: to_line must be an integer, got true"); + (() => { + parse("", { to_line: false }, () => {}); + }).should.throw("Invalid Option: to_line must be an integer, got false"); + (() => { + parse("", { to_line: "oh no" }, () => {}); + }).should.throw('Invalid Option: to_line must be an integer, got "oh no"'); + }); +}); diff --git a/packages/csv-parse/test/option.to_line.ts b/packages/csv-parse/test/option.to_line.ts new file mode 100644 index 000000000..1b128cf44 --- /dev/null +++ b/packages/csv-parse/test/option.to_line.ts @@ -0,0 +1,133 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; + +describe("Option `to_line`", function () { + it("validation", function () { + parse("", { to_line: 10 }, () => {}); + parse("", { to_line: "10" }, () => {}); + parse("", { to_line: null }, () => {}); + parse("", { to_line: undefined }, () => {}); + (() => { + parse("", { to_line: -2 }, () => {}); + }).should.throw( + "Invalid Option: to_line must be a positive integer greater than 0, got -2", + ); + (() => { + parse("", { to_line: 0 }, () => {}); + }).should.throw( + "Invalid Option: to_line must be a positive integer greater than 0, got 0", + ); + }); + + it("start at defined position", function (next) { + parse( + dedent` + 1,2,3 + 4,5,6 + 7,8,9 + `, + { to_line: 2 }, + (err, records) => { + if (!err) { + records.should.eql([ + ["1", "2", "3"], + ["4", "5", "6"], + ]); + } + next(err); + }, + ); + }); + + it("count headers", function (next) { + parse( + dedent` + a,b,c + 1,2,3 + 4,5,6 + 7,8,9 + `, + { columns: true, to_line: 3 }, + (err, records) => { + if (!err) { + records.should.eql([ + { a: "1", b: "2", c: "3" }, + { a: "4", b: "5", c: "6" }, + ]); + } + next(err); + }, + ); + }); + + it("records with quoted line at the end of line", function (next) { + parse( + dedent` + 1,2," + + 3" + 4,5," + 6" + 7,8," + 9" + `, + { to_line: 5 }, + (err, records) => { + if (!err) { + records.should.eql([ + ["1", "2", "\n\n3"], + ["4", "5", "\n6"], + ]); + } + next(err); + }, + ); + }); + + it("records with quoted line in the middle of line", function (next) { + parse( + dedent` + 1,2," + + 3" + 4,5," + 6" + 7,8," + 9" + `, + { to_line: 6 }, + (err, records) => { + if (!err) { + records.should.eql([ + ["1", "2", "\n\n3"], + ["4", "5", "\n6"], + ]); + } + next(err); + }, + ); + }); + + it("not influenced by record delimiter", function (next) { + parse( + dedent` + a,b,c:1,2, + 3:d,e,f:4,5, + 6:g,h,i:7,8, + 9 + `, + { to_line: 2, record_delimiter: ":" }, + (err, records) => { + if (!err) { + records.should.eql([ + ["a", "b", "c"], + ["1", "2", "\n3"], + ["d", "e", "f"], + ]); + } + next(err); + }, + ); + }); +}); diff --git a/packages/csv-parse/test/option.trim.coffee b/packages/csv-parse/test/option.trim.coffee deleted file mode 100644 index f74c67048..000000000 --- a/packages/csv-parse/test/option.trim.coffee +++ /dev/null @@ -1,227 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Option `rtrim`', -> - - it 'validation', -> - parse '', rtrim: true, (->) - parse '', rtrim: false, (->) - parse '', rtrim: null, (->) - parse '', rtrim: undefined, (->) - (-> - parse '', rtrim: 1, (->) - ).should.throw 'Invalid Option: rtrim must be a boolean, got 1' - (-> - parse '', rtrim: "true", (->) - ).should.throw 'Invalid Option: rtrim must be a boolean, got "true"' - -describe 'Option `ltrim`', -> - - it 'validation', -> - parse '', ltrim: true, (->) - parse '', ltrim: false, (->) - parse '', ltrim: null, (->) - parse '', ltrim: undefined, (->) - (-> - parse '', ltrim: 1, (->) - ).should.throw 'Invalid Option: ltrim must be a boolean, got 1' - (-> - parse '', ltrim: "true", (->) - ).should.throw 'Invalid Option: ltrim must be a boolean, got "true"' - -describe 'Option `trim`', -> - - it 'validation', -> - parse '', trim: true, (->) - parse '', trim: false, (->) - parse '', trim: null, (->) - parse '', trim: undefined, (->) - (-> - parse '', trim: 1, (->) - ).should.throw 'Invalid Option: trim must be a boolean, got 1' - (-> - parse '', trim: "true", (->) - ).should.throw 'Invalid Option: trim must be a boolean, got "true"' - - it 'set ltrim', -> - parser = parse trim: true - parser.options.ltrim.should.be.true() - - it 'respect ltrim', -> - parser = parse trim: true, ltrim: false - parser.options.ltrim.should.be.false() - - it 'set rtrim', -> - parser = parse trim: true - parser.options.rtrim.should.be.true() - - it 'respect rtrim', -> - parser = parse trim: true, rtrim: false - parser.options.rtrim.should.be.false() - - it 'interpret whitespaces', (next) -> - parse [ - String.fromCharCode 9 # Horizontal tab - String.fromCharCode 10 # NL line feed - String.fromCharCode 12 # NP Form feed - String.fromCharCode 13 # Carriage return - String.fromCharCode 32 # Space - 'sth' - ].join(''), trim: true, record_delimiter: '|', (err, records) -> - records.should.eql [['sth']] - next() - - it 'should ignore the whitespaces immediately preceding and following the delimiter', (next) -> - records = [] - parser = parse trim: true - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'end', -> - records.should.eql [ - [ 'FIELD 1','FIELD 2','FIELD 3','FIELD 4','FIELD 5','FIELD 6' ] - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - ] - next() - parser.write [ - ' FIELD 1 , FIELD 2 , FIELD 3,FIELD 4 , FIELD 5,FIELD 6 ' - '20322051544,1979 ,8.8017226E7,ABC , 45 , 2000-01-01' - ' 28392898392, 1974,8.8392926E7,DEF , 23 , 2050-11-27' - ].join('\n') - parser.end() - - it 'should preserve whitespace inside text if there are quotes or not', (next) -> - records = [] - parser = parse trim: true - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'end', -> - records.should.eql [ - [ 'FIELD 1','FIELD 2','FIELD 3','FIELD 4','FIELD 5','FIELD 6' ] - [ '20322051544','1979','8.8017226E7','ABC DEF','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7',' ABC DEF ','23','2050-11-27' ] - ] - next() - parser.write """ - FIELD 1, FIELD 2, FIELD 3, FIELD 4, FIELD 5, FIELD 6 - 20322051544, 1979, 8.8017226E7, ABC DEF , 45, 2000-01-01 - 28392898392, 1974, 8.8392926E7," ABC DEF ", 23, 2050-11-27 - """ - parser.end() - - it 'with columns and last field is a space', (next) -> - parse 'h1,h2,h3, \n1,2,3, \n4,5,6, ', - delimiter: ',' - columns: true - trim: true - , (err, records) -> - records.should.eql [ - { h1: '1', h2: '2', h3: '3', '': '' } - { h1: '4', h2: '5', h3: '6', '': '' } - ] unless err - next err - - it 'last field empty', (next) -> - parse "a,", trim: true, (err, records) -> - records.should.eql [ [ 'a', '' ] ] unless err - next err - - it 'with skip_empty_lines and empty lines at the end', (next) -> - parse "letter,number\na,1\nb,2\nc,3\n", - columns: true - skip_empty_lines: true - trim: true - , (err, records) -> - return next err if err - records.should.eql [ - { letter: 'a', number: '1' } - { letter: 'b', number: '2' } - { letter: 'c', number: '3' } - ] - next() - - it 'write aggressively', (next) -> - records = [] - parser = parse({ trim: true }) - parser.on 'readable', -> - while(d = parser.read()) - records.push d - parser.on 'end', -> - records.should.eql [ - [ 'Test 0', '', ' 0,00 ', '"' ] - [ 'Test 1', '', ' 100000,100000 ', '"' ] - [ 'Test 2', '', ' 200000,200000 ', '"' ] - [ 'Test 3', '', ' 300000,300000 ', '"' ] - [ 'Test 4', '', ' 400000,400000 ', '"' ] - [ 'Test 5', '', ' 500000,500000 ', '"' ] - [ 'Test 6', '', ' 600000,600000 ', '"' ] - [ 'Test 7', '', ' 700000,700000 ', '"' ] - [ 'Test 8', '', ' 800000,800000 ', '"' ] - [ 'Test 9', '', ' 900000,900000 ', '"' ] - ] - next() - data = ''' - Test 0 ,," 0,00 ","""" - Test 1 ,," 100000,100000 ","""" - Test 2 ,," 200000,200000 ","""" - Test 3 ,," 300000,300000 ","""" - Test 4 ,," 400000,400000 ","""" - Test 5 ,," 500000,500000 ","""" - Test 6 ,," 600000,600000 ","""" - Test 7 ,," 700000,700000 ","""" - Test 8 ,," 800000,800000 ","""" - Test 9 ,," 900000,900000 ","""" - ''' - parser.write chr for chr in data - parser.end() - -describe 'no trim', -> - - it 'should preserve surrounding whitespaces', (next) -> - records = [] - parser = parse() - parser.on 'readable', -> - while d = parser.read() - records.push d - parser.on 'end', -> - records.should.eql [ - [ ' FIELD 1 ',' FIELD 2 ',' FIELD 3','FIELD 4 ',' FIELD 5','FIELD 6 ' ] - [ '20322051544','1979 ','8.8017226E7','AB C ',' 45 ',' 2000-01-01' ] - [ ' 28392898392',' 1974','8.8392926E7','D EF ',' 23 ',' 2050-11-27' ] - ] - next() - parser.write [ - ' FIELD 1 , FIELD 2 , FIELD 3,FIELD 4 , FIELD 5,FIELD 6 ' - '20322051544,1979 ,8.8017226E7,AB C , 45 , 2000-01-01' - ' 28392898392, 1974,8.8392926E7,D EF , 23 , 2050-11-27' - ].join('\n') - parser.end() - -describe 'options', -> - - it.skip 'with encoding', (next) -> - parse Buffer.from('a, a', 'utf8'), - encoding: 'utf8' - trim: true - , (err, records) -> - # records[0].map (record) -> console.log Buffer.from(record, 'utf16le') - records.should.eql [['a', 'a']] unless err - next err - - it 'ltrim with encoding', (next) -> - parse Buffer.from('ф, ф', 'utf16le'), - encoding: 'utf16le' - trim: true - , (err, records) -> - records.should.eql [['ф', 'ф']] unless err - next err - - it 'rtrim with encoding', (next) -> - parse Buffer.from('ф ,ф', 'utf16le'), - encoding: 'utf16le' - trim: true - , (err, records) -> - records.should.eql [['ф', 'ф']] unless err - next err diff --git a/packages/csv-parse/test/option.trim.js b/packages/csv-parse/test/option.trim.js new file mode 100644 index 000000000..107d08689 --- /dev/null +++ b/packages/csv-parse/test/option.trim.js @@ -0,0 +1,13 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Option `trim`", function () { + it("validation", function () { + (() => { + parse("", { trim: 1 }, () => {}); + }).should.throw("Invalid Option: trim must be a boolean, got 1"); + (() => { + parse("", { trim: "true" }, () => {}); + }).should.throw('Invalid Option: trim must be a boolean, got "true"'); + }); +}); diff --git a/packages/csv-parse/test/option.trim.ts b/packages/csv-parse/test/option.trim.ts new file mode 100644 index 000000000..7df62767d --- /dev/null +++ b/packages/csv-parse/test/option.trim.ts @@ -0,0 +1,303 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; + +describe("Option `trim`", function () { + it("validation", function () { + parse("", { trim: true }, () => {}); + parse("", { trim: false }, () => {}); + parse("", { trim: null }, () => {}); + parse("", { trim: undefined }, () => {}); + }); + + it("set ltrim", function () { + const parser = parse({ trim: true }); + parser.options.ltrim.should.be.true(); + }); + + it("respect ltrim", function () { + const parser = parse({ trim: true, ltrim: false }); + parser.options.ltrim.should.be.false(); + }); + + it("set rtrim", function () { + const parser = parse({ trim: true }); + parser.options.rtrim.should.be.true(); + }); + + it("respect rtrim", function () { + const parser = parse({ trim: true, rtrim: false }); + parser.options.rtrim.should.be.false(); + }); + + it("interpret whitespaces", function (next) { + parse( + [ + String.fromCharCode(9), // Horizontal tab + String.fromCharCode(10), // NL line feed + String.fromCharCode(12), // NP Form feed + String.fromCharCode(13), // Carriage return + String.fromCharCode(32), // Space + "sth", + ].join(""), + { trim: true, record_delimiter: "|" }, + (err, records) => { + records.should.eql([["sth"]]); + next(); + }, + ); + }); + + it("should ignore the whitespaces immediately preceding and following the delimiter", function (next) { + const records: string[] = []; + const parser = parse({ trim: true }); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + records.should.eql([ + ["FIELD 1", "FIELD 2", "FIELD 3", "FIELD 4", "FIELD 5", "FIELD 6"], + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ]); + next(); + }); + parser.write( + [ + " FIELD 1 , FIELD 2 , FIELD 3,FIELD 4 , FIELD 5,FIELD 6 ", + "20322051544,1979 ,8.8017226E7,ABC , 45 , 2000-01-01", + " 28392898392, 1974,8.8392926E7,DEF , 23 , 2050-11-27", + ].join("\n"), + ); + parser.end(); + }); + + it("should preserve whitespace inside text if there are quotes or not", function (next) { + const records: string[] = []; + const parser = parse({ trim: true }); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + records.should.eql([ + ["FIELD 1", "FIELD 2", "FIELD 3", "FIELD 4", "FIELD 5", "FIELD 6"], + ["20322051544", "1979", "8.8017226E7", "ABC DEF", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", " ABC DEF ", "23", "2050-11-27"], + ]); + next(); + }); + parser.write(dedent` + FIELD 1, FIELD 2, FIELD 3, FIELD 4, FIELD 5, FIELD 6 + 20322051544, 1979, 8.8017226E7, ABC DEF , 45, 2000-01-01 + 28392898392, 1974, 8.8392926E7," ABC DEF ", 23, 2050-11-27 + `); + parser.end(); + }); + + it("with columns and last field is a space", function (next) { + parse( + dedent` + h1,h2,h3, + 1,2,3, + 4,5,6, + `, + { + delimiter: ",", + columns: true, + trim: true, + }, + (err, records) => { + if (!err) { + records.should.eql([ + { h1: "1", h2: "2", h3: "3", "": "" }, + { h1: "4", h2: "5", h3: "6", "": "" }, + ]); + } + next(err); + }, + ); + }); + + it("last field empty", function (next) { + parse("a,", { trim: true }, (err, records) => { + if (!err) { + records.should.eql([["a", ""]]); + } + next(err); + }); + }); + + it("with skip_empty_lines and empty lines at the end", function (next) { + parse( + dedent` + letter,number + a,1 + + b,2 + c,3 + ` + "\n\n", + { + columns: true, + skip_empty_lines: true, + trim: true, + }, + (err, records) => { + if (err) return next(err); + records.should.eql([ + { letter: "a", number: "1" }, + { letter: "b", number: "2" }, + { letter: "c", number: "3" }, + ]); + next(); + }, + ); + }); + + it("write aggressively", function (next) { + const records: string[] = []; + const parser = parse({ trim: true }); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + records.should.eql([ + ["Test 0", "", " 0,00 ", '"'], + ["Test 1", "", " 100000,100000 ", '"'], + ["Test 2", "", " 200000,200000 ", '"'], + ["Test 3", "", " 300000,300000 ", '"'], + ["Test 4", "", " 400000,400000 ", '"'], + ["Test 5", "", " 500000,500000 ", '"'], + ["Test 6", "", " 600000,600000 ", '"'], + ["Test 7", "", " 700000,700000 ", '"'], + ["Test 8", "", " 800000,800000 ", '"'], + ["Test 9", "", " 900000,900000 ", '"'], + ]); + next(); + }); + const data = [ + ' Test 0 ,," 0,00 ","""" ', + ' Test 1 ,," 100000,100000 ","""" ', + ' Test 2 ,," 200000,200000 ","""" ', + ' Test 3 ,," 300000,300000 ","""" ', + ' Test 4 ,," 400000,400000 ","""" ', + ' Test 5 ,," 500000,500000 ","""" ', + ' Test 6 ,," 600000,600000 ","""" ', + ' Test 7 ,," 700000,700000 ","""" ', + ' Test 8 ,," 800000,800000 ","""" ', + ' Test 9 ,," 900000,900000 ","""" ', + ].join("\n"); + for (const chr of data) { + parser.write(chr); + } + parser.end(); + }); + + describe("no trim", function () { + it("should preserve surrounding whitespaces", function (next) { + const records: string[] = []; + const parser = parse(); + parser.on("readable", () => { + let d; + while ((d = parser.read())) { + records.push(d); + } + }); + parser.on("end", () => { + records.should.eql([ + [ + " FIELD 1 ", + " FIELD 2 ", + " FIELD 3", + "FIELD 4 ", + " FIELD 5", + "FIELD 6 ", + ], + [ + "20322051544", + "1979 ", + "8.8017226E7", + "AB C ", + " 45 ", + " 2000-01-01", + ], + [ + " 28392898392", + " 1974", + "8.8392926E7", + "D EF ", + " 23 ", + " 2050-11-27", + ], + ]); + next(); + }); + parser.write( + [ + " FIELD 1 , FIELD 2 , FIELD 3,FIELD 4 , FIELD 5,FIELD 6 ", + "20322051544,1979 ,8.8017226E7,AB C , 45 , 2000-01-01", + " 28392898392, 1974,8.8392926E7,D EF , 23 , 2050-11-27", + ].join("\n"), + ); + parser.end(); + }); + }); + + describe("options", function () { + it("with encoding", function (next) { + parse( + Buffer.from(" ф , ф ", "utf16le"), + { + encoding: "utf16le", + trim: true, + }, + (err, records) => { + if (!err) { + records.should.eql([["ф", "ф"]]); + } + next(err); + }, + ); + }); + + it("ltrim with encoding", function (next) { + parse( + Buffer.from(" ф , ф ", "utf16le"), + { + encoding: "utf16le", + ltrim: true, + }, + (err, records) => { + if (!err) { + records.should.eql([["ф ", "ф "]]); + } + next(err); + }, + ); + }); + + it("rtrim with encoding", function (next) { + parse( + Buffer.from(" ф , ф ", "utf16le"), + { + encoding: "utf16le", + rtrim: true, + }, + (err, records) => { + if (!err) { + records.should.eql([[" ф", " ф"]]); + } + next(err); + }, + ); + }); + }); +}); diff --git a/packages/csv-parse/test/options.coffee b/packages/csv-parse/test/options.coffee deleted file mode 100644 index 3a0bf24d5..000000000 --- a/packages/csv-parse/test/options.coffee +++ /dev/null @@ -1,20 +0,0 @@ - -import { parse } from '../lib/index.js' - -describe 'Options', -> - - it 'are cloned', (next) -> - options = quote: false - parse """ - FIELD_1,FIELD_2 - 20322051544,1979 - 28392898392,1974 - """, options, (err) -> - return next err if err - (options.quote is false).should.be.true() - next() - - it 'underscore options', -> - parser = parse recordDelimiter: ':' - parser.options.record_delimiter.toString().should.eql ':' - (parser.options.recordDelimiter is undefined).should.be.true() diff --git a/packages/csv-parse/test/options.js b/packages/csv-parse/test/options.js new file mode 100644 index 000000000..a347ade19 --- /dev/null +++ b/packages/csv-parse/test/options.js @@ -0,0 +1,9 @@ +import "should"; +import { parse } from "../lib/index.js"; + +describe("Options", function () { + it("camel case options are not disposed", function () { + const parser = parse({ recordDelimiter: ":" }); + (parser.options.recordDelimiter === undefined).should.be.true(); + }); +}); diff --git a/packages/csv-parse/test/options.ts b/packages/csv-parse/test/options.ts new file mode 100644 index 000000000..0437ca2a7 --- /dev/null +++ b/packages/csv-parse/test/options.ts @@ -0,0 +1,27 @@ +import "should"; +import dedent from "dedent"; +import { parse } from "../lib/index.js"; + +describe("Options", function () { + it("are cloned", function (next) { + const options = { quote: false }; + parse( + dedent` + FIELD_1,FIELD_2 + 20322051544,1979 + 28392898392,1974 + `, + options, + (err) => { + if (err) return next(err); + (options.quote === false).should.be.true(); + next(); + }, + ); + }); + + it("camelcase options are converted to underscore", function () { + const parser = parse({ recordDelimiter: ":" }); + parser.options.record_delimiter.toString().should.eql(":"); + }); +}); diff --git a/packages/csv-parse/test/samples.coffee b/packages/csv-parse/test/samples.coffee deleted file mode 100644 index 7f52fbf2f..000000000 --- a/packages/csv-parse/test/samples.coffee +++ /dev/null @@ -1,31 +0,0 @@ -import fs from 'node:fs/promises' -import path from 'node:path' -import { spawn } from 'node:child_process' - -[_, major] = process.version.match(/(\d+)\.\d+\.\d+/) -__dirname = new URL( '.', import.meta.url).pathname -dir = path.resolve __dirname, '../samples' -samples = await fs.readdir dir - -describe 'Samples', -> - - samples - .filter (sample) -> ! (major < 16 && sample is 'recipe.promises.js') - .filter (sample) -> - return false unless /\.(js|ts)?$/.test sample - true - .map (sample) -> - - it "Sample #{sample}", () -> - data = await fs.readFile path.resolve(dir, sample), 'utf8' - return if /^["|']skip test["|']/.test data - new Promise (resolve, reject) -> - ext = /\.(\w+)?$/.exec(sample)[0] - [cmd, ...args] = switch ext - when '.js' - ['node', path.resolve dir, sample] - when '.ts' - ['node', '--loader', 'ts-node/esm', path.resolve dir, sample] - spawn(cmd, args) - .on 'close', (code) -> if code is 0 then resolve() else reject(new Error 'Failure') - .stdout.on 'data', (->) diff --git a/packages/csv-parse/test/samples.js b/packages/csv-parse/test/samples.js new file mode 100644 index 000000000..8eb8e66e4 --- /dev/null +++ b/packages/csv-parse/test/samples.js @@ -0,0 +1,47 @@ +import fs from "node:fs/promises"; +import path from "node:path"; +import { spawn } from "node:child_process"; + +const __dirname = new URL(".", import.meta.url).pathname; +const dir = path.resolve(__dirname, "../samples"); +const samples = await fs.readdir(dir); + +const [, major] = process.version.match(/(\d+)\.\d+\.\d+/); + +describe("Samples", function () { + /* eslint mocha/no-setup-in-describe: "off" */ + samples + .filter((sample) => !(major < 16 && sample === "recipe.promises.js")) + .filter((sample) => { + if (!/\.(js|ts)?$/.test(sample)) return false; + return true; + }) + .map((sample) => { + it(`Sample ${sample}`, async function () { + const data = await fs.readFile(path.resolve(dir, sample), "utf8"); + if (/^["|']skip test["|']/.test(data)) return; + return new Promise((resolve, reject) => { + const ext = /\.(\w+)?$/.exec(sample)[0]; + let cmd, args; + switch (ext) { + case ".js": + [cmd, ...args] = ["node", path.resolve(dir, sample)]; + break; + case ".ts": + [cmd, ...args] = [ + "node", + "--loader", + "ts-node/esm", + path.resolve(dir, sample), + ]; + break; + } + spawn(cmd, args) + .on("close", (code) => + code === 0 ? resolve() : reject(new Error("Failure")), + ) + .stdout.on("data", () => {}); + }); + }); + }); +}); diff --git a/packages/csv-parse/test/spectrum.coffee b/packages/csv-parse/test/spectrum.coffee deleted file mode 100644 index 02376f9b4..000000000 --- a/packages/csv-parse/test/spectrum.coffee +++ /dev/null @@ -1,15 +0,0 @@ - -import { default as spectrum } from 'csv-spectrum' -import { default as each } from 'each' -import { parse } from '../lib/sync.js' - -describe 'spectrum', -> - - it 'pass all tests', (next) -> - spectrum (err, tests) -> - each tests, (test) -> - return if test.name is 'simple' # See https://github.com/maxogden/csv-spectrum/commit/ec45e96a79661d7bd87f6becbb845b30f11accde - return if test.name is 'location_coordinates'# See https://github.com/max-mapper/csv-spectrum/issues/20 - records = parse test.csv.toString(), columns: true, relax_quotes: true - records.should.eql JSON.parse test.json.toString() - .then (-> next()), next diff --git a/packages/csv-parse/test/spectrum.js b/packages/csv-parse/test/spectrum.js new file mode 100644 index 000000000..2a1e65164 --- /dev/null +++ b/packages/csv-parse/test/spectrum.js @@ -0,0 +1,20 @@ +import "should"; +import { default as spectrum } from "csv-spectrum"; +import { default as each } from "each"; +import { parse } from "../lib/sync.js"; + +describe("spectrum", function () { + it("pass all tests", function (next) { + spectrum((err, tests) => { + each(tests, (test) => { + if (test.name === "simple") return; // See https://github.com/maxogden/csv-spectrum/commit/ec45e96a79661d7bd87f6becbb845b30f11accde + if (test.name === "location_coordinates") return; // See https://github.com/max-mapper/csv-spectrum/issues/20 + const records = parse(test.csv.toString(), { + columns: true, + relax_quotes: true, + }); + records.should.eql(JSON.parse(test.json.toString())); + }).then(() => next(), next); + }); + }); +}); diff --git a/packages/csv-parse/tsconfig.json b/packages/csv-parse/tsconfig.json index 4db508a7c..5da38148b 100644 --- a/packages/csv-parse/tsconfig.json +++ b/packages/csv-parse/tsconfig.json @@ -4,6 +4,6 @@ "esModuleInterop": true, "module": "ES2020", "moduleResolution": "node", - "strict": true, + "strict": true } } diff --git a/packages/csv-stringify/CHANGELOG.md b/packages/csv-stringify/CHANGELOG.md index 47814ccc9..583b58737 100644 --- a/packages/csv-stringify/CHANGELOG.md +++ b/packages/csv-stringify/CHANGELOG.md @@ -3,6 +3,51 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 6.6.0 (2025-07-10) + +### Features + +- add unicode chars to formula escape ([#387](https://github.com/adaltas/node-csv/issues/387)) ([1fc177c](https://github.com/adaltas/node-csv/commit/1fc177c605e8a88e403539806890695a6ba72dec)) +- backport support for node 14 ([dbfeb78](https://github.com/adaltas/node-csv/commit/dbfeb78f61ed36f02936d63a53345708ca213e45)) +- backward support for node 8 ([496231d](https://github.com/adaltas/node-csv/commit/496231dfd838f0a6a72269a5a2390a4c637cef95)) +- **csv-parse:** set `columns` type as `readonly` ([#358](https://github.com/adaltas/node-csv/issues/358)) ([44f2e7c](https://github.com/adaltas/node-csv/commit/44f2e7c2d1c36adf2b1f5a32ee181b3c4c4b50d7)) +- **csv-stringify:** Add escape_formulas to defend against injection attacks ([#380](https://github.com/adaltas/node-csv/issues/380)) ([47ac4bd](https://github.com/adaltas/node-csv/commit/47ac4bd7f5838e28daf889528fd6427ad0934076)) +- **csv-stringify:** ts extends options with stream.TransformOptions ([#301](https://github.com/adaltas/node-csv/issues/301)) ([cc30d66](https://github.com/adaltas/node-csv/commit/cc30d66e0f07686d2c42670ead10246ebcf37a67)) +- esm migration ([b5c0d4b](https://github.com/adaltas/node-csv/commit/b5c0d4b191c8b57397808c0922a3f08248506a9f)) +- export ts types in sync ([890bf8d](https://github.com/adaltas/node-csv/commit/890bf8d950c18a05cab5e35a461d0847d9425156)) +- replace ts types with typesVersions ([acb41d5](https://github.com/adaltas/node-csv/commit/acb41d5031669f2d582e40da1c80f5fd4738fee4)) +- ts module Node16 and type declaration to exports field ([#341](https://github.com/adaltas/node-csv/issues/341)) ([4b0283d](https://github.com/adaltas/node-csv/commit/4b0283d17b7fa46daa1f87380759ba72c71ec79b)) +- wg stream api ([8a5eb7d](https://github.com/adaltas/node-csv/commit/8a5eb7dfd31b22217db4fbbc832d707221850785)) + +### Bug Fixes + +- commonjs types, run tsc and lint to validate changes ([#397](https://github.com/adaltas/node-csv/issues/397)) ([e6870fe](https://github.com/adaltas/node-csv/commit/e6870fe272c119e273196522c9771d12ff8b2a35)) +- correct exports in package.json with webpack ([154eafb](https://github.com/adaltas/node-csv/commit/154eafbac866eb4499a0d392f8dcd057695c2586)) +- **csv-demo-ts-cjs-node16:** upgrade module definition after latest typescript ([87fe919](https://github.com/adaltas/node-csv/commit/87fe91996fb2a8895c252177fca4f0cb59a518f9)) +- **csv-demo-webpack-ts:** remove polyfill ([47a99bd](https://github.com/adaltas/node-csv/commit/47a99bd944d1d943e6374227dbc4e20aaa2c8c7f)) +- **csv-demo-webpack-ts:** simplify export paths ([8d63a14](https://github.com/adaltas/node-csv/commit/8d63a14313bb6b26f13fafb740cc686f1dfaa65f)) +- **csv-stringify:** add missing type definition for bigint cast option ([#369](https://github.com/adaltas/node-csv/issues/369)) ([764e748](https://github.com/adaltas/node-csv/commit/764e7486971835189364ea7a0103798e5c07fb2b)) +- **csv-stringify:** allow mixed string and object columns typedef ([#456](https://github.com/adaltas/node-csv/issues/456)) ([c40c0d2](https://github.com/adaltas/node-csv/commit/c40c0d2114d7800cca8da2d685ad1e49bf4cc7eb)) +- **csv-stringify:** bom and header in sync mode with no records (fix [#343](https://github.com/adaltas/node-csv/issues/343)) ([bff158f](https://github.com/adaltas/node-csv/commit/bff158fbc9001b2cf7177ecd0f16dc97edac55f2)) +- **csv-stringify:** catch error with sync api, fix [#296](https://github.com/adaltas/node-csv/issues/296) ([e157f40](https://github.com/adaltas/node-csv/commit/e157f407eeffe5bcfb179cb20476169037bfb4f1)) +- **csv-stringify:** node 12 compatibility in flush ([9145b75](https://github.com/adaltas/node-csv/commit/9145b75012ec71a0b4152036af2275bf28c460e0)) +- **csv-stringify:** quote_match with empty string pattern quotes empty strings ([#345](https://github.com/adaltas/node-csv/issues/345)) ([1c22d2e](https://github.com/adaltas/node-csv/commit/1c22d2e07f66dd747150b5a7499b5ebd5bc0f25c)), closes [#344](https://github.com/adaltas/node-csv/issues/344) +- **csv-stringify:** remove non-functional auto value ([6e8a9ca](https://github.com/adaltas/node-csv/commit/6e8a9ca0a712c56c73eabeb8aa052bd6d197cb3f)) +- **csv-stringify:** throw err with no records and header in sync mode ([5c8ef2e](https://github.com/adaltas/node-csv/commit/5c8ef2e25618b122982e01c22bcfa3f8ed5db8aa)) +- **csv-stringify:** update quoted_match config option to accept arrays ([#371](https://github.com/adaltas/node-csv/issues/371)) ([42c468b](https://github.com/adaltas/node-csv/commit/42c468b188d9f0370d0f7ccf2b20c8f477b751d8)) +- **csv-stringify:** update TS types to allow cast to return an object ([#339](https://github.com/adaltas/node-csv/issues/339)) ([60efa78](https://github.com/adaltas/node-csv/commit/60efa7862ed43bd2fd19d1f027a1809e9df6a67e)) +- **csv-stringify:** use removeListener instead of off ([2c2623f](https://github.com/adaltas/node-csv/commit/2c2623f01a4985c5d248e1557a32a70350e825f6)) +- dont insert polyfills in cjs [#303](https://github.com/adaltas/node-csv/issues/303) ([9baf334](https://github.com/adaltas/node-csv/commit/9baf334044dab90b4a0d096a7e456d0fd5807d5b)) +- esm exports in package.json files ([c48fe47](https://github.com/adaltas/node-csv/commit/c48fe478ced7560aa078fbc36ec33d6007111e2b)), closes [#308](https://github.com/adaltas/node-csv/issues/308) +- export original lib esm modules ([be25349](https://github.com/adaltas/node-csv/commit/be2534928ba21156e9cde1e15d2e8593d62ffe71)) +- expose browser esm modules ([eb87355](https://github.com/adaltas/node-csv/commit/eb873557c65912f065d2581d30a17a96b0bfd2d6)) +- fallback to setTimeout is setImmediate is undefined ([3d6a2d0](https://github.com/adaltas/node-csv/commit/3d6a2d0a655af342f28456b46db7ccfe7ee9d664)) +- refer to esm files in dist ([b780fbd](https://github.com/adaltas/node-csv/commit/b780fbd26f5e54494e511eb2e004d3cdedee3593)) +- remove samples from publicatgion ([12c221d](https://github.com/adaltas/node-csv/commit/12c221dc37add26f094e3bb7f94b50ee06ff5be6)) +- support ts node16 resolution in cjs ([#354](https://github.com/adaltas/node-csv/issues/354)) ([fa09d03](https://github.com/adaltas/node-csv/commit/fa09d03aaf0008b2790656871ca6b2c4be12d14c)) +- support TypeScript moduleResolution node16 ([#368](https://github.com/adaltas/node-csv/issues/368)) ([f4d7c97](https://github.com/adaltas/node-csv/commit/f4d7c97f39fb73e9d248eee21e61e7dc48015c78)) +- uncaught errors with large stream chunks (fix [#386](https://github.com/adaltas/node-csv/issues/386)) ([1d500ed](https://github.com/adaltas/node-csv/commit/1d500edf38ba06fc80409974e08c37c6a40f27a1)) + ## [6.5.2](https://github.com/adaltas/node-csv/compare/csv-stringify@6.5.1...csv-stringify@6.5.2) (2024-11-21) **Note:** Version bump only for package csv-stringify diff --git a/packages/csv-stringify/dist/cjs/index.cjs b/packages/csv-stringify/dist/cjs/index.cjs index 7e170d787..22f55819c 100644 --- a/packages/csv-stringify/dist/cjs/index.cjs +++ b/packages/csv-stringify/dist/cjs/index.cjs @@ -52,6 +52,7 @@ const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv-stringify/dist/cjs/index.d.cts b/packages/csv-stringify/dist/cjs/index.d.cts index 618b7ee6b..4ce56ceda 100644 --- a/packages/csv-stringify/dist/cjs/index.d.cts +++ b/packages/csv-stringify/dist/cjs/index.d.cts @@ -2,124 +2,213 @@ import * as stream from "stream"; -export type Callback = (err: Error | undefined, output: string) => void -export type RecordDelimiter = string | Buffer | 'unix' | 'mac' | 'windows' | 'ascii' | 'unicode' +export type Callback = (err: Error | undefined, output: string) => void; +export type RecordDelimiter = + | string + | Buffer + | "unix" + | "mac" + | "windows" + | "ascii" + | "unicode"; export type CastReturnObject = { value: string } & Pick< - Options, - | 'delimiter' - | 'escape' - | 'quote' - | 'quoted' - | 'quoted_empty' - | 'quoted_string' - | 'quoted_match' - | 'record_delimiter' -> + Options, + | "delimiter" + | "escape" + | "quote" + | "quoted" + | "quoted_empty" + | "quoted_string" + | "quoted_match" + | "record_delimiter" +>; export type Cast = ( - value: T, - context: CastingContext -) => string | CastReturnObject; + value: T, + context: CastingContext, +) => string | null | CastReturnObject; -export type PlainObject = Record -export type Input = any[] +export type PlainObject = Record; +export type Input = any[]; export interface ColumnOption { - key: string - header?: string + key: string; + header?: string; } export interface CastingContext { - readonly column?: number | string; - readonly header: boolean; - readonly index: number; - readonly records: number; + readonly column?: number | string; + readonly header: boolean; + readonly index: number; + readonly records: number; } -export interface Options extends stream.TransformOptions { - /** - * Prepend the byte order mark (BOM) to the output stream. - */ - bom?: boolean - /** - * Key-value object which defines custom cast for certain data types - */ - cast?: { - boolean?: Cast - date?: Cast - number?: Cast - bigint?: Cast - /** - * Custom formatter for generic object values - */ - object?: Cast> - string?: Cast - } - /** - * List of fields, applied when `transform` returns an object - * order matters - * read the transformer documentation for additionnal information - * columns are auto discovered in the first record when the user write objects - * can refer to nested properties of the input JSON - * see the "header" option on how to print columns names on the first line - */ - columns?: readonly string[] | PlainObject | readonly ColumnOption[] - /** - * Set the field delimiter, one character only, defaults to a comma. - */ - delimiter?: string | Buffer - /** - * Add the value of "options.RecordDelimiter" on the last line, default to true. - */ - eof?: boolean - /** - * Defaults to the escape read option. - */ - escape?: string | Buffer - /** - * Display the column names on the first line if the columns option is provided or discovered. - */ - header?: boolean - /** - * The quote characters, defaults to the ", an empty quote value will preserve the original field. - */ - quote?: string | Buffer | boolean - /** - * Boolean, default to false, quote all the non-empty fields even if not required. - */ - quoted?: boolean +export interface OptionsNormalized extends stream.TransformOptions { + /** + * Prepend the byte order mark (BOM) to the output stream. + */ + bom: boolean; + /** + * Key-value object which defines custom cast for certain data types + */ + cast?: { + boolean?: Cast; + date?: Cast; + number?: Cast; + bigint?: Cast; /** - * Boolean, no default, quote empty fields and overrides `quoted_string` on empty strings when defined. - */ - quoted_empty?: boolean - /** - * String or RegExp, no default, quote all fields matching a regular expression. - */ - quoted_match?: string | RegExp | (string | RegExp)[] - /** - * Boolean, default to false, quote all fields of type string even if not required. + * Custom formatter for generic object values */ - quoted_string?: boolean - /** - * String used to delimit record rows or a special value - * special values are 'unix', 'mac', 'windows', 'ascii', 'unicode' - * defaults to '\n'. - */ - record_delimiter?: RecordDelimiter + object?: Cast>; + string?: Cast; + }; + /** + * List of fields, applied when `transform` returns an object + * order matters + * read the transformer documentation for additionnal information + * columns are auto discovered in the first record when the user write objects + * can refer to nested properties of the input JSON + * see the "header" option on how to print columns names on the first line + */ + columns: ReadonlyArray | PlainObject; + /** + * Set the field delimiter, one character only, defaults to a comma. + */ + delimiter: string; + /** + * Add the value of "options.RecordDelimiter" on the last line, default to true. + */ + eof: boolean; + /** + * Defaults to the escape read option. + */ + escape: string; + /** + * Display the column names on the first line if the columns option is provided or discovered. + */ + header: boolean; + /** + * The quote characters, defaults to the ", an empty quote value will preserve the original field. + */ + quote: string; + /** + * Boolean, default to false, quote all the non-empty fields even if not required. + */ + quoted: boolean; + + /** + * Boolean, no default, quote empty fields and overrides `quoted_string` on empty strings when defined. + */ + quoted_empty: boolean; + /** + * String or RegExp, no default, quote all fields matching a regular expression. + */ + quoted_match: null | (string | RegExp)[]; + /** + * Boolean, default to false, quote all fields of type string even if not required. + */ + quoted_string: boolean; + /** + * String used to delimit record rows or a special value + * special values are 'unix', 'mac', 'windows', 'ascii', 'unicode' + * defaults to '\n'. + */ + record_delimiter: RecordDelimiter; + /** + * Boolean, default to false, if true, fields that begin with `=`, `+`, `-`, `@`, `\t`, or `\r` will be prepended with a `'` to protected agains csv injection attacks + */ + escape_formulas: boolean; +} + +export interface Options extends stream.TransformOptions { + /** + * Prepend the byte order mark (BOM) to the output stream. + */ + bom?: boolean; + /** + * Key-value object which defines custom cast for certain data types + */ + cast?: { + boolean?: Cast; + date?: Cast; + number?: Cast; + bigint?: Cast; /** - * Boolean, default to false, if true, fields that begin with `=`, `+`, `-`, `@`, `\t`, or `\r` will be prepended with a `'` to protected agains csv injection attacks + * Custom formatter for generic object values */ - escape_formulas?: boolean + object?: Cast>; + string?: Cast; + }; + /** + * List of fields, applied when `transform` returns an object + * order matters + * read the transformer documentation for additionnal information + * columns are auto discovered in the first record when the user write objects + * can refer to nested properties of the input JSON + * see the "header" option on how to print columns names on the first line + */ + columns?: ReadonlyArray | PlainObject; + /** + * Set the field delimiter, one character only, defaults to a comma. + */ + delimiter?: string | Buffer; + /** + * Add the value of "options.RecordDelimiter" on the last line, default to true. + */ + eof?: boolean; + /** + * Defaults to the escape read option. + */ + escape?: string | Buffer; + /** + * Display the column names on the first line if the columns option is provided or discovered. + */ + header?: boolean; + /** + * The quote characters, defaults to the ", an empty quote value will preserve the original field. + */ + quote?: string | Buffer | boolean; + /** + * Boolean, default to false, quote all the non-empty fields even if not required. + */ + quoted?: boolean; + + /** + * Boolean, no default, quote empty fields and overrides `quoted_string` on empty strings when defined. + */ + quoted_empty?: boolean; + /** + * String or RegExp, no default, quote all fields matching a regular expression. + */ + quoted_match?: null | string | RegExp | (string | RegExp)[]; + /** + * Boolean, default to false, quote all fields of type string even if not required. + */ + quoted_string?: boolean; + /** + * String used to delimit record rows or a special value + * special values are 'unix', 'mac', 'windows', 'ascii', 'unicode' + * defaults to '\n'. + */ + record_delimiter?: RecordDelimiter; + /** + * Boolean, default to false, if true, fields that begin with `=`, `+`, `-`, `@`, `\t`, or `\r` will be prepended with a `'` to protected agains csv injection attacks + */ + escape_formulas?: boolean; } export class Stringifier extends stream.Transform { - constructor(options: Options) - readonly options: Options + constructor(options: Options); + readonly options: OptionsNormalized; } -declare function stringify(callback?: Callback): Stringifier -declare function stringify(options: Options, callback?: Callback): Stringifier -declare function stringify(input: Input, callback?: Callback): Stringifier -declare function stringify(input: Input, options?: Options, callback?: Callback): Stringifier +declare function stringify(callback?: Callback): Stringifier; +declare function stringify(options: Options, callback?: Callback): Stringifier; +declare function stringify(input: Input, callback?: Callback): Stringifier; +declare function stringify( + input: Input, + options?: Options, + callback?: Callback, +): Stringifier; // export default stringify -export { stringify } +export { stringify }; diff --git a/packages/csv-stringify/dist/cjs/sync.cjs b/packages/csv-stringify/dist/cjs/sync.cjs index 4e6b32529..412a50f69 100644 --- a/packages/csv-stringify/dist/cjs/sync.cjs +++ b/packages/csv-stringify/dist/cjs/sync.cjs @@ -25,6 +25,7 @@ const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv-stringify/dist/cjs/sync.d.cts b/packages/csv-stringify/dist/cjs/sync.d.cts index 98699bd2d..dfc5bffcb 100644 --- a/packages/csv-stringify/dist/cjs/sync.d.cts +++ b/packages/csv-stringify/dist/cjs/sync.d.cts @@ -1,12 +1,17 @@ +import { Input, Options } from "./index.cjs"; -import { Input, Options } from './index.cjs' - -declare function stringify(input: Input, options?: Options): string +declare function stringify(input: Input, options?: Options): string; // export default stringify; export { stringify }; export { - RecordDelimiter, Cast, PlainObject, Input, ColumnOption, CastingContext, - Options -} from './index.cjs'; + RecordDelimiter, + Cast, + PlainObject, + Input, + ColumnOption, + CastingContext, + Options, + OptionsNormalized, +} from "./index.cjs"; diff --git a/packages/csv-stringify/dist/esm/index.d.ts b/packages/csv-stringify/dist/esm/index.d.ts index 618b7ee6b..4ce56ceda 100644 --- a/packages/csv-stringify/dist/esm/index.d.ts +++ b/packages/csv-stringify/dist/esm/index.d.ts @@ -2,124 +2,213 @@ import * as stream from "stream"; -export type Callback = (err: Error | undefined, output: string) => void -export type RecordDelimiter = string | Buffer | 'unix' | 'mac' | 'windows' | 'ascii' | 'unicode' +export type Callback = (err: Error | undefined, output: string) => void; +export type RecordDelimiter = + | string + | Buffer + | "unix" + | "mac" + | "windows" + | "ascii" + | "unicode"; export type CastReturnObject = { value: string } & Pick< - Options, - | 'delimiter' - | 'escape' - | 'quote' - | 'quoted' - | 'quoted_empty' - | 'quoted_string' - | 'quoted_match' - | 'record_delimiter' -> + Options, + | "delimiter" + | "escape" + | "quote" + | "quoted" + | "quoted_empty" + | "quoted_string" + | "quoted_match" + | "record_delimiter" +>; export type Cast = ( - value: T, - context: CastingContext -) => string | CastReturnObject; + value: T, + context: CastingContext, +) => string | null | CastReturnObject; -export type PlainObject = Record -export type Input = any[] +export type PlainObject = Record; +export type Input = any[]; export interface ColumnOption { - key: string - header?: string + key: string; + header?: string; } export interface CastingContext { - readonly column?: number | string; - readonly header: boolean; - readonly index: number; - readonly records: number; + readonly column?: number | string; + readonly header: boolean; + readonly index: number; + readonly records: number; } -export interface Options extends stream.TransformOptions { - /** - * Prepend the byte order mark (BOM) to the output stream. - */ - bom?: boolean - /** - * Key-value object which defines custom cast for certain data types - */ - cast?: { - boolean?: Cast - date?: Cast - number?: Cast - bigint?: Cast - /** - * Custom formatter for generic object values - */ - object?: Cast> - string?: Cast - } - /** - * List of fields, applied when `transform` returns an object - * order matters - * read the transformer documentation for additionnal information - * columns are auto discovered in the first record when the user write objects - * can refer to nested properties of the input JSON - * see the "header" option on how to print columns names on the first line - */ - columns?: readonly string[] | PlainObject | readonly ColumnOption[] - /** - * Set the field delimiter, one character only, defaults to a comma. - */ - delimiter?: string | Buffer - /** - * Add the value of "options.RecordDelimiter" on the last line, default to true. - */ - eof?: boolean - /** - * Defaults to the escape read option. - */ - escape?: string | Buffer - /** - * Display the column names on the first line if the columns option is provided or discovered. - */ - header?: boolean - /** - * The quote characters, defaults to the ", an empty quote value will preserve the original field. - */ - quote?: string | Buffer | boolean - /** - * Boolean, default to false, quote all the non-empty fields even if not required. - */ - quoted?: boolean +export interface OptionsNormalized extends stream.TransformOptions { + /** + * Prepend the byte order mark (BOM) to the output stream. + */ + bom: boolean; + /** + * Key-value object which defines custom cast for certain data types + */ + cast?: { + boolean?: Cast; + date?: Cast; + number?: Cast; + bigint?: Cast; /** - * Boolean, no default, quote empty fields and overrides `quoted_string` on empty strings when defined. - */ - quoted_empty?: boolean - /** - * String or RegExp, no default, quote all fields matching a regular expression. - */ - quoted_match?: string | RegExp | (string | RegExp)[] - /** - * Boolean, default to false, quote all fields of type string even if not required. + * Custom formatter for generic object values */ - quoted_string?: boolean - /** - * String used to delimit record rows or a special value - * special values are 'unix', 'mac', 'windows', 'ascii', 'unicode' - * defaults to '\n'. - */ - record_delimiter?: RecordDelimiter + object?: Cast>; + string?: Cast; + }; + /** + * List of fields, applied when `transform` returns an object + * order matters + * read the transformer documentation for additionnal information + * columns are auto discovered in the first record when the user write objects + * can refer to nested properties of the input JSON + * see the "header" option on how to print columns names on the first line + */ + columns: ReadonlyArray | PlainObject; + /** + * Set the field delimiter, one character only, defaults to a comma. + */ + delimiter: string; + /** + * Add the value of "options.RecordDelimiter" on the last line, default to true. + */ + eof: boolean; + /** + * Defaults to the escape read option. + */ + escape: string; + /** + * Display the column names on the first line if the columns option is provided or discovered. + */ + header: boolean; + /** + * The quote characters, defaults to the ", an empty quote value will preserve the original field. + */ + quote: string; + /** + * Boolean, default to false, quote all the non-empty fields even if not required. + */ + quoted: boolean; + + /** + * Boolean, no default, quote empty fields and overrides `quoted_string` on empty strings when defined. + */ + quoted_empty: boolean; + /** + * String or RegExp, no default, quote all fields matching a regular expression. + */ + quoted_match: null | (string | RegExp)[]; + /** + * Boolean, default to false, quote all fields of type string even if not required. + */ + quoted_string: boolean; + /** + * String used to delimit record rows or a special value + * special values are 'unix', 'mac', 'windows', 'ascii', 'unicode' + * defaults to '\n'. + */ + record_delimiter: RecordDelimiter; + /** + * Boolean, default to false, if true, fields that begin with `=`, `+`, `-`, `@`, `\t`, or `\r` will be prepended with a `'` to protected agains csv injection attacks + */ + escape_formulas: boolean; +} + +export interface Options extends stream.TransformOptions { + /** + * Prepend the byte order mark (BOM) to the output stream. + */ + bom?: boolean; + /** + * Key-value object which defines custom cast for certain data types + */ + cast?: { + boolean?: Cast; + date?: Cast; + number?: Cast; + bigint?: Cast; /** - * Boolean, default to false, if true, fields that begin with `=`, `+`, `-`, `@`, `\t`, or `\r` will be prepended with a `'` to protected agains csv injection attacks + * Custom formatter for generic object values */ - escape_formulas?: boolean + object?: Cast>; + string?: Cast; + }; + /** + * List of fields, applied when `transform` returns an object + * order matters + * read the transformer documentation for additionnal information + * columns are auto discovered in the first record when the user write objects + * can refer to nested properties of the input JSON + * see the "header" option on how to print columns names on the first line + */ + columns?: ReadonlyArray | PlainObject; + /** + * Set the field delimiter, one character only, defaults to a comma. + */ + delimiter?: string | Buffer; + /** + * Add the value of "options.RecordDelimiter" on the last line, default to true. + */ + eof?: boolean; + /** + * Defaults to the escape read option. + */ + escape?: string | Buffer; + /** + * Display the column names on the first line if the columns option is provided or discovered. + */ + header?: boolean; + /** + * The quote characters, defaults to the ", an empty quote value will preserve the original field. + */ + quote?: string | Buffer | boolean; + /** + * Boolean, default to false, quote all the non-empty fields even if not required. + */ + quoted?: boolean; + + /** + * Boolean, no default, quote empty fields and overrides `quoted_string` on empty strings when defined. + */ + quoted_empty?: boolean; + /** + * String or RegExp, no default, quote all fields matching a regular expression. + */ + quoted_match?: null | string | RegExp | (string | RegExp)[]; + /** + * Boolean, default to false, quote all fields of type string even if not required. + */ + quoted_string?: boolean; + /** + * String used to delimit record rows or a special value + * special values are 'unix', 'mac', 'windows', 'ascii', 'unicode' + * defaults to '\n'. + */ + record_delimiter?: RecordDelimiter; + /** + * Boolean, default to false, if true, fields that begin with `=`, `+`, `-`, `@`, `\t`, or `\r` will be prepended with a `'` to protected agains csv injection attacks + */ + escape_formulas?: boolean; } export class Stringifier extends stream.Transform { - constructor(options: Options) - readonly options: Options + constructor(options: Options); + readonly options: OptionsNormalized; } -declare function stringify(callback?: Callback): Stringifier -declare function stringify(options: Options, callback?: Callback): Stringifier -declare function stringify(input: Input, callback?: Callback): Stringifier -declare function stringify(input: Input, options?: Options, callback?: Callback): Stringifier +declare function stringify(callback?: Callback): Stringifier; +declare function stringify(options: Options, callback?: Callback): Stringifier; +declare function stringify(input: Input, callback?: Callback): Stringifier; +declare function stringify( + input: Input, + options?: Options, + callback?: Callback, +): Stringifier; // export default stringify -export { stringify } +export { stringify }; diff --git a/packages/csv-stringify/dist/esm/index.js b/packages/csv-stringify/dist/esm/index.js index 47013ff04..db36122b1 100644 --- a/packages/csv-stringify/dist/esm/index.js +++ b/packages/csv-stringify/dist/esm/index.js @@ -28,7 +28,9 @@ EventEmitter.init = function() { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -1297,8 +1299,8 @@ function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -2057,7 +2059,7 @@ Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, no Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -2067,7 +2069,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2080,7 +2082,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -2093,7 +2095,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2108,7 +2110,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2569,94 +2571,19 @@ function Item(fun, array) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; -var title = 'browser'; -var platform = 'browser'; -var browser = true; var env = {}; -var argv = []; -var version = ''; // empty string to avoid regexp issues -var versions = {}; -var release = {}; -var config = {}; - -function noop() {} - -var on = noop; -var addListener = noop; -var once = noop; -var off = noop; -var removeListener = noop; -var removeAllListeners = noop; -var emit = noop; - -function binding(name) { - throw new Error('process.binding is not supported'); -} - -function cwd () { return '/' } -function chdir (dir) { - throw new Error('process.chdir is not supported'); -}function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; -var performanceNow = - performance.now || +performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; -// generate timestamp or delta -// see http://nodejs.org/api/process.html#process_process_hrtime -function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] -} - -var startTime = new Date(); -function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; -} - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime -}; + env: env}; var inherits; if (typeof Object.create === 'function'){ @@ -5174,6 +5101,7 @@ const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv-stringify/dist/esm/sync.d.ts b/packages/csv-stringify/dist/esm/sync.d.ts index 3814c21db..9e6140e96 100644 --- a/packages/csv-stringify/dist/esm/sync.d.ts +++ b/packages/csv-stringify/dist/esm/sync.d.ts @@ -1,12 +1,17 @@ +import { Input, Options } from "./index.js"; -import { Input, Options } from './index.js' - -declare function stringify(input: Input, options?: Options): string +declare function stringify(input: Input, options?: Options): string; // export default stringify; export { stringify }; export { - RecordDelimiter, Cast, PlainObject, Input, ColumnOption, CastingContext, - Options -} from './index.js'; + RecordDelimiter, + Cast, + PlainObject, + Input, + ColumnOption, + CastingContext, + Options, + OptionsNormalized, +} from "./index.js"; diff --git a/packages/csv-stringify/dist/esm/sync.js b/packages/csv-stringify/dist/esm/sync.js index 3348f7aee..58ebc60e2 100644 --- a/packages/csv-stringify/dist/esm/sync.js +++ b/packages/csv-stringify/dist/esm/sync.js @@ -831,8 +831,8 @@ function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1591,7 +1591,7 @@ Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, no Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1601,7 +1601,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1614,7 +1614,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1627,7 +1627,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1642,7 +1642,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -1995,6 +1995,7 @@ const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv-stringify/dist/iife/index.js b/packages/csv-stringify/dist/iife/index.js index 4b540a2da..fb5febc2a 100644 --- a/packages/csv-stringify/dist/iife/index.js +++ b/packages/csv-stringify/dist/iife/index.js @@ -31,7 +31,9 @@ var csv_stringify = (function (exports) { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -1300,8 +1302,8 @@ var csv_stringify = (function (exports) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -2060,7 +2062,7 @@ var csv_stringify = (function (exports) { Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -2070,7 +2072,7 @@ var csv_stringify = (function (exports) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2083,7 +2085,7 @@ var csv_stringify = (function (exports) { Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -2096,7 +2098,7 @@ var csv_stringify = (function (exports) { Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2111,7 +2113,7 @@ var csv_stringify = (function (exports) { Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2572,94 +2574,19 @@ var csv_stringify = (function (exports) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ @@ -5177,6 +5104,7 @@ var csv_stringify = (function (exports) { const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv-stringify/dist/iife/sync.js b/packages/csv-stringify/dist/iife/sync.js index 2473d394f..e4be39a47 100644 --- a/packages/csv-stringify/dist/iife/sync.js +++ b/packages/csv-stringify/dist/iife/sync.js @@ -834,8 +834,8 @@ var csv_stringify_sync = (function (exports) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1594,7 +1594,7 @@ var csv_stringify_sync = (function (exports) { Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1604,7 +1604,7 @@ var csv_stringify_sync = (function (exports) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1617,7 +1617,7 @@ var csv_stringify_sync = (function (exports) { Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1630,7 +1630,7 @@ var csv_stringify_sync = (function (exports) { Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1645,7 +1645,7 @@ var csv_stringify_sync = (function (exports) { Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -1998,6 +1998,7 @@ var csv_stringify_sync = (function (exports) { const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv-stringify/dist/umd/index.js b/packages/csv-stringify/dist/umd/index.js index b27b478d2..3321216a3 100644 --- a/packages/csv-stringify/dist/umd/index.js +++ b/packages/csv-stringify/dist/umd/index.js @@ -34,7 +34,9 @@ this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -1303,8 +1305,8 @@ byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -2063,7 +2065,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -2073,7 +2075,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2086,7 +2088,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -2099,7 +2101,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2114,7 +2116,7 @@ Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2575,94 +2577,19 @@ Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ @@ -5180,6 +5107,7 @@ const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv-stringify/dist/umd/sync.js b/packages/csv-stringify/dist/umd/sync.js index cdb9332a9..ab1911b0b 100644 --- a/packages/csv-stringify/dist/umd/sync.js +++ b/packages/csv-stringify/dist/umd/sync.js @@ -837,8 +837,8 @@ byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1597,7 +1597,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1607,7 +1607,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1620,7 +1620,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1633,7 +1633,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1648,7 +1648,7 @@ Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2001,6 +2001,7 @@ const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv-stringify/lib/index.d.ts b/packages/csv-stringify/lib/index.d.ts index 618b7ee6b..4ce56ceda 100644 --- a/packages/csv-stringify/lib/index.d.ts +++ b/packages/csv-stringify/lib/index.d.ts @@ -2,124 +2,213 @@ import * as stream from "stream"; -export type Callback = (err: Error | undefined, output: string) => void -export type RecordDelimiter = string | Buffer | 'unix' | 'mac' | 'windows' | 'ascii' | 'unicode' +export type Callback = (err: Error | undefined, output: string) => void; +export type RecordDelimiter = + | string + | Buffer + | "unix" + | "mac" + | "windows" + | "ascii" + | "unicode"; export type CastReturnObject = { value: string } & Pick< - Options, - | 'delimiter' - | 'escape' - | 'quote' - | 'quoted' - | 'quoted_empty' - | 'quoted_string' - | 'quoted_match' - | 'record_delimiter' -> + Options, + | "delimiter" + | "escape" + | "quote" + | "quoted" + | "quoted_empty" + | "quoted_string" + | "quoted_match" + | "record_delimiter" +>; export type Cast = ( - value: T, - context: CastingContext -) => string | CastReturnObject; + value: T, + context: CastingContext, +) => string | null | CastReturnObject; -export type PlainObject = Record -export type Input = any[] +export type PlainObject = Record; +export type Input = any[]; export interface ColumnOption { - key: string - header?: string + key: string; + header?: string; } export interface CastingContext { - readonly column?: number | string; - readonly header: boolean; - readonly index: number; - readonly records: number; + readonly column?: number | string; + readonly header: boolean; + readonly index: number; + readonly records: number; } -export interface Options extends stream.TransformOptions { - /** - * Prepend the byte order mark (BOM) to the output stream. - */ - bom?: boolean - /** - * Key-value object which defines custom cast for certain data types - */ - cast?: { - boolean?: Cast - date?: Cast - number?: Cast - bigint?: Cast - /** - * Custom formatter for generic object values - */ - object?: Cast> - string?: Cast - } - /** - * List of fields, applied when `transform` returns an object - * order matters - * read the transformer documentation for additionnal information - * columns are auto discovered in the first record when the user write objects - * can refer to nested properties of the input JSON - * see the "header" option on how to print columns names on the first line - */ - columns?: readonly string[] | PlainObject | readonly ColumnOption[] - /** - * Set the field delimiter, one character only, defaults to a comma. - */ - delimiter?: string | Buffer - /** - * Add the value of "options.RecordDelimiter" on the last line, default to true. - */ - eof?: boolean - /** - * Defaults to the escape read option. - */ - escape?: string | Buffer - /** - * Display the column names on the first line if the columns option is provided or discovered. - */ - header?: boolean - /** - * The quote characters, defaults to the ", an empty quote value will preserve the original field. - */ - quote?: string | Buffer | boolean - /** - * Boolean, default to false, quote all the non-empty fields even if not required. - */ - quoted?: boolean +export interface OptionsNormalized extends stream.TransformOptions { + /** + * Prepend the byte order mark (BOM) to the output stream. + */ + bom: boolean; + /** + * Key-value object which defines custom cast for certain data types + */ + cast?: { + boolean?: Cast; + date?: Cast; + number?: Cast; + bigint?: Cast; /** - * Boolean, no default, quote empty fields and overrides `quoted_string` on empty strings when defined. - */ - quoted_empty?: boolean - /** - * String or RegExp, no default, quote all fields matching a regular expression. - */ - quoted_match?: string | RegExp | (string | RegExp)[] - /** - * Boolean, default to false, quote all fields of type string even if not required. + * Custom formatter for generic object values */ - quoted_string?: boolean - /** - * String used to delimit record rows or a special value - * special values are 'unix', 'mac', 'windows', 'ascii', 'unicode' - * defaults to '\n'. - */ - record_delimiter?: RecordDelimiter + object?: Cast>; + string?: Cast; + }; + /** + * List of fields, applied when `transform` returns an object + * order matters + * read the transformer documentation for additionnal information + * columns are auto discovered in the first record when the user write objects + * can refer to nested properties of the input JSON + * see the "header" option on how to print columns names on the first line + */ + columns: ReadonlyArray | PlainObject; + /** + * Set the field delimiter, one character only, defaults to a comma. + */ + delimiter: string; + /** + * Add the value of "options.RecordDelimiter" on the last line, default to true. + */ + eof: boolean; + /** + * Defaults to the escape read option. + */ + escape: string; + /** + * Display the column names on the first line if the columns option is provided or discovered. + */ + header: boolean; + /** + * The quote characters, defaults to the ", an empty quote value will preserve the original field. + */ + quote: string; + /** + * Boolean, default to false, quote all the non-empty fields even if not required. + */ + quoted: boolean; + + /** + * Boolean, no default, quote empty fields and overrides `quoted_string` on empty strings when defined. + */ + quoted_empty: boolean; + /** + * String or RegExp, no default, quote all fields matching a regular expression. + */ + quoted_match: null | (string | RegExp)[]; + /** + * Boolean, default to false, quote all fields of type string even if not required. + */ + quoted_string: boolean; + /** + * String used to delimit record rows or a special value + * special values are 'unix', 'mac', 'windows', 'ascii', 'unicode' + * defaults to '\n'. + */ + record_delimiter: RecordDelimiter; + /** + * Boolean, default to false, if true, fields that begin with `=`, `+`, `-`, `@`, `\t`, or `\r` will be prepended with a `'` to protected agains csv injection attacks + */ + escape_formulas: boolean; +} + +export interface Options extends stream.TransformOptions { + /** + * Prepend the byte order mark (BOM) to the output stream. + */ + bom?: boolean; + /** + * Key-value object which defines custom cast for certain data types + */ + cast?: { + boolean?: Cast; + date?: Cast; + number?: Cast; + bigint?: Cast; /** - * Boolean, default to false, if true, fields that begin with `=`, `+`, `-`, `@`, `\t`, or `\r` will be prepended with a `'` to protected agains csv injection attacks + * Custom formatter for generic object values */ - escape_formulas?: boolean + object?: Cast>; + string?: Cast; + }; + /** + * List of fields, applied when `transform` returns an object + * order matters + * read the transformer documentation for additionnal information + * columns are auto discovered in the first record when the user write objects + * can refer to nested properties of the input JSON + * see the "header" option on how to print columns names on the first line + */ + columns?: ReadonlyArray | PlainObject; + /** + * Set the field delimiter, one character only, defaults to a comma. + */ + delimiter?: string | Buffer; + /** + * Add the value of "options.RecordDelimiter" on the last line, default to true. + */ + eof?: boolean; + /** + * Defaults to the escape read option. + */ + escape?: string | Buffer; + /** + * Display the column names on the first line if the columns option is provided or discovered. + */ + header?: boolean; + /** + * The quote characters, defaults to the ", an empty quote value will preserve the original field. + */ + quote?: string | Buffer | boolean; + /** + * Boolean, default to false, quote all the non-empty fields even if not required. + */ + quoted?: boolean; + + /** + * Boolean, no default, quote empty fields and overrides `quoted_string` on empty strings when defined. + */ + quoted_empty?: boolean; + /** + * String or RegExp, no default, quote all fields matching a regular expression. + */ + quoted_match?: null | string | RegExp | (string | RegExp)[]; + /** + * Boolean, default to false, quote all fields of type string even if not required. + */ + quoted_string?: boolean; + /** + * String used to delimit record rows or a special value + * special values are 'unix', 'mac', 'windows', 'ascii', 'unicode' + * defaults to '\n'. + */ + record_delimiter?: RecordDelimiter; + /** + * Boolean, default to false, if true, fields that begin with `=`, `+`, `-`, `@`, `\t`, or `\r` will be prepended with a `'` to protected agains csv injection attacks + */ + escape_formulas?: boolean; } export class Stringifier extends stream.Transform { - constructor(options: Options) - readonly options: Options + constructor(options: Options); + readonly options: OptionsNormalized; } -declare function stringify(callback?: Callback): Stringifier -declare function stringify(options: Options, callback?: Callback): Stringifier -declare function stringify(input: Input, callback?: Callback): Stringifier -declare function stringify(input: Input, options?: Options, callback?: Callback): Stringifier +declare function stringify(callback?: Callback): Stringifier; +declare function stringify(options: Options, callback?: Callback): Stringifier; +declare function stringify(input: Input, callback?: Callback): Stringifier; +declare function stringify( + input: Input, + options?: Options, + callback?: Callback, +): Stringifier; // export default stringify -export { stringify } +export { stringify }; diff --git a/packages/csv-stringify/lib/sync.d.ts b/packages/csv-stringify/lib/sync.d.ts index 3814c21db..9e6140e96 100644 --- a/packages/csv-stringify/lib/sync.d.ts +++ b/packages/csv-stringify/lib/sync.d.ts @@ -1,12 +1,17 @@ +import { Input, Options } from "./index.js"; -import { Input, Options } from './index.js' - -declare function stringify(input: Input, options?: Options): string +declare function stringify(input: Input, options?: Options): string; // export default stringify; export { stringify }; export { - RecordDelimiter, Cast, PlainObject, Input, ColumnOption, CastingContext, - Options -} from './index.js'; + RecordDelimiter, + Cast, + PlainObject, + Input, + ColumnOption, + CastingContext, + Options, + OptionsNormalized, +} from "./index.js"; diff --git a/packages/csv-stringify/lib/utils/get.js b/packages/csv-stringify/lib/utils/get.js index f59132257..9b46ed434 100644 --- a/packages/csv-stringify/lib/utils/get.js +++ b/packages/csv-stringify/lib/utils/get.js @@ -23,7 +23,7 @@ const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; const reIsPlainProp = /^\w*$/; const getTag = function (value) { - if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv-stringify/package.json b/packages/csv-stringify/package.json index a14a4e3b9..0fb0b3364 100644 --- a/packages/csv-stringify/package.json +++ b/packages/csv-stringify/package.json @@ -1,5 +1,5 @@ { - "version": "6.5.2", + "version": "6.6.0", "name": "csv-stringify", "description": "CSV stringifier implementing the Node.js `stream.Transform` API", "keywords": [ @@ -11,26 +11,21 @@ ], "author": "David Worms (https://www.adaltas.com)", "devDependencies": { - "@eslint/js": "^9.15.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@types/mocha": "^10.0.9", - "@types/node": "^22.9.1", - "coffeescript": "~2.7.0", - "csv-generate": "^4.4.2", + "@rollup/plugin-node-resolve": "^16.0.1", + "@types/mocha": "^10.0.10", + "@types/node": "^22.15.30", + "csv-generate": "^4.5.0", + "dedent": "^1.6.0", "each": "^2.7.2", - "eslint": "^9.15.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-mocha": "^10.5.0", - "eslint-plugin-prettier": "^5.2.1", - "express": "^4.21.1", - "mocha": "~10.8.2", - "prettier": "^3.3.3", - "rollup": "^4.27.3", + "express": "^5.1.0", + "mocha": "~11.5.0", + "prettier": "^3.5.3", + "rollup": "^4.41.1", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "should": "~13.2.3", "ts-node": "^10.9.2", - "typescript": "^5.6.3" + "typescript": "^5.8.3" }, "exports": { ".": { @@ -71,19 +66,12 @@ "main": "./dist/cjs/index.cjs", "mocha": { "inline-diffs": true, - "loader": "./test/loaders/all.js", + "loader": "ts-node/esm", "recursive": true, "reporter": "spec", - "require": [ - "should" - ], "throw-deprecation": false, "timeout": 40000 }, - "lint-staged": { - "*.js": "npm run lint:fix", - "*.md": "prettier -w" - }, "repository": { "type": "git", "url": "https://github.com/adaltas/node-csv.git", @@ -98,8 +86,8 @@ "lint:fix": "eslint --fix", "lint:ts": "tsc --noEmit true", "preversion": "npm run build && git add dist", - "test": "mocha 'test/**/*.{coffee,ts}'", - "test:legacy": "mocha --ignore test/api.callback.coffee --ignore test/api.web_stream.coffee --loader=./test/loaders/legacy/all.js 'test/**/*.{coffee,ts}'" + "test": "mocha 'test/**/*.{js,ts}'", + "test:legacy": "mocha --ignore test/api.callback.js --ignore test/api.web_stream.js 'test/**/*.{js,ts}'" }, "type": "module", "types": "dist/esm/index.d.ts", diff --git a/packages/csv-stringify/samples/browser/index.html b/packages/csv-stringify/samples/browser/index.html deleted file mode 100644 index d80a6c182..000000000 --- a/packages/csv-stringify/samples/browser/index.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - Page Title - - - - -
-

CSV stringify demo

- - - -
- -
- - diff --git a/packages/csv-stringify/samples/browser/index.js b/packages/csv-stringify/samples/browser/index.js deleted file mode 100644 index 72c52eb7f..000000000 --- a/packages/csv-stringify/samples/browser/index.js +++ /dev/null @@ -1,10 +0,0 @@ -const express = require("express"); -const app = express(); -const port = 3000; - -app.use(express.static(__dirname)); -app.use("/lib", express.static(`${__dirname}/../../lib/browser`)); - -app.listen(port, () => { - console.log(`Example app listening at http://localhost:${port}`); -}); diff --git a/packages/csv-stringify/test/api.callback.coffee b/packages/csv-stringify/test/api.callback.coffee deleted file mode 100644 index e5e6a014b..000000000 --- a/packages/csv-stringify/test/api.callback.coffee +++ /dev/null @@ -1,43 +0,0 @@ - -import fs from 'fs' -import { generate } from 'csv-generate' -import { stringify } from '../lib/index.js' - -describe 'api.callback', -> - - it '2 args: data, callback', (next) -> - data = '' - stringifier = stringify [ - ['field_1','field_2'], ['value 1','value 2'] - ], (err, data) -> - data.should.eql 'field_1,field_2\nvalue 1,value 2\n' - next() - - it '2 args: options, callback', (next) -> - data = '' - stringifier = stringify eof: false, (err, data) -> - data.should.eql 'field_1,field_2\nvalue 1,value 2' - next() - stringifier.write ['field_1','field_2'] - stringifier.write ['value 1','value 2'] - stringifier.end() - - it '3 args: data, options, callback', (next) -> - data = '' - stringifier = stringify [ - ['field_1','field_2'], ['value 1','value 2'] - ], eof: false, (err, data) -> - data.should.eql 'field_1,field_2\nvalue 1,value 2' - next() - - it 'catch error in end handler, see #386', (next) -> - input = - Array.from( length: 200000 ).map -> - Array.from( length: 100 ).map -> - 'ABCDEFGHIJKLMNOPQRSTUVXYZ0123456789' - stringify input, (err, res) -> - err.should.match - code: 'ERR_STRING_TOO_LONG' - message: 'Cannot create a string longer than 0x1fffffe8 characters' - next() - \ No newline at end of file diff --git a/packages/csv-stringify/test/api.callback.js b/packages/csv-stringify/test/api.callback.js new file mode 100644 index 000000000..b6a8af32c --- /dev/null +++ b/packages/csv-stringify/test/api.callback.js @@ -0,0 +1,56 @@ +import "should"; +import { stringify } from "../lib/index.js"; + +describe("api.callback", function () { + it("2 args: data, callback", function (next) { + stringify( + [ + ["field_1", "field_2"], + ["value 1", "value 2"], + ], + (err, data) => { + data.should.eql("field_1,field_2\nvalue 1,value 2\n"); + next(); + }, + ); + }); + + it("2 args: options, callback", function (next) { + const stringifier = stringify({ eof: false }, (err, data) => { + data.should.eql("field_1,field_2\nvalue 1,value 2"); + next(); + }); + stringifier.write(["field_1", "field_2"]); + stringifier.write(["value 1", "value 2"]); + stringifier.end(); + }); + + it("3 args: data, options, callback", function (next) { + stringify( + [ + ["field_1", "field_2"], + ["value 1", "value 2"], + ], + { eof: false }, + (err, data) => { + data.should.eql("field_1,field_2\nvalue 1,value 2"); + next(); + }, + ); + }); + + it("catch error in end handler, see #386", function (next) { + const input = Array.from({ length: 200000 }).map(() => + Array.from({ length: 100 }).map( + () => "ABCDEFGHIJKLMNOPQRSTUVXYZ0123456789", + ), + ); + stringify(input, (err) => { + err.should.match({ + code: "ERR_STRING_TOO_LONG", + message: "Cannot create a string longer than 0x1fffffe8 characters", + }); + next(); + }); + }); +}); diff --git a/packages/csv-stringify/test/api.coffee b/packages/csv-stringify/test/api.coffee deleted file mode 100644 index b0a036a4d..000000000 --- a/packages/csv-stringify/test/api.coffee +++ /dev/null @@ -1,60 +0,0 @@ - -import fs from 'fs' -import { generate } from 'csv-generate' -import { stringify } from '../lib/index.js' - -describe 'API', -> - - it '0 arg: write input and stream output', (next) -> - data = '' - stringifier = stringify() - stringifier.on 'readable', -> - data += d while d = stringifier.read() - stringifier.on 'err', (err) -> - next err - stringifier.on 'finish', -> - data.should.eql 'field_1,field_2\nvalue 1,value 2\n' - next() - stringifier.write ['field_1','field_2'] - stringifier.write ['value 1','value 2'] - stringifier.end() - - it '1 arg: option; write input and stream output', (next) -> - data = '' - generator = generate length: 2, objectMode: true, seed: 1, columns: 2 - stringifier = stringify eof: false - stringifier.on 'readable', -> - data += d while d = stringifier.read() - generator.on 'error', next - generator.on 'end', (err) -> - stringifier.end() - generator.on 'readable', -> - stringifier.write row while row = generator.read() - stringifier.on 'finish', -> - data.should.eql """ - OMH,ONKCHhJmjadoA - D,GeACHiN - """ - next() - - it '1 arg: data and stream output', (next) -> - data = '' - stringifier = stringify [ - ['field_1','field_2'], ['value 1','value 2'] - ] - stringifier.on 'readable', -> - data += d while d = stringifier.read() - stringifier.on 'finish', -> - data.should.eql 'field_1,field_2\nvalue 1,value 2\n' - next() - - it '2 args: data, option and stream output', (next) -> - data = '' - stringifier = stringify [ - ['field_1','field_2'], ['value 1','value 2'] - ], eof: false - stringifier.on 'readable', -> - data += d while d = stringifier.read() - stringifier.on 'finish', -> - data.should.eql 'field_1,field_2\nvalue 1,value 2' - next() diff --git a/packages/csv-stringify/test/api.js b/packages/csv-stringify/test/api.js new file mode 100644 index 000000000..a3de3d268 --- /dev/null +++ b/packages/csv-stringify/test/api.js @@ -0,0 +1,96 @@ +import "should"; +import { generate } from "csv-generate"; +import { stringify } from "../lib/index.js"; + +describe("API", function () { + it("0 arg: write input and stream output", function (next) { + let data = ""; + const stringifier = stringify(); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + stringifier.on("err", (err) => { + next(err); + }); + stringifier.on("finish", () => { + data.should.eql("field_1,field_2\nvalue 1,value 2\n"); + next(); + }); + stringifier.write(["field_1", "field_2"]); + stringifier.write(["value 1", "value 2"]); + stringifier.end(); + }); + + it("1 arg: option; write input and stream output", function (next) { + let data = ""; + const generator = generate({ + length: 2, + objectMode: true, + seed: 1, + columns: 2, + }); + const stringifier = stringify({ eof: false }); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + generator.on("error", next); + generator.on("end", () => { + stringifier.end(); + }); + generator.on("readable", () => { + let row; + while ((row = generator.read())) { + stringifier.write(row); + } + }); + stringifier.on("finish", () => { + data.should.eql("OMH,ONKCHhJmjadoA\nD,GeACHiN"); + next(); + }); + }); + + it("1 arg: data and stream output", function (next) { + let data = ""; + const stringifier = stringify([ + ["field_1", "field_2"], + ["value 1", "value 2"], + ]); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + stringifier.on("finish", () => { + data.should.eql("field_1,field_2\nvalue 1,value 2\n"); + next(); + }); + }); + + it("2 args: data, option and stream output", function (next) { + let data = ""; + const stringifier = stringify( + [ + ["field_1", "field_2"], + ["value 1", "value 2"], + ], + { eof: false }, + ); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + stringifier.on("finish", () => { + data.should.eql("field_1,field_2\nvalue 1,value 2"); + next(); + }); + }); +}); diff --git a/packages/csv-stringify/test/api.pipe.coffee b/packages/csv-stringify/test/api.pipe.coffee deleted file mode 100644 index 60a27f954..000000000 --- a/packages/csv-stringify/test/api.pipe.coffee +++ /dev/null @@ -1,47 +0,0 @@ - -import fs from 'fs' -import { generate } from 'csv-generate' -import { stringify } from '../lib/index.js' - -describe 'API pipe', -> - - it 'pipe from source to destination', (next) -> - data = '' - generator = generate length: 2, objectMode: true, seed: 1, columns: 2 - stringifier = stringify eof: false - ws = fs.createWriteStream '/tmp/large.out' - generator.pipe(stringifier).pipe(ws).on 'finish', -> - fs.readFile '/tmp/large.out', 'ascii', (err, data) -> - data.should.eql """ - OMH,ONKCHhJmjadoA - D,GeACHiN - """ - fs.unlink '/tmp/large.out', next - - it 'pipe to destination', (next) -> - data = '' - generate length: 1000, objectMode: true, seed: 1, columns: 2, (err, data) -> - stringifier = stringify eof: false - ws = fs.createWriteStream '/tmp/large.out' - stringifier.pipe ws - for row in data - stringifier.write row - stringifier.end() - ws.on 'finish', -> - fs.readFile '/tmp/large.out', 'ascii', (err, data) -> - data.split('\n').length.should.eql 1000 unless err - next err - - it 'pipe from source', (next) -> - data = '' - generator = generate length: 2, objectMode: true, seed: 1, columns: 2 - stringifier = generator.pipe stringify eof: false - stringifier.on 'readable', -> - while(d = stringifier.read()) - data += d - stringifier.on 'finish', -> - data.should.eql """ - OMH,ONKCHhJmjadoA - D,GeACHiN - """ - next() diff --git a/packages/csv-stringify/test/api.pipe.js b/packages/csv-stringify/test/api.pipe.js new file mode 100644 index 000000000..5199f7e2d --- /dev/null +++ b/packages/csv-stringify/test/api.pipe.js @@ -0,0 +1,70 @@ +import "should"; +import fs from "fs"; +import { generate } from "csv-generate"; +import { stringify } from "../lib/index.js"; + +describe("API pipe", function () { + it("pipe from source to destination", function (next) { + const generator = generate({ + length: 2, + objectMode: true, + seed: 1, + columns: 2, + }); + const stringifier = stringify({ eof: false }); + const ws = fs.createWriteStream("/tmp/large.out"); + generator + .pipe(stringifier) + .pipe(ws) + .on("finish", () => { + fs.readFile("/tmp/large.out", "ascii", (err, data) => { + data.should.eql("OMH,ONKCHhJmjadoA\nD,GeACHiN"); + fs.unlink("/tmp/large.out", next); + }); + }); + }); + + it("pipe to destination", function (next) { + generate( + { length: 1000, objectMode: true, seed: 1, columns: 2 }, + (err, data) => { + const stringifier = stringify({ eof: false }); + const ws = fs.createWriteStream("/tmp/large.out"); + stringifier.pipe(ws); + for (const row of data) { + stringifier.write(row); + } + stringifier.end(); + ws.on("finish", () => { + fs.readFile("/tmp/large.out", "ascii", (err, data) => { + if (!err) { + data.split("\n").length.should.eql(1000); + } + next(err); + }); + }); + }, + ); + }); + + it("pipe from source", function (next) { + let data = ""; + const generator = generate({ + length: 2, + objectMode: true, + seed: 1, + columns: 2, + }); + const stringifier = generator.pipe(stringify({ eof: false })); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + stringifier.on("finish", () => { + data.should.eql("OMH,ONKCHhJmjadoA\nD,GeACHiN"); + next(); + }); + }); +}); diff --git a/packages/csv-stringify/test/api.sync.coffee b/packages/csv-stringify/test/api.sync.coffee deleted file mode 100644 index ab7e861ef..000000000 --- a/packages/csv-stringify/test/api.sync.coffee +++ /dev/null @@ -1,21 +0,0 @@ - -import { stringify } from '../lib/sync.js' - -describe 'sync', -> - - it 'work on object', -> - data = stringify [ {a: '1', b: '2'}, {a: '3', b: '4'}] - data.should.eql "1,2\n3,4\n" - - it 'work on array', -> - data = stringify [ ['1', '2'], ['3', '4']] - data.should.eql "1,2\n3,4\n" - - it 'pass options', -> - data = stringify [ {a: '1', b: '2'}, {a: '3', b: '4'}], quoted: true, eof: false - data.should.eql '"1","2"\n"3","4"' - - it 'catch error', -> - (-> - stringify([ 1, {a: '3', b: '4'}]) - ).should.throw 'Invalid Record: expect an array or an object, got 1' diff --git a/packages/csv-stringify/test/api.sync.js b/packages/csv-stringify/test/api.sync.js new file mode 100644 index 000000000..2a97b1206 --- /dev/null +++ b/packages/csv-stringify/test/api.sync.js @@ -0,0 +1,37 @@ +import "should"; +import { stringify } from "../lib/sync.js"; + +describe("sync", function () { + it("work on object", function () { + const data = stringify([ + { a: "1", b: "2" }, + { a: "3", b: "4" }, + ]); + data.should.eql("1,2\n3,4\n"); + }); + + it("work on array", function () { + const data = stringify([ + ["1", "2"], + ["3", "4"], + ]); + data.should.eql("1,2\n3,4\n"); + }); + + it("pass options", function () { + const data = stringify( + [ + { a: "1", b: "2" }, + { a: "3", b: "4" }, + ], + { quoted: true, eof: false }, + ); + data.should.eql('"1","2"\n"3","4"'); + }); + + it("catch error", function () { + (() => { + stringify([1, { a: "3", b: "4" }]); + }).should.throw("Invalid Record: expect an array or an object, got 1"); + }); +}); diff --git a/packages/csv-stringify/test/api.types.sync.ts b/packages/csv-stringify/test/api.types.sync.ts index 07dc3c6b3..73ecbf2d5 100644 --- a/packages/csv-stringify/test/api.types.sync.ts +++ b/packages/csv-stringify/test/api.types.sync.ts @@ -1,53 +1,56 @@ - -import 'should' +import "should"; import { stringify, - RecordDelimiter, Cast, PlainObject, Input, - ColumnOption, CastingContext, -Options -} from '../lib/sync.js' - -describe('API Types', () => { + RecordDelimiter, + Cast, + PlainObject, + Input, + ColumnOption, + CastingContext, + Options, +} from "../lib/sync.js"; - it('stringify return string', () => { - const input: Input = [[1,2,3]]; - const stringifier: string = stringify(input) - stringifier - }) +describe("API Types", function () { + it("stringify return string", function () { + const input: Input = [[1, 2, 3]]; + const stringifier: string = stringify(input); + stringifier; + }); - it('Options', () => { + it("Options", function () { (options: Options) => { - const rd: RecordDelimiter | undefined = options.record_delimiter - const cast = options.cast - const castBoolean : Cast | undefined = cast?.boolean - const columns: readonly string[] | PlainObject | readonly ColumnOption[] | undefined = options.columns - return [ - rd, castBoolean, columns - ] - } - }) - - it('CastingContext', () => { + const rd: RecordDelimiter | undefined = options.record_delimiter; + const cast = options.cast; + const castBoolean: Cast | undefined = cast?.boolean; + const columns: + | ReadonlyArray + | PlainObject + | undefined = options.columns; + return [rd, castBoolean, columns]; + }; + }); + + it("CastingContext", function () { const options: Options = { cast: { boolean: (value: boolean, context: CastingContext) => { - return `${value} ${context.index}` - } - } - } - return options - }) + return `${value} ${context.index}`; + }, + }, + }; + return options; + }); - it('allows cast to return an object', () => { + it("allows cast to return an object", function () { const options: Options = { cast: { boolean: (value: boolean) => ({ value: value.toString(), - delimiter: ';', - quote: false - }) - } - } - }) - -}) + delimiter: ";", + quote: false, + }), + }, + }; + options; + }); +}); diff --git a/packages/csv-stringify/test/api.types.ts b/packages/csv-stringify/test/api.types.ts index 9907e65ef..3e18e1d5e 100644 --- a/packages/csv-stringify/test/api.types.ts +++ b/packages/csv-stringify/test/api.types.ts @@ -1,166 +1,174 @@ +import "should"; +import { + stringify, + CastingContext, + Options, + Stringifier, +} from "../lib/index.js"; -import 'should' -import { stringify, CastingContext, Options, Stringifier } from '../lib/index.js' -import { stringify as stringifySync } from '../lib/index.js' - -describe('API Types', () => { - - describe('Parser', () => { - - it('Expose options', () => { - const stringifier: Stringifier = stringify() - const options: Options = stringifier.options - const keys: any = Object.keys(options) - keys.sort().should.eql([ - 'bom', 'cast', 'columns', 'delimiter', 'eof', 'escape', - 'escape_formulas', 'header', 'on_record', 'quote', 'quoted', - 'quoted_empty', 'quoted_match', 'quoted_string', 'record_delimiter' - ]) - }) - - it('Receive Callback', (next) => { - stringify([['a'], ['b']], function(err: Error | undefined, output: string){ - if(err !== undefined){ - output.should.eql('a\nb') - } - next(err) - }) - }) - - }) - - describe('Options', () => { - - it('bom', () => { - const options: Options = {} - options.bom = true - }) - - it('cast', () => { - const options: Options = {} +describe("API Types", function () { + describe("Parser", function () { + it("Expose options", function () { + const stringifier: Stringifier = stringify(); + const options: Options = stringifier.options; + const keys = Object.keys(options); + keys + .sort() + .should.eql([ + "bom", + "cast", + "columns", + "delimiter", + "eof", + "escape", + "escape_formulas", + "header", + "on_record", + "quote", + "quoted", + "quoted_empty", + "quoted_match", + "quoted_string", + "record_delimiter", + ]); + }); + + it("Receive Callback", function (next) { + stringify( + [["a"], ["b"]], + function (err: Error | undefined, output: string) { + if (err !== undefined) { + output.should.eql("a\nb"); + } + next(err); + }, + ); + }); + }); + + describe("Options", function () { + it("bom", function () { + const options: Options = {}; + options.bom = true; + }); + + it("cast", function () { + const options: Options = {}; options.cast = { boolean: (value: boolean) => { - return value ? 'true': 'false' + return value ? "true" : "false"; }, date: (value: Date) => { - return value ? 'true': 'false' + return value ? "true" : "false"; }, number: (value: number) => { - return value ? 'true': 'false' + return value ? "true" : "false"; }, bigint: (value: bigint) => { - return value ? 'true': 'false' + return value ? "true" : "false"; }, object: (value: object) => { - return value ? 'true': 'false' + return value ? "true" : "false"; }, string: (value: string) => { - return value ? 'true': 'false' + return value ? "true" : "false"; }, - } - }) - - it('columns', () => { - const options: Options = {} - options.columns = [ - 'b', - 'a' - ] + }; + }); + + it("columns", function () { + const options: Options = {}; + options.columns = ["b", "a"]; + options.columns = [{ key: "b" }, { key: "a" }]; options.columns = [ - { key: 'b' }, - { key: 'a' } - ] + { key: "b", header: "B" }, + { key: "a", header: "A" }, + "c", + { key: "d" }, + ]; options.columns = { - field1: 'column1', - field3: 'column3' - } - }) - - it("columns as const", () => { + field1: "column1", + field3: "column3", + }; + }); + + it("columns as const", function () { const options: Options = {}; options.columns = ["b", "a"]; options.columns = ["b", "a"] as const; }); - - it('delimiter', () => { - const options: Options = {} - options.delimiter = ':' - options.delimiter = Buffer.from(':') - }) - - it('escape', () => { - const options: Options = {} - options.escape = '"' - options.escape = Buffer.from('"') - }) - - it('escape_formulas', () => { - const options: Options = {} - options.escape_formulas = true - }) - - it('header', () => { - const options: Options = {} - options.header = true - }) - - it('quote', () => { - const options: Options = {} - options.quote = "\"" - options.quote = Buffer.from("\"") - options.quote = true - options.quote = false - }) - - it('quoted', () => { - const options: Options = {} - options.quoted = true - options.quoted = false - }) - - it('quoted_empty', () => { - const options: Options = {} - options.quoted_empty = true - options.quoted_empty = false - }) - - it('quoted_match', () => { - const options: Options = {} - options.quoted_match = "\"" - options.quoted_match = /\"/ - options.quoted_match = [ - "\"", - /\"/ - ] - }) - - it('quoted_string', () => { - const options: Options = {} - options.quoted_string = true - options.quoted_string = false - }) - - it('record_delimiter', () => { - const options: Options = {} - options.record_delimiter = '|' - options.record_delimiter = Buffer.from('|') - }) - - }) - - describe('CastingContext', () => { - - it('all properties', () => { + + it("delimiter", function () { + const options: Options = {}; + options.delimiter = ":"; + options.delimiter = Buffer.from(":"); + }); + + it("escape", function () { + const options: Options = {}; + options.escape = '"'; + options.escape = Buffer.from('"'); + }); + + it("escape_formulas", function () { + const options: Options = {}; + options.escape_formulas = true; + }); + + it("header", function () { + const options: Options = {}; + options.header = true; + }); + + it("quote", function () { + const options: Options = {}; + options.quote = '"'; + options.quote = Buffer.from('"'); + options.quote = true; + options.quote = false; + }); + + it("quoted", function () { + const options: Options = {}; + options.quoted = true; + options.quoted = false; + }); + + it("quoted_empty", function () { + const options: Options = {}; + options.quoted_empty = true; + options.quoted_empty = false; + }); + + it("quoted_match", function () { + const options: Options = {}; + options.quoted_match = '"'; + options.quoted_match = /"/; + options.quoted_match = ['"', /"/]; + }); + + it("quoted_string", function () { + const options: Options = {}; + options.quoted_string = true; + options.quoted_string = false; + }); + + it("record_delimiter", function () { + const options: Options = {}; + options.record_delimiter = "|"; + options.record_delimiter = Buffer.from("|"); + }); + }); + + describe("CastingContext", function () { + it("all properties", function () { (context: CastingContext) => { - const column: number|string|undefined = context.column - const header: boolean = context.header - const index: number = context.index - const records: number = context.records - return [ - column, header, index, records - ] - } - }) - }) - -}) + const column: number | string | undefined = context.column; + const header: boolean = context.header; + const index: number = context.index; + const records: number = context.records; + return [column, header, index, records]; + }; + }); + }); +}); diff --git a/packages/csv-stringify/test/api.web_stream.coffee b/packages/csv-stringify/test/api.web_stream.coffee deleted file mode 100644 index d0744f2e0..000000000 --- a/packages/csv-stringify/test/api.web_stream.coffee +++ /dev/null @@ -1,18 +0,0 @@ - -# import {generate as generateStream} from 'csv-generate/stream' -# import {stringify as stringifyStream} from '../lib/stream.js' -# import {stringify as stringifyClassic} from '../lib/index.js' -# -# describe 'api stream', -> -# -# it.skip 'perf stream with iterator', -> -# generator = generateStream -# objectMode: true, -# length: 5 -# stringifier = stringifyStream() -# stream = generator.pipeThrough stringifier -# chunks = [] -# for await chunk from stream -# chunks.push chunk -# # records.length.should.eql 5 -# console.log(chunks) diff --git a/packages/csv-stringify/test/api.web_stream.js b/packages/csv-stringify/test/api.web_stream.js new file mode 100644 index 000000000..4a67386a6 --- /dev/null +++ b/packages/csv-stringify/test/api.web_stream.js @@ -0,0 +1,21 @@ +import "should"; +// import { generate as generateStream } from "csv-generate/stream"; +// import { stringify as stringifyStream } from "../lib/stream.js"; +// import { stringify as stringifyClassic } from "../lib/index.js"; + +describe("api stream", function () { + it.skip("perf stream with iterator", function () { + // const generator = generateStream({ + // objectMode: true, + // length: 5 + // }) + // const stringifier = stringifyStream() + // const stream = generator.pipeThrough(stringifier) + // const chunks = [] + // for await (const chunk of stream) { + // chunks.push(chunk) + // } + // // records.length.should.eql 5 + // console.log(chunks) + }); +}); diff --git a/packages/csv-stringify/test/api.write.coffee b/packages/csv-stringify/test/api.write.coffee deleted file mode 100644 index e241d3e81..000000000 --- a/packages/csv-stringify/test/api.write.coffee +++ /dev/null @@ -1,127 +0,0 @@ - -import { stringify } from '../lib/index.js' - -describe 'API write', -> - - it 'arrays', (next) -> - count = 0 - data = '' - stringifier = stringify eof: false - stringifier.on 'readable', -> - while(d = stringifier.read()) - data += d - stringifier.on 'record', (record, index) -> - record.should.be.an.instanceof Array - count.should.eql index - count++ - stringifier.on 'finish', -> - count.should.eql 10 - data.should.eql """ - Test 0,0,\"\"\"\" - Test 1,1,\"\"\"\" - Test 2,2,\"\"\"\" - Test 3,3,\"\"\"\" - Test 4,4,\"\"\"\" - Test 5,5,\"\"\"\" - Test 6,6,\"\"\"\" - Test 7,7,\"\"\"\" - Test 8,8,\"\"\"\" - Test 9,9,\"\"\"\" - """ - next() - for i in [0...10] - stringifier.write ["Test #{i}", i, '"'] - stringifier.end() - - it 'objects with column options', (next) -> - count = 0 - data = '' - stringifier = stringify(columns: ['name','value','escape'], eof: false) - stringifier.on 'readable', -> - while(d = stringifier.read()) - data += d - stringifier.on 'record', (record, index) -> - record.should.be.an.Object - record.should.not.be.an.instanceOf Array - count.should.eql index - count++ - stringifier.on 'finish', -> - count.should.eql 10 - data.should.eql """ - Test 0,0,\"\"\"\" - Test 1,1,\"\"\"\" - Test 2,2,\"\"\"\" - Test 3,3,\"\"\"\" - Test 4,4,\"\"\"\" - Test 5,5,\"\"\"\" - Test 6,6,\"\"\"\" - Test 7,7,\"\"\"\" - Test 8,8,\"\"\"\" - Test 9,9,\"\"\"\" - """ - next() - for i in [0...10] - stringifier.write {name: "Test #{i}", value:i, escape: '"', ovni: "ET #{i}"} - stringifier.end() - - it 'throw error if not writable', (next) -> - stringifier = stringify() - stringifier.on 'error', (err) -> - err.message.should.eql 'write after end' - next() - stringifier.write ['abc','123'] - stringifier.end() - stringifier.write ['def', '456'] - - it 'accepts full write API', (next) -> - stringifier = stringify() - stringifier.on 'finish', -> - next() - stringifier.write ['abc','123'], 'utf8' , (e,d) -> - stringifier.end() - - it 'write invalid record null', (next) -> - stringifier = stringify() - stringifier.on 'error', (err) -> - # Until Node.js 13 - err.message.should.eql 'May not write null values to stream' - next() - stringifier.on 'end', -> - next Error 'Oh no!' - try - stringifier.write null, 'utf8' , (e,d) -> - stringifier.end() - catch err - # Since Node.js 14 - err.message.should.eql 'May not write null values to stream' - next() - - it 'write invalid record true', (next) -> - stringifier = stringify() - stringifier.on 'error', (err) -> - err.message.should.eql 'Invalid Record: expect an array or an object, got true' - next() - stringifier.on 'end', -> - next Error 'Oh no!' - stringifier.write true, 'utf8' , (e,d) -> - stringifier.end() - - describe 'input', -> - - it 'array are immutable', (next) -> - chunks = [['a', 'b'], ['c', 'd']] - stringify chunks, (err) -> - chunks.should.eql [['a', 'b'], ['c', 'd']] unless err - next err - - it 'object (with columns are immutable', (next) -> - chunks = [{a: 1, b: 2}, {a: 3, b: 4}] - stringify chunks, columns: ['b'], (err, data) -> - chunks.should.eql [{a: 1, b: 2}, {a: 3, b: 4}] unless err - next err - - it 'object (without columns) are immutable', (next) -> - chunks = [{a: 1, b: 2}, {a: 3, b: 4}] - stringify chunks, (err, data) -> - chunks.should.eql [{a: 1, b: 2}, {a: 3, b: 4}] unless err - next err diff --git a/packages/csv-stringify/test/api.write.js b/packages/csv-stringify/test/api.write.js new file mode 100644 index 000000000..fc3665ade --- /dev/null +++ b/packages/csv-stringify/test/api.write.js @@ -0,0 +1,197 @@ +import "should"; +import dedent from "dedent"; +import { stringify } from "../lib/index.js"; + +describe("API write", function () { + it("arrays", function (next) { + let count = 0; + let data = ""; + const stringifier = stringify({ eof: false }); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + stringifier.on("record", (record, index) => { + record.should.be.an.instanceof(Array); + count.should.eql(index); + count++; + }); + stringifier.on("finish", () => { + count.should.eql(10); + data.should.eql( + dedent` + Test 0,0,"""" + Test 1,1,"""" + Test 2,2,"""" + Test 3,3,"""" + Test 4,4,"""" + Test 5,5,"""" + Test 6,6,"""" + Test 7,7,"""" + Test 8,8,"""" + Test 9,9,"""" + `, + ); + next(); + }); + for (let i = 0; i < 10; i++) { + stringifier.write([`Test ${i}`, i, '"']); + } + stringifier.end(); + }); + + it("objects with column options", function (next) { + let count = 0; + let data = ""; + const stringifier = stringify({ + columns: ["name", "value", "escape"], + eof: false, + }); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + stringifier.on("record", (record, index) => { + record.should.be.an.Object(); + record.should.not.be.an.instanceOf(Array); + count.should.eql(index); + count++; + }); + stringifier.on("finish", () => { + count.should.eql(10); + data.should.eql( + dedent` + Test 0,0,"""" + Test 1,1,"""" + Test 2,2,"""" + Test 3,3,"""" + Test 4,4,"""" + Test 5,5,"""" + Test 6,6,"""" + Test 7,7,"""" + Test 8,8,"""" + Test 9,9,"""" + `, + ); + next(); + }); + for (let i = 0; i < 10; i++) { + stringifier.write({ + name: `Test ${i}`, + value: i, + escape: '"', + ovni: `ET ${i}`, + }); + } + stringifier.end(); + }); + + it("throw error if not writable", function (next) { + const stringifier = stringify(); + stringifier.on("error", (err) => { + err.message.should.eql("write after end"); + next(); + }); + stringifier.write(["abc", "123"]); + stringifier.end(); + stringifier.write(["def", "456"]); + }); + + it("accepts full write API", function (next) { + const stringifier = stringify(); + stringifier.on("finish", () => { + next(); + }); + stringifier.write(["abc", "123"], "utf8", () => { + stringifier.end(); + }); + }); + + it("write invalid record null", function (next) { + const stringifier = stringify(); + stringifier.on("error", (err) => { + // Until Node.js 13 + err.message.should.eql("May not write null values to stream"); + next(); + }); + stringifier.on("end", () => { + next(Error("Oh no!")); + }); + try { + stringifier.write(null, "utf8", () => { + stringifier.end(); + }); + } catch (err) { + // Since Node.js 14 + err.message.should.eql("May not write null values to stream"); + next(); + } + }); + + it("write invalid record true", function (next) { + const stringifier = stringify(); + stringifier.on("error", (err) => { + err.message.should.eql( + "Invalid Record: expect an array or an object, got true", + ); + next(); + }); + stringifier.on("end", () => { + next(Error("Oh no!")); + }); + stringifier.write(true, "utf8", () => { + stringifier.end(); + }); + }); + + describe("input", function () { + it("array are immutable", function (next) { + const chunks = [ + ["a", "b"], + ["c", "d"], + ]; + stringify(chunks, (err) => { + if (!err) + chunks.should.eql([ + ["a", "b"], + ["c", "d"], + ]); + next(err); + }); + }); + + it("object (with columns are immutable", function (next) { + const chunks = [ + { a: 1, b: 2 }, + { a: 3, b: 4 }, + ]; + stringify(chunks, { columns: ["b"] }, (err) => { + if (!err) + chunks.should.eql([ + { a: 1, b: 2 }, + { a: 3, b: 4 }, + ]); + next(err); + }); + }); + + it("object (without columns) are immutable", function (next) { + const chunks = [ + { a: 1, b: 2 }, + { a: 3, b: 4 }, + ]; + stringify(chunks, (err) => { + if (!err) + chunks.should.eql([ + { a: 1, b: 2 }, + { a: 3, b: 4 }, + ]); + next(err); + }); + }); + }); +}); diff --git a/packages/csv-stringify/test/loaders/all.js b/packages/csv-stringify/test/loaders/all.js deleted file mode 100644 index 4e81c3449..000000000 --- a/packages/csv-stringify/test/loaders/all.js +++ /dev/null @@ -1,15 +0,0 @@ -import * as coffee from "./coffee.js"; -import * as ts from "ts-node/esm"; - -const coffeeRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; -const tsRegex = /\.ts$/; - -export function load(url, context, next) { - if (coffeeRegex.test(url)) { - return coffee.load.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.load.apply(this, arguments); - } - return next(url, context, next); -} diff --git a/packages/csv-stringify/test/loaders/coffee.js b/packages/csv-stringify/test/loaders/coffee.js deleted file mode 100644 index 75b15abe0..000000000 --- a/packages/csv-stringify/test/loaders/coffee.js +++ /dev/null @@ -1,20 +0,0 @@ -import CoffeeScript from "coffeescript"; - -// See https://github.com/nodejs/node/issues/36396 -const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; - -export async function load(url, context, next) { - if (extensionsRegex.test(url)) { - const format = "module"; - const { source: rawSource } = await next(url, { format }); - const source = CoffeeScript.compile(rawSource.toString(), { - bare: true, - inlineMap: true, - filename: url, - header: false, - sourceMap: false, - }); - return { format, source }; - } - return next(url, context); -} diff --git a/packages/csv-stringify/test/loaders/legacy/all.js b/packages/csv-stringify/test/loaders/legacy/all.js deleted file mode 100644 index f5e57e542..000000000 --- a/packages/csv-stringify/test/loaders/legacy/all.js +++ /dev/null @@ -1,36 +0,0 @@ -import * as coffee from "./coffee.js"; -import * as ts from "ts-node/esm"; - -const coffeeRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; -const tsRegex = /\.ts$/; - -export function resolve(specifier) { - if (coffeeRegex.test(specifier)) { - return coffee.resolve.apply(this, arguments); - } - if (tsRegex.test(specifier)) { - return ts.resolve.apply(this, arguments); - } - return ts.resolve.apply(this, arguments); -} - -export function getFormat(url) { - if (coffeeRegex.test(url)) { - return coffee.getFormat.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.getFormat.apply(this, arguments); - } - return ts.getFormat.apply(this, arguments); -} - -export function transformSource(source, context) { - const { url } = context; - if (coffeeRegex.test(url)) { - return coffee.transformSource.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.transformSource.apply(this, arguments); - } - return ts.transformSource.apply(this, arguments); -} diff --git a/packages/csv-stringify/test/loaders/legacy/coffee.js b/packages/csv-stringify/test/loaders/legacy/coffee.js deleted file mode 100644 index 6a9975db9..000000000 --- a/packages/csv-stringify/test/loaders/legacy/coffee.js +++ /dev/null @@ -1,50 +0,0 @@ -// coffeescript-loader.mjs -import { URL, pathToFileURL } from "url"; -import CoffeeScript from "coffeescript"; -import { cwd } from "process"; - -const baseURL = pathToFileURL(`${cwd()}/`).href; - -// CoffeeScript files end in .coffee, .litcoffee or .coffee.md. -const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; - -export function resolve(specifier, context, defaultResolve) { - const { parentURL = baseURL } = context; - // Node.js normally errors on unknown file extensions, so return a URL for - // specifiers ending in the CoffeeScript file extensions. - if (extensionsRegex.test(specifier)) { - return { - url: new URL(specifier, parentURL).href, - stop: true, - }; - } - // Let Node.js handle all other specifiers. - return defaultResolve(specifier, context, defaultResolve); -} - -export function getFormat(url, context, defaultGetFormat) { - // Now that we patched resolve to let CoffeeScript URLs through, we need to - // tell Node.js what format such URLs should be interpreted as. For the - // purposes of this loader, all CoffeeScript URLs are ES modules. - if (extensionsRegex.test(url)) { - return { - format: "module", - stop: true, - }; - } - // Let Node.js handle all other URLs. - return defaultGetFormat(url, context, defaultGetFormat); -} - -export function transformSource(source, context, defaultTransformSource) { - const { url } = context; - - if (extensionsRegex.test(url)) { - return { - source: CoffeeScript.compile(String(source), { bare: true }), - }; - } - - // Let Node.js handle all other sources. - return defaultTransformSource(source, context, defaultTransformSource); -} diff --git a/packages/csv-stringify/test/option.bom.coffee b/packages/csv-stringify/test/option.bom.coffee deleted file mode 100644 index 70d90f2aa..000000000 --- a/packages/csv-stringify/test/option.bom.coffee +++ /dev/null @@ -1,56 +0,0 @@ - -import { stringify } from '../lib/index.js' -import { stringify as stringifySync } from '../lib/sync.js' - -describe 'Option `bom`', -> - - it 'validate', -> - (-> - stringify [], bom: 'invalid', (->) - ).should.throw - code: 'CSV_OPTION_BOOLEAN_INVALID_TYPE' - message: 'option `bom` is optional and must be a boolean value, got "invalid"' - - it 'empty', (next) -> - stringify [], bom: true, (err, data) -> - data.should.eql Buffer.from([239, 187, 191]).toString() - next() - - it 'value is `true`', (next) -> - stringify [ - value: 'ok' - ], bom: true, (err, data) -> - data.should.eql Buffer.from([239, 187, 191]).toString()+'ok\n' - next() - - it 'value is `false`', (next) -> - stringify [ - value: 'ok' - ], bom: false, (err, data) -> - data.should.eql 'ok\n' - next() - - describe 'sync ', -> - - it 'validate', -> - (-> - stringifySync [], bom: 'invalid' - ).should.throw - code: 'CSV_OPTION_BOOLEAN_INVALID_TYPE' - message: 'option `bom` is optional and must be a boolean value, got "invalid"' - - it 'empty', -> - data = stringifySync [], bom: true - data.should.eql Buffer.from([239, 187, 191]).toString() - - it 'value is `true`', -> - res = stringifySync [ - value: 'ok' - ], bom: true - res.should.eql '\ufeffok\n' - - it 'value is `false`', -> - res = stringifySync [ - value: 'ok' - ], bom: false - res.should.eql 'ok\n' diff --git a/packages/csv-stringify/test/option.bom.js b/packages/csv-stringify/test/option.bom.js new file mode 100644 index 000000000..36e431af8 --- /dev/null +++ b/packages/csv-stringify/test/option.bom.js @@ -0,0 +1,27 @@ +import "should"; +import { stringify } from "../lib/index.js"; +import { stringify as stringifySync } from "../lib/sync.js"; + +describe("Option `bom`", function () { + it("validate", function () { + (() => { + stringify([], { bom: "invalid" }, () => {}); + }).should.throw({ + code: "CSV_OPTION_BOOLEAN_INVALID_TYPE", + message: + 'option `bom` is optional and must be a boolean value, got "invalid"', + }); + }); + + describe("sync ", function () { + it("validate", function () { + (() => { + stringifySync([], { bom: "invalid" }); + }).should.throw({ + code: "CSV_OPTION_BOOLEAN_INVALID_TYPE", + message: + 'option `bom` is optional and must be a boolean value, got "invalid"', + }); + }); + }); +}); diff --git a/packages/csv-stringify/test/option.bom.ts b/packages/csv-stringify/test/option.bom.ts new file mode 100644 index 000000000..0512d5802 --- /dev/null +++ b/packages/csv-stringify/test/option.bom.ts @@ -0,0 +1,73 @@ +import "should"; +import { stringify } from "../lib/index.js"; +import { stringify as stringifySync } from "../lib/sync.js"; + +describe("Option `bom`", function () { + it("empty", function (next) { + stringify([], { bom: true }, (err, data) => { + data.should.eql(Buffer.from([239, 187, 191]).toString()); + next(); + }); + }); + + it("value is `true`", function (next) { + stringify( + [ + { + value: "ok", + }, + ], + { bom: true }, + (err, data) => { + data.should.eql(Buffer.from([239, 187, 191]).toString() + "ok\n"); + next(); + }, + ); + }); + + it("value is `false`", function (next) { + stringify( + [ + { + value: "ok", + }, + ], + { bom: false }, + (err, data) => { + data.should.eql("ok\n"); + next(); + }, + ); + }); + + describe("sync ", function () { + it("empty", function () { + const data = stringifySync([], { bom: true }); + data.should.eql(Buffer.from([239, 187, 191]).toString()); + }); + + it("value is `true`", function () { + const res = stringifySync( + [ + { + value: "ok", + }, + ], + { bom: true }, + ); + res.should.eql("\ufeffok\n"); + }); + + it("value is `false`", function () { + const res = stringifySync( + [ + { + value: "ok", + }, + ], + { bom: false }, + ); + res.should.eql("ok\n"); + }); + }); +}); diff --git a/packages/csv-stringify/test/option.cast.coffee b/packages/csv-stringify/test/option.cast.coffee deleted file mode 100644 index afa949c90..000000000 --- a/packages/csv-stringify/test/option.cast.coffee +++ /dev/null @@ -1,198 +0,0 @@ - -import { stringify } from '../lib/index.js' - -describe 'Option `cast`', -> - - describe 'default', -> - - it 'default BigInt formatter', (next) -> - stringify [ - value: BigInt 9007199254740991 - ], (err, data) -> - data.should.eql '9007199254740991\n' unless err - next err - - describe 'udf', -> - - it 'handle string formatter', (next) -> - stringify [ - value: 'ok' - ], {cast: string: -> 'X'}, (err, data) -> - data.should.eql 'X\n' unless err - next err - - it 'handle boolean formatter', (next) -> - stringify [ - value: true - ], {cast: boolean: -> 'X'}, (err, data) -> - data.should.eql 'X\n' unless err - next err - - it 'handle date formatter', (next) -> - stringify [ - value: new Date - ], {cast: date: -> 'X'}, (err, data) -> - data.should.eql 'X\n' unless err - next err - - it 'handle number formatter', (next) -> - stringify [ - value: 3.14 - ], {cast: number: (value) -> '' + value * 2 }, (err, data) -> - data.should.eql '6.28\n' unless err - next err - - it 'handle bigint formatter', (next) -> - stringify [ - value: BigInt(9007199254740991) - ], {cast: bigint: (value) -> '' + value / BigInt(2) }, (err, data) -> - data.should.eql '4503599627370495\n' unless err - next err - - it 'handle object formatter', (next) -> - stringify [ - value: a: 1 - ], {cast: object: -> 'X'}, (err, data) -> - data.should.eql 'X\n' unless err - next err - - it 'catch error', (next) -> - stringify [ - value: true - ], {cast: boolean: (value) -> throw Error 'Catchme'}, (err, data) -> - err.message.should.eql 'Catchme' - next() - - it 'return null', (next) -> - # We might change this behavior in futures version, allowing to skip a field - # if the return value is null or undefined, see #83 - stringify [ - { a: true, b: true } - { a: false, b: true } - { a: true, b: false } - { a: false, b: false } - ], {cast: boolean: (value) -> if value then '1' else null}, (err, data) -> - data.trim().should.eql """ - 1,1 - ,1 - 1, - , - """ - next() - - it 'boolean must return a string', (next) -> - stringify [ - value: true - ], {cast: boolean: (value) -> if value then 1 else 0}, (err, data) -> - err.message.should.eql 'Invalid Casting Value: returned value must return a string, an object, null or undefined, got 1' - next() - - describe 'context', -> - - it 'expose the expected properties', (next) -> - stringify [ - ['a'] - ], cast: string: (value, context) -> - Object.keys(context).sort().should.eql [ - 'column', 'header', 'index', 'records' - ] - null - , next - - it 'index and column on array', (next) -> - stringify [ - [true, false] - ], cast: boolean: (value, context) -> - if value - context.index.should.equal 0 - context.column.should.equal 0 - 'yes' - else - context.index.should.equal 1 - context.column.should.equal 1 - 'no' - , (err, data) -> - data.trim().should.eql 'yes,no' unless err - next err - - it 'index and column on object', (next) -> - stringify [ - is_true: true - is_false: false - ], cast: boolean: (value, context) -> - if value - context.index.should.equal 0 - context.column.should.equal 'is_true' - 'yes' - else - context.index.should.equal 1 - context.column.should.equal 'is_false' - 'no' - , (err, data) -> - data.trim().should.eql 'yes,no' unless err - next err - - it 'header', (next) -> - stringify [ - ['value 1'] - ['value 2'] - ], header: true, columns: ['header'], cast: string: (value, context) -> - "#{value} | #{context.header}" - , (err, data) -> - data.trim().should.eql """ - header | true - value 1 | false - value 2 | false - """ - next err - - describe 'option header', -> - - it 'records with header and columns as array', (next) -> - stringify [ - ['value 1'] - ['value 2'] - ], header: true, columns: ['header'], cast: string: (value, context) -> - "#{context.records}" - , (err, data) -> - data.trim().should.eql '0\n0\n1' unless err - next err - - it 'records without header', (next) -> - stringify [ - ['record 1'] - ['record 2'] - ], cast: string: (value, context) -> - "#{context.records}" - , (err, data) -> - data.trim().should.eql '0\n1' unless err - next err - - describe 'info object', -> - - it 'modify escape', (next) -> - stringify [ - ['record " 1'] - ['record " 2'] - ['record " 3'] - ], eof: false, escape: '#', cast: string: (value, context) -> - return value if context.records is 2 - value: value, escape: ['\\', '"'][context.records] - , (err, data) -> - data.should.eql """ - "record \\" 1" - "record "" 2" - "record #" 3" - """ - next err - - it 'validate and normalize local options', (next) -> - stringify [ - ['invalid cast'] - ], eof: false, escape: '#', cast: string: (value) -> - value: value, quote: NaN - , (err) -> - err.code.should.eql 'CSV_OPTION_QUOTE_INVALID_TYPE' - next() - - diff --git a/packages/csv-stringify/test/option.cast.js b/packages/csv-stringify/test/option.cast.js new file mode 100644 index 000000000..643c3c24e --- /dev/null +++ b/packages/csv-stringify/test/option.cast.js @@ -0,0 +1,45 @@ +import "should"; +import { stringify } from "../lib/index.js"; + +describe("Option `cast`", function () { + describe("udf", function () { + it("boolean must return a string", function (next) { + stringify( + [ + { + value: true, + }, + ], + { cast: { boolean: (value) => (value ? 1 : 0) } }, + (err) => { + err.message.should.eql( + "Invalid Casting Value: returned value must return a string, an object, null or undefined, got 1", + ); + next(); + }, + ); + }); + }); + + describe("info object", function () { + it("validate and normalize local options", function (next) { + stringify( + [["invalid cast"]], + { + eof: false, + escape: "#", + cast: { + string: (value) => ({ + value: value, + quote: NaN, + }), + }, + }, + (err) => { + err.code.should.eql("CSV_OPTION_QUOTE_INVALID_TYPE"); + next(); + }, + ); + }); + }); +}); diff --git a/packages/csv-stringify/test/option.cast.ts b/packages/csv-stringify/test/option.cast.ts new file mode 100644 index 000000000..f966eb77d --- /dev/null +++ b/packages/csv-stringify/test/option.cast.ts @@ -0,0 +1,311 @@ +import "should"; +import dedent from "dedent"; +import { stringify } from "../lib/index.js"; + +describe("Option `cast`", function () { + describe("default", function () { + it("default BigInt formatter", function (next) { + stringify( + [ + { + value: BigInt(9007199254740991), + }, + ], + (err, data) => { + if (!err) data.should.eql("9007199254740991\n"); + next(err); + }, + ); + }); + }); + + describe("udf", function () { + it("handle string formatter", function (next) { + stringify( + [ + { + value: "ok", + }, + ], + { cast: { string: () => "X" } }, + (err, data) => { + if (!err) data.should.eql("X\n"); + next(err); + }, + ); + }); + + it("handle boolean formatter", function (next) { + stringify( + [ + { + value: true, + }, + ], + { cast: { boolean: () => "X" } }, + (err, data) => { + if (!err) data.should.eql("X\n"); + next(err); + }, + ); + }); + + it("handle date formatter", function (next) { + stringify( + [ + { + value: new Date(), + }, + ], + { cast: { date: () => "X" } }, + (err, data) => { + if (!err) data.should.eql("X\n"); + next(err); + }, + ); + }); + + it("handle number formatter", function (next) { + stringify( + [ + { + value: 3.14, + }, + ], + { cast: { number: (value) => "" + value * 2 } }, + (err, data) => { + if (!err) data.should.eql("6.28\n"); + next(err); + }, + ); + }); + + it("handle bigint formatter", function (next) { + stringify( + [ + { + value: BigInt(9007199254740991), + }, + ], + { cast: { bigint: (value) => "" + value / BigInt(2) } }, + (err, data) => { + if (!err) data.should.eql("4503599627370495\n"); + next(err); + }, + ); + }); + + it("handle object formatter", function (next) { + stringify( + [ + { + value: { a: 1 }, + }, + ], + { cast: { object: () => "X" } }, + (err, data) => { + if (!err) data.should.eql("X\n"); + next(err); + }, + ); + }); + + it("catch error", function (next) { + stringify( + [ + { + value: true, + }, + ], + { + cast: { + boolean: () => { + throw Error("Catchme"); + }, + }, + }, + (err) => { + if (!err) return next(Error("Invalid assessment")); + err.message.should.eql("Catchme"); + next(); + }, + ); + }); + + it("return null", function (next) { + stringify( + [ + { a: true, b: true }, + { a: false, b: true }, + { a: true, b: false }, + { a: false, b: false }, + ], + { cast: { boolean: (value) => (value ? "1" : null) } }, + (err, data) => { + if (err) return next(err); + data.trim().should.eql("1,1\n,1\n1,\n,"); + next(); + }, + ); + }); + }); + + describe("context", function () { + it("expose the expected properties", function (next) { + stringify( + [["a"]], + { + cast: { + string: (value, context) => { + Object.keys(context) + .sort() + .should.eql(["column", "header", "index", "records"]); + return ""; + }, + }, + }, + next, + ); + }); + + it("index and column on array", function (next) { + stringify( + [[true, false]], + { + cast: { + boolean: (value, context) => { + if (context.column == null) throw Error("Invalid assessment"); + if (value) { + context.index.should.equal(0); + context.column.should.equal(0); + return "yes"; + } else { + context.index.should.equal(1); + context.column.should.equal(1); + return "no"; + } + }, + }, + }, + (err, data) => { + if (!err) data.trim().should.eql("yes,no"); + next(err); + }, + ); + }); + + it("index and column on object", function (next) { + stringify( + [ + { + is_true: true, + is_false: false, + }, + ], + { + cast: { + boolean: (value, context) => { + if (!context.column) throw Error("Invalid assessment"); + if (value) { + context.index.should.equal(0); + context.column.should.equal("is_true"); + return "yes"; + } else { + context.index.should.equal(1); + context.column.should.equal("is_false"); + return "no"; + } + }, + }, + }, + (err, data) => { + if (!err) data.trim().should.eql("yes,no"); + next(err); + }, + ); + }); + + it("header", function (next) { + stringify( + [["value 1"], ["value 2"]], + { + header: true, + columns: ["header"], + cast: { + string: (value, context) => `${value} | ${context.header}`, + }, + }, + (err, data) => { + if (!err) + data + .trim() + .should.eql("header | true\nvalue 1 | false\nvalue 2 | false"); + next(err); + }, + ); + }); + }); + + describe("option header", function () { + it("records with header and columns as array", function (next) { + stringify( + [["value 1"], ["value 2"]], + { + header: true, + columns: ["header"], + cast: { + string: (value, context) => `${context.records}`, + }, + }, + (err, data) => { + if (!err) data.trim().should.eql("0\n0\n1"); + next(err); + }, + ); + }); + + it("records without header", function (next) { + stringify( + [["record 1"], ["record 2"]], + { + cast: { + string: (value, context) => `${context.records}`, + }, + }, + (err, data) => { + if (!err) data.trim().should.eql("0\n1"); + next(err); + }, + ); + }); + }); + + describe("info object", function () { + it("modify escape", function (next) { + stringify( + [['record " 1'], ['record " 2'], ['record " 3']], + { + eof: false, + escape: "#", + cast: { + string: (value, context) => { + if (context.records === 2) return value; + return { + value: value, + escape: ["\\", '"'][context.records], + }; + }, + }, + }, + (err, data) => { + data.should.eql(dedent` + "record \" 1" + "record "" 2" + "record #" 3" + `); + next(err); + }, + ); + }); + }); +}); diff --git a/packages/csv-stringify/test/option.columns.coffee b/packages/csv-stringify/test/option.columns.coffee deleted file mode 100644 index aec2f955e..000000000 --- a/packages/csv-stringify/test/option.columns.coffee +++ /dev/null @@ -1,119 +0,0 @@ - -import { stringify } from '../lib/index.js' - -describe 'Option `columns`', -> - - describe 'definition', -> - - it 'validates option types', -> - (-> - stringify [], columns: true, (->) - ).should.throw 'Invalid option "columns": expect an array or an object' - (-> - stringify [], columns: false, (->) - ).should.throw 'Invalid option "columns": expect an array or an object' - (-> - stringify [], columns: '', (->) - ).should.throw 'Invalid option "columns": expect an array or an object' - (-> - stringify [], columns: (->), (->) - ).should.throw 'Invalid option "columns": expect an array or an object' - - it 'validates column definition', -> - (-> - stringify [], columns: [ - key_does_not_exists: 'yes' - ], (->) - ).should.throw 'Invalid column definition: property "key" is required' - (-> - stringify [], columns: [ - true - ], (->) - ).should.throw 'Invalid column definition: expect a string or an object' - - it 'is an array with column object', (next) -> - stringify [ - {a: '11', b: '12'} - {a: '21', b: '22'} - ], columns: [ - { key: 'b' } - { key: 'a' } - ], (err, records) -> - records.should.eql "12,11\n22,21\n" - next err - - it 'is an array of strings', (next) -> - stringify [ - {a: '11', b: '12'} - {a: '21', b: '22'} - ], columns: [ - 'b' - 'a' - ], (err, records) -> - records.should.eql "12,11\n22,21\n" - next err - - it 'is an array of strings matching nested object', (next) -> - stringify [ - {a: {a1: '1a1', a2: '1a2'}, b: '1b'} - {a: {a1: '2a1', a2: '2a2'}, b: '2b'} - ], columns: [ - 'b' - 'a.a2' - ], (err, records) -> - records.should.eql "1b,1a2\n2b,2a2\n" - next err - - it 'is an array of strings matching nested [object]', (next) -> - stringify [ - {a: [{}, {a1: '1a1', a2: '1a2'}], b: '1b'} - {a: [{}, {a1: '2a1', a2: '2a2'}], b: '2b'} - ], columns: [ - 'b' - 'a[1].a2' - ], (err, records) -> - records.should.eql "1b,1a2\n2b,2a2\n" - next err - - it 'is an array of strings with parent key not matching a nested object', (next) -> - stringify [ - {a: undefined, b: '1b'} - {a: null, b: '2b'} - {a: false, b: '3b'} - ], columns: [ - 'b' - 'a.a2' - ], (err, records) -> - records.should.eql "1b,\n2b,\n3b,\n" - next err - - it 'can still access fields with dots', (next) -> - stringify [ - {'foo.bar': '1'} - {'foo.bar': '2'} - ], header: true, (err, records) -> - records.should.eql "foo.bar\n1\n2\n" unless err - next err - - describe 'input', -> - - it 'is an array, should be the same length', (next) -> - # Since there is not columns set in input options, we just expect - # the output stream to contains 2 fields - stringify [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - ], columns: ["FIELD_1", "FIELD_2"], (err, data) -> - data.should.eql '20322051544,1979\n28392898392,1974\n' unless err - next err - - it 'is a readable stream', (next) -> - ws = stringify - header: true - columns: field1: 'column1', field3: 'column3' - , (err, data) -> - data.should.eql 'column1,column3\nval11,val13\nval21,val23\n' unless err - next err - ws.write {field1: 'val11', field2: 'val12', field3: 'val13'} - ws.write {field1: 'val21', field2: 'val22', field3: 'val23'} - ws.end() diff --git a/packages/csv-stringify/test/option.columns.js b/packages/csv-stringify/test/option.columns.js new file mode 100644 index 000000000..a83bd1dd1 --- /dev/null +++ b/packages/csv-stringify/test/option.columns.js @@ -0,0 +1,48 @@ +import "should"; +import { stringify } from "../lib/index.js"; + +describe("Option `columns`", function () { + describe("definition", function () { + it("validates option types", function () { + (() => { + stringify([], { columns: true }, () => {}); + }).should.throw('Invalid option "columns": expect an array or an object'); + (() => { + stringify([], { columns: false }, () => {}); + }).should.throw('Invalid option "columns": expect an array or an object'); + (() => { + stringify([], { columns: "" }, () => {}); + }).should.throw('Invalid option "columns": expect an array or an object'); + (() => { + stringify([], { columns: () => {} }, () => {}); + }).should.throw('Invalid option "columns": expect an array or an object'); + }); + + it("validates column definition", function () { + (() => { + stringify( + [], + { + columns: [ + { + key_does_not_exists: "yes", + }, + ], + }, + () => {}, + ); + }).should.throw('Invalid column definition: property "key" is required'); + (() => { + stringify( + [], + { + columns: [true], + }, + () => {}, + ); + }).should.throw( + "Invalid column definition: expect a string or an object", + ); + }); + }); +}); diff --git a/packages/csv-stringify/test/option.columns.ts b/packages/csv-stringify/test/option.columns.ts new file mode 100644 index 000000000..c5e5783fe --- /dev/null +++ b/packages/csv-stringify/test/option.columns.ts @@ -0,0 +1,135 @@ +import "should"; +import { stringify } from "../lib/index.js"; + +describe("Option `columns`", function () { + describe("definition", function () { + it("is an array with column object", function (next) { + stringify( + [ + { a: "11", b: "12" }, + { a: "21", b: "22" }, + ], + { + columns: [{ key: "b" }, { key: "a" }], + }, + (err, records) => { + records.should.eql("12,11\n22,21\n"); + next(err); + }, + ); + }); + + it("is an array of strings", function (next) { + stringify( + [ + { a: "11", b: "12" }, + { a: "21", b: "22" }, + ], + { + columns: ["b", "a"], + }, + (err, records) => { + records.should.eql("12,11\n22,21\n"); + next(err); + }, + ); + }); + + it("is an array of strings matching nested object", function (next) { + stringify( + [ + { a: { a1: "1a1", a2: "1a2" }, b: "1b" }, + { a: { a1: "2a1", a2: "2a2" }, b: "2b" }, + ], + { + columns: ["b", "a.a2"], + }, + (err, records) => { + records.should.eql("1b,1a2\n2b,2a2\n"); + next(err); + }, + ); + }); + + it("is an array of strings matching nested [object]", function (next) { + stringify( + [ + { a: [{}, { a1: "1a1", a2: "1a2" }], b: "1b" }, + { a: [{}, { a1: "2a1", a2: "2a2" }], b: "2b" }, + ], + { + columns: ["b", "a[1].a2"], + }, + (err, records) => { + records.should.eql("1b,1a2\n2b,2a2\n"); + next(err); + }, + ); + }); + + it("is an array of strings with parent key not matching a nested object", function (next) { + stringify( + [ + { a: undefined, b: "1b" }, + { a: null, b: "2b" }, + { a: false, b: "3b" }, + ], + { + columns: ["b", "a.a2"], + }, + (err, records) => { + records.should.eql("1b,\n2b,\n3b,\n"); + next(err); + }, + ); + }); + + it("can still access fields with dots", function (next) { + stringify( + [{ "foo.bar": "1" }, { "foo.bar": "2" }], + { + header: true, + }, + (err, records) => { + if (!err) records.should.eql("foo.bar\n1\n2\n"); + next(err); + }, + ); + }); + }); + + describe("input", function () { + it("is an array, should be the same length", function (next) { + stringify( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ], + { + columns: ["FIELD_1", "FIELD_2"], + }, + (err, data) => { + if (!err) data.should.eql("20322051544,1979\n28392898392,1974\n"); + next(err); + }, + ); + }); + + it("is a readable stream", function (next) { + const ws = stringify( + { + header: true, + columns: { field1: "column1", field3: "column3" }, + }, + (err, data) => { + if (!err) + data.should.eql("column1,column3\nval11,val13\nval21,val23\n"); + next(err); + }, + ); + ws.write({ field1: "val11", field2: "val12", field3: "val13" }); + ws.write({ field1: "val21", field2: "val22", field3: "val23" }); + ws.end(); + }); + }); +}); diff --git a/packages/csv-stringify/test/option.delimiter.coffee b/packages/csv-stringify/test/option.delimiter.coffee deleted file mode 100644 index 366a2af3e..000000000 --- a/packages/csv-stringify/test/option.delimiter.coffee +++ /dev/null @@ -1,73 +0,0 @@ - -import { stringify } from '../lib/index.js' - -describe 'Option `delimiter`', -> - - it 'validation', -> - stringify [], delimiter: '' - stringify [], delimiter: ',' - stringify [], delimiter: ',,' - stringify [], delimiter: Buffer.from ',' - ( -> - stringify [], delimiter: true - ).should.throw - code: 'CSV_OPTION_DELIMITER_INVALID_TYPE' - message: 'option `delimiter` must be a buffer or a string, got true' - ( -> - stringify [], delimiter: false - ).should.throw - code: 'CSV_OPTION_DELIMITER_INVALID_TYPE' - message: 'option `delimiter` must be a buffer or a string, got false' - ( -> - stringify [], delimiter: 123 - ).should.throw - code: 'CSV_OPTION_DELIMITER_INVALID_TYPE' - message: 'option `delimiter` must be a buffer or a string, got 123' - - it 'with default value', (next) -> - stringify [ - [ '20322051544','','8.8017226E7','45',''] - [ '','1974','8.8392926E7','',''] - ], eof: false, (err, data) -> - return next err if err - data.should.eql """ - 20322051544,,8.8017226E7,45, - ,1974,8.8392926E7,, - """ - next() - - it 'disabled if empty', (next) -> - stringify [ - [ 'a',1] - [ 'b',2] - ], delimiter: '', eof: false, (err, data) -> - return next err if err - data.should.eql """ - a1 - b2 - """ - next() - - it 'with on character', (next) -> - stringify [ - [ '20322051544','','8.8017226E7','45',''] - [ '','1974','8.8392926E7','',''] - ], delimiter: '\t', eof: false, (err, data) -> - return next err if err - data.should.eql """ - 20322051544\t\t8.8017226E7\t45\t - \t1974\t8.8392926E7\t\t - """ - next() - - it 'with multiple character', (next) -> - stringify [ - [ 'a','b'] - [ 'c','d'] - ], delimiter: ':)(:', eof: false, (err, data) -> - return next err if err - data.should.eql """ - a:)(:b - c:)(:d - """ - next() diff --git a/packages/csv-stringify/test/option.delimiter.js b/packages/csv-stringify/test/option.delimiter.js new file mode 100644 index 000000000..4c5217cb3 --- /dev/null +++ b/packages/csv-stringify/test/option.delimiter.js @@ -0,0 +1,25 @@ +import "should"; +import { stringify } from "../lib/index.js"; + +describe("Option `delimiter`", function () { + it("validation", function () { + (() => { + stringify([], { delimiter: true }); + }).should.throw({ + code: "CSV_OPTION_DELIMITER_INVALID_TYPE", + message: "option `delimiter` must be a buffer or a string, got true", + }); + (() => { + stringify([], { delimiter: false }); + }).should.throw({ + code: "CSV_OPTION_DELIMITER_INVALID_TYPE", + message: "option `delimiter` must be a buffer or a string, got false", + }); + (() => { + stringify([], { delimiter: 123 }); + }).should.throw({ + code: "CSV_OPTION_DELIMITER_INVALID_TYPE", + message: "option `delimiter` must be a buffer or a string, got 123", + }); + }); +}); diff --git a/packages/csv-stringify/test/option.delimiter.ts b/packages/csv-stringify/test/option.delimiter.ts new file mode 100644 index 000000000..38b205729 --- /dev/null +++ b/packages/csv-stringify/test/option.delimiter.ts @@ -0,0 +1,84 @@ +import "should"; +import { stringify } from "../lib/index.js"; + +describe("Option `delimiter`", function () { + it("validation", function () { + stringify([], { delimiter: "" }); + stringify([], { delimiter: "," }); + stringify([], { delimiter: ",," }); + stringify([], { delimiter: Buffer.from(",") }); + }); + + it("with default value", function (next) { + stringify( + [ + ["20322051544", "", "8.8017226E7", "45", ""], + ["", "1974", "8.8392926E7", "", ""], + ], + { + eof: false, + }, + (err, data) => { + if (err) return next(err); + data.should.eql("20322051544,,8.8017226E7,45,\n,1974,8.8392926E7,,"); + next(); + }, + ); + }); + + it("disabled if empty", function (next) { + stringify( + [ + ["a", 1], + ["b", 2], + ], + { + delimiter: "", + eof: false, + }, + (err, data) => { + if (err) return next(err); + data.should.eql("a1\nb2"); + next(); + }, + ); + }); + + it("with on character", function (next) { + stringify( + [ + ["20322051544", "", "8.8017226E7", "45", ""], + ["", "1974", "8.8392926E7", "", ""], + ], + { + delimiter: "\t", + eof: false, + }, + (err, data) => { + if (err) return next(err); + data.should.eql( + "20322051544\t\t8.8017226E7\t45\t\n\t1974\t8.8392926E7\t\t", + ); + next(); + }, + ); + }); + + it("with multiple character", function (next) { + stringify( + [ + ["a", "b"], + ["c", "d"], + ], + { + delimiter: ":)(:", + eof: false, + }, + (err, data) => { + if (err) return next(err); + data.should.eql("a:)(:b\nc:)(:d"); + next(); + }, + ); + }); +}); diff --git a/packages/csv-stringify/test/option.eof.coffee b/packages/csv-stringify/test/option.eof.coffee deleted file mode 100644 index 20380319c..000000000 --- a/packages/csv-stringify/test/option.eof.coffee +++ /dev/null @@ -1,22 +0,0 @@ - -import { stringify } from '../lib/index.js' - -describe 'Option `eof`', -> - - it 'print line break when true', (next) -> - stringify [ - ['a','b','c'] - ['1','2','3'] - ], eof: true, (err, data) -> - return next err if err - data.should.eql "a,b,c\n1,2,3\n" - next() - - it 'dont print line break when false', (next) -> - stringify [ - ['a','b','c'] - ['1','2','3'] - ], eof: false, (err, data) -> - return next err if err - data.should.eql "a,b,c\n1,2,3" - next() diff --git a/packages/csv-stringify/test/option.eof.ts b/packages/csv-stringify/test/option.eof.ts new file mode 100644 index 000000000..64c5be4f3 --- /dev/null +++ b/packages/csv-stringify/test/option.eof.ts @@ -0,0 +1,34 @@ +import "should"; +import { stringify } from "../lib/index.js"; + +describe("Option `eof`", function () { + it("print line break when true", function (next) { + stringify( + [ + ["a", "b", "c"], + ["1", "2", "3"], + ], + { eof: true }, + (err, data) => { + if (err) return next(err); + data.should.eql("a,b,c\n1,2,3\n"); + next(); + }, + ); + }); + + it("dont print line break when false", function (next) { + stringify( + [ + ["a", "b", "c"], + ["1", "2", "3"], + ], + { eof: false }, + (err, data) => { + if (err) return next(err); + data.should.eql("a,b,c\n1,2,3"); + next(); + }, + ); + }); +}); diff --git a/packages/csv-stringify/test/option.escape.coffee b/packages/csv-stringify/test/option.escape.coffee deleted file mode 100644 index 006bfdfee..000000000 --- a/packages/csv-stringify/test/option.escape.coffee +++ /dev/null @@ -1,78 +0,0 @@ - -import { stringify } from '../lib/index.js' - -describe 'Option `escape`', -> - - it 'default', (next) -> - stringifier = stringify [ - ['abc', 'def'] - ], -> - stringifier.options.escape.should.eql('"') - next() - - it 'validation', -> - stringify [], escape: ',' - stringify [], escape: Buffer.from ',' - ( -> - stringify [], escape: true - ).should.throw 'Invalid Option: escape must be a buffer or a string, got true' - ( -> - stringify [], escape: false - ).should.throw 'Invalid Option: escape must be a buffer or a string, got false' - ( -> - stringify [], escape: 123 - ).should.throw 'Invalid Option: escape must be a buffer or a string, got 123' - ( -> - stringify [], escape: 'XX' - ).should.throw 'Invalid Option: escape must be one character, got 2 characters' - - it 'only apply to quote and escape characters', (next) -> - stringify [ - [ '-', '1"2' ] - [ '-', '"' ] - [ '-', '"abc' ] - [ '-', 'def"' ] - ], escape: '"', eof: false, (err, data) -> - return next err if err - data.should.eql """ - -,"1""2" - -,"\"\"" - -,"\""abc" - -,"def\""" - """ - next() - - it 'escape delimiter', (next) -> - stringify [ - [ 'a', 'b,c', 'd' ] - ], escape: '"', delimiter: ',', eof: false, (err, data) -> - return next err if err - data.should.eql """ - a,"b,c",d - """ - next() - - it 'escape record_delimiter', (next) -> - stringify [ - [ 'a', 'b\nc', 'd' ] - ], escape: '"', record_delimiter: '\n', eof: false, (err, data) -> - return next err if err - data.should.eql """ - a,"b\nc",d - """ - next() - - it 'should honor the backslash escape characters', (next) -> - stringify [ - [ '1"2','3"4"5' ] - [ '\\abc', 'def\\' ] - [ 'escape and quote','\\"' ] # actually \" - ], escape: '\\', eof: false, (err, data) -> - return next err if err - data.should.eql """ - "1\\"2","3\\"4\\"5" - \\abc,def\\ - escape and quote,"\\\\\\\"" - """ - # for the "escape char and quote char" value we want: \\\" - next() diff --git a/packages/csv-stringify/test/option.escape.js b/packages/csv-stringify/test/option.escape.js new file mode 100644 index 000000000..b4026dc41 --- /dev/null +++ b/packages/csv-stringify/test/option.escape.js @@ -0,0 +1,27 @@ +import "should"; +import { stringify } from "../lib/index.js"; + +describe("Option `escape`", function () { + it("validation", function () { + (() => { + stringify([], { escape: true }); + }).should.throw( + "Invalid Option: escape must be a buffer or a string, got true", + ); + (() => { + stringify([], { escape: false }); + }).should.throw( + "Invalid Option: escape must be a buffer or a string, got false", + ); + (() => { + stringify([], { escape: 123 }); + }).should.throw( + "Invalid Option: escape must be a buffer or a string, got 123", + ); + (() => { + stringify([], { escape: "XX" }); + }).should.throw( + "Invalid Option: escape must be one character, got 2 characters", + ); + }); +}); diff --git a/packages/csv-stringify/test/option.escape.ts b/packages/csv-stringify/test/option.escape.ts new file mode 100644 index 000000000..d84143b6c --- /dev/null +++ b/packages/csv-stringify/test/option.escape.ts @@ -0,0 +1,85 @@ +import "should"; +import dedent from "dedent"; +import { stringify } from "../lib/index.js"; + +describe("Option `escape`", function () { + it("default", function (next) { + const stringifier = stringify([["abc", "def"]], () => { + stringifier.options.escape.should.eql('"'); + next(); + }); + }); + + it("validation", function () { + stringify([], { escape: "," }); + stringify([], { escape: Buffer.from(",") }); + }); + + it("only apply to quote and escape characters", function (next) { + stringify( + [ + ["-", '1"2'], + ["-", '"'], + ["-", '"abc'], + ["-", 'def"'], + ], + { escape: '"', eof: false }, + (err, data) => { + if (err) return next(err); + data.should.eql(dedent` + -,"1""2" + -,"""" + -,"""abc" + -,"def""" + `); + next(); + }, + ); + }); + + it("escape delimiter", function (next) { + stringify( + [["a", "b,c", "d"]], + { escape: '"', delimiter: ",", eof: false }, + (err, data) => { + if (err) return next(err); + data.should.eql('a,"b,c",d'); + next(); + }, + ); + }); + + it("escape record_delimiter", function (next) { + stringify( + [["a", "b\nc", "d"]], + { escape: '"', record_delimiter: "\n", eof: false }, + (err, data) => { + if (err) return next(err); + data.should.eql('a,"b\nc",d'); + next(); + }, + ); + }); + + it("should honor the backslash escape characters", function (next) { + stringify( + [ + ['1"2', '3"4"5'], + ["\\abc", "def\\"], + ["escape and quote", '\\"'], + ], + { escape: "\\", eof: false }, + (err, data) => { + if (err) return next(err); + data.should.eql( + [ + '"1\\"2","3\\"4\\"5"', + "\\abc,def\\", + 'escape and quote,"\\\\\\""', + ].join("\n"), + ); + next(); + }, + ); + }); +}); diff --git a/packages/csv-stringify/test/option.escape_formulas.coffee b/packages/csv-stringify/test/option.escape_formulas.coffee deleted file mode 100644 index fd606031f..000000000 --- a/packages/csv-stringify/test/option.escape_formulas.coffee +++ /dev/null @@ -1,64 +0,0 @@ - -import { stringify } from '../lib/index.js' - -describe 'Option `escape_formulas`', -> - - it 'default to `false`', (next) -> - stringifier = stringify [ - ['abc', 'def'] - ], -> - stringifier.options.escape_formulas.should.be.false() - next() - - it 'validation', -> - (-> - stringify [ - ['abc', 'def'] - ], escape_formulas: 'invalid' - ).should.throw - code: 'CSV_OPTION_ESCAPE_FORMULAS_INVALID_TYPE' - message: 'option `escape_formulas` must be a boolean, got "invalid"' - - it 'escape =, +, -, @, \\t, \\r and unicode equivalent signs', (next) -> - stringify [ - [ '=a',1] - [ '+b',2] - [ '-c',3] - [ '@d',4] - [ '\te',5] - [ '\rf',6] - [ 'g',7] - [ '\uFF1Dh',8] - [ '\uFF0Bi',9] - [ '\uFF0Dj',10] - [ '\uFF20k',11] - [ '\uFF0Cl',12] # \uFF0C is 'full width comma' and should not be escaped - ], escape_formulas: true, eof: false, (err, data) -> - return next err if err - data.should.eql """ - '=a,1 - '+b,2 - '-c,3 - '@d,4 - '\te,5 - '\rf,6 - g,7 - '\uFF1Dh,8 - '\uFF0Bi,9 - '\uFF0Dj,10 - '\uFF20k,11 - \uFF0Cl,12 - """ - next() - - it 'with `quoted` option', (next) -> - stringify [ - [ '=a',1] - [ 'b',2] - ], escape_formulas: true, quoted: true, eof: false, (err, data) -> - return next err if err - data.should.eql """ - "'=a","1" - "b","2" - """ - next() diff --git a/packages/csv-stringify/test/option.escape_formulas.js b/packages/csv-stringify/test/option.escape_formulas.js new file mode 100644 index 000000000..a9abe00e9 --- /dev/null +++ b/packages/csv-stringify/test/option.escape_formulas.js @@ -0,0 +1,13 @@ +import "should"; +import { stringify } from "../lib/index.js"; + +describe("Option `escape_formulas`", function () { + it("validation", function () { + (() => { + stringify([["abc", "def"]], { escape_formulas: "invalid" }); + }).should.throw({ + code: "CSV_OPTION_ESCAPE_FORMULAS_INVALID_TYPE", + message: 'option `escape_formulas` must be a boolean, got "invalid"', + }); + }); +}); diff --git a/packages/csv-stringify/test/option.escape_formulas.ts b/packages/csv-stringify/test/option.escape_formulas.ts new file mode 100644 index 000000000..9963c6531 --- /dev/null +++ b/packages/csv-stringify/test/option.escape_formulas.ts @@ -0,0 +1,77 @@ +import "should"; +import dedent from "dedent"; +import { stringify } from "../lib/index.js"; + +describe("Option `escape_formulas`", function () { + it("default to `false`", function (next) { + const stringifier = stringify([["abc", "def"]], () => { + stringifier.options.escape_formulas.should.be.false(); + next(); + }); + }); + + it("escape =, +, -, @, \\t, \\r and unicode equivalent signs", function (next) { + stringify( + [ + ["=a", 1], + ["+b", 2], + ["-c", 3], + ["@d", 4], + ["\te", 5], + ["\rf", 6], + ["g", 7], + ["\uFF1Dh", 8], + ["\uFF0Bi", 9], + ["\uFF0Dj", 10], + ["\uFF20k", 11], + ["\uFF0Cl", 12], // \uFF0C is 'full width comma' and should not be escaped + ], + { + escape_formulas: true, + eof: false, + }, + (err, data) => { + if (err) return next(err); + data.should.eql( + [ + "'=a,1", + "'+b,2", + "'-c,3", + "'@d,4", + "'\te,5", + "'\rf,6", + "g,7", + "'\uFF1Dh,8", + "'\uFF0Bi,9", + "'\uFF0Dj,10", + "'\uFF20k,11", + "\uFF0Cl,12", + ].join("\n"), + ); + next(); + }, + ); + }); + + it("with `quoted` option", function (next) { + stringify( + [ + ["=a", 1], + ["b", 2], + ], + { + escape_formulas: true, + quoted: true, + eof: false, + }, + (err, data) => { + if (err) return next(err); + data.should.eql(dedent` + "'=a","1" + "b","2" + `); + next(); + }, + ); + }); +}); diff --git a/packages/csv-stringify/test/option.header.coffee b/packages/csv-stringify/test/option.header.coffee deleted file mode 100644 index 7f3b88cf0..000000000 --- a/packages/csv-stringify/test/option.header.coffee +++ /dev/null @@ -1,140 +0,0 @@ - -import { stringify } from '../lib/index.js' -import { stringify as stringifySync } from '../lib/sync.js' - -describe 'Option `header`', -> - - it 'as "true" and without "column" option with objects', (next) -> - stringify [ - {field1: 'val11', field2: 'val12', field3: 'val13'} - {field1: 'val21', field2: 'val22', field3: 'val23'} - ], header: true, (err, data) -> - return next err if err - data.should.eql 'field1,field2,field3\nval11,val12,val13\nval21,val22,val23\n' - next() - - it 'must get columns from somewhere', (next) -> - stringify [ - ['h1', 'h2', 'h3'] - ['1', '2', '3'] - ['4', '5', '6'] - ], header: true, (err, data) -> - err.message.should.eql 'Undiscoverable Columns: header option requires column option or object records' - next() - - it 'is immutable', (next) -> - options = header: true, quotedEmpty:true, delimiter: "|" - data1 = [ { a:'1', b:'2', c:'3' }, {a: '4', b: '5', c: '6'} ] - data2 = [ { x:'1', y:'2', z:'3' }, {x: '4', y: '5', z: '6' } ] - stringify data1, options, (err, result1) -> - stringify data2, options, (err, result2) -> - result1.should.eql "a|b|c\n1|2|3\n4|5|6\n" unless err - result2.should.eql "x|y|z\n1|2|3\n4|5|6\n" unless err - next err - - describe 'event', -> - - it 'emit header', (next) -> - count = 0 - data = '' - stringifier = stringify(columns: [ 'col1', 'col2' ], header: true) - stringifier.on 'readable', -> - while(d = stringifier.read()) - data += d - stringifier.on 'record', (record, index) -> - count++ - stringifier.on 'finish', -> - count.should.eql 2 - data.should.eql 'col1,col2\nfoo1,goo1\nfoo2,goo2\n' - next() - stringifier.write col1: 'foo1', col2: 'goo1' - stringifier.write col1: 'foo2', col2: 'goo2' - stringifier.end() - - it 'emit header even without a source', (next) -> - count = 0 - data = '' - stringifier = stringify(columns: [ 'col1', 'col2' ], header: true) - stringifier.on 'readable', -> - while(d = stringifier.read()) - data += d - stringifier.on 'end', -> - data.should.eql 'col1,col2\n' - next() - stringifier.end() - - describe 'without records', -> - - it 'print headers if no records to parse', (next) -> - stringify [], header: true, columns: ['some', 'headers'], (err, data) -> - data.should.eql 'some,headers\n' - next() - - it 'print headers if no records to parse in sync mode, fix #343', -> - data = stringifySync [], header: true, columns: ['some', 'headers'] - data.should.eql 'some,headers\n' - - it 'not print headers if no records to parse and no header option', (next) -> - stringify [], header: false, columns: ['some', 'headers'], (err, data) -> - data.should.eql '' - next() - - describe 'with column', -> - - it 'filter records array properties not listed as columns', (next) -> - stringify [ - [ 20322051544, 1979, 'ABC', 45, ] - [ 28392898392, 1974, 'DEF', 23, ] - ], header: true, columns: ["a", "b"], eof: false, (err, data) -> - data.should.eql """ - a,b - 20322051544,1979 - 28392898392,1974 - """ unless err - next err - - it 'filter records object properties not listed as columns', (next) -> - stringify [ - { a: 20322051544, b: '1979', c: '8.8017226E7' } - { a: 28392898392, b: '1974', c: '8.8392926E7' } - ], header: true, columns: ["a", "c"], eof: false, (err, data) -> - data.should.eql """ - a,c - 20322051544,8.8017226E7 - 28392898392,8.8392926E7 - """ - next() - - it 'map the column property name to display name', (next) -> - stringify [ - { field1: 'val11', field2: 'val12', field3: 'val13' } - { field1: 'val21', field2: 'val22', field3: 'val23' } - ], header: true, columns: {field1: 'column1', field3: 'column3'}, (err, data) -> - data.should.eql 'column1,column3\nval11,val13\nval21,val23\n' unless err - next err - - it 'map the column property name to display name', (next) -> - stringify [ - { field1: 'val11', field2: 'val12', field3: 'val13' } - { field1: 'val21', field2: 'val22', field3: 'val23' } - ], header: true, columns: {field1: 'column1', field3: 'column3'}, (err, data) -> - data.should.eql 'column1,column3\nval11,val13\nval21,val23\n' unless err - next err - - describe 'nested columns', -> - - it 'and nested properties', (next) -> - stringify [ - { field1: {nested: 'val11'}, field2: 'val12', field3: 'val13' } - { field1: {}, field2: 'val22', field3: 'val23' } - ], header: true, columns: {'field1.nested': 'column1', field3: 'column3'}, (err, data) -> - data.should.eql 'column1,column3\nval11,val13\n,val23\n' unless err - next err - - it 'also work for nested properties', (next) -> - stringify [ - { field1: {nested: 'val11'}, field2: 'val12', field3: 'val13' } - { field1: {}, field2: 'val22', field3: 'val23' } - ], header: true, columns: {'field1.nested': 'column1', field3: 'column3'}, (err, data) -> - data.should.eql 'column1,column3\nval11,val13\n,val23\n' unless err - next err diff --git a/packages/csv-stringify/test/option.header.ts b/packages/csv-stringify/test/option.header.ts new file mode 100644 index 000000000..296d07dcc --- /dev/null +++ b/packages/csv-stringify/test/option.header.ts @@ -0,0 +1,270 @@ +import "should"; +import dedent from "dedent"; +import { stringify } from "../lib/index.js"; +import { stringify as stringifySync } from "../lib/sync.js"; + +describe("Option `header`", function () { + it('as "true" and without "column" option with objects', function (next) { + stringify( + [ + { field1: "val11", field2: "val12", field3: "val13" }, + { field1: "val21", field2: "val22", field3: "val23" }, + ], + { + header: true, + }, + (err, data) => { + if (err) return next(err); + data.should.eql( + dedent` + field1,field2,field3 + val11,val12,val13 + val21,val22,val23 + ` + "\n", + ); + next(); + }, + ); + }); + + it("must get columns from somewhere", function (next) { + stringify( + [ + ["h1", "h2", "h3"], + ["1", "2", "3"], + ["4", "5", "6"], + ], + { + header: true, + }, + (err) => { + if (!err) return next(Error("Invalid assessment")); + err.message.should.eql( + "Undiscoverable Columns: header option requires column option or object records", + ); + next(); + }, + ); + }); + + it("is immutable", function (next) { + const options = { header: true, quotedEmpty: true, delimiter: "|" }; + const data1 = [ + { a: "1", b: "2", c: "3" }, + { a: "4", b: "5", c: "6" }, + ]; + const data2 = [ + { x: "1", y: "2", z: "3" }, + { x: "4", y: "5", z: "6" }, + ]; + stringify(data1, options, (err, result1) => { + stringify(data2, options, (err, result2) => { + if (!err) { + result1.should.eql("a|b|c\n1|2|3\n4|5|6\n"); + result2.should.eql("x|y|z\n1|2|3\n4|5|6\n"); + } + next(err); + }); + }); + }); + + describe("event", function () { + it("emit header", function (next) { + let count = 0; + let data = ""; + const stringifier = stringify({ + columns: ["col1", "col2"], + header: true, + }); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + stringifier.on("record", () => { + count++; + }); + stringifier.on("finish", () => { + count.should.eql(2); + data.should.eql("col1,col2\nfoo1,goo1\nfoo2,goo2\n"); + next(); + }); + stringifier.write({ col1: "foo1", col2: "goo1" }); + stringifier.write({ col1: "foo2", col2: "goo2" }); + stringifier.end(); + }); + + it("emit header even without a source", function (next) { + let data = ""; + const stringifier = stringify({ + columns: ["col1", "col2"], + header: true, + }); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + stringifier.on("end", () => { + data.should.eql("col1,col2\n"); + next(); + }); + stringifier.end(); + }); + }); + + describe("without records", function () { + it("print headers if no records to parse", function (next) { + stringify( + [], + { + header: true, + columns: ["some", "headers"], + }, + (err, data) => { + data.should.eql("some,headers\n"); + next(); + }, + ); + }); + + it("print headers if no records to parse in sync mode, fix #343", function () { + const data = stringifySync([], { + header: true, + columns: ["some", "headers"], + }); + data.should.eql("some,headers\n"); + }); + + it("not print headers if no records to parse and no header option", function (next) { + stringify( + [], + { + header: false, + columns: ["some", "headers"], + }, + (err, data) => { + data.should.eql(""); + next(); + }, + ); + }); + }); + + describe("with column", function () { + it("filter records array properties not listed as columns", function (next) { + stringify( + [ + [20322051544, 1979, "ABC", 45], + [28392898392, 1974, "DEF", 23], + ], + { + header: true, + columns: ["a", "b"], + eof: false, + }, + (err, data) => { + if (!err) { + data.should.eql( + dedent` + a,b + 20322051544,1979 + 28392898392,1974 + `, + ); + } + next(err); + }, + ); + }); + + it("filter records object properties not listed as columns", function (next) { + stringify( + [ + { a: 20322051544, b: "1979", c: "8.8017226E7" }, + { a: 28392898392, b: "1974", c: "8.8392926E7" }, + ], + { + header: true, + columns: ["a", "c"], + eof: false, + }, + (err, data) => { + data.should.eql( + dedent` + a,c + 20322051544,8.8017226E7 + 28392898392,8.8392926E7 + `, + ); + next(); + }, + ); + }); + + it("map the column property name to display name", function (next) { + stringify( + [ + { field1: "val11", field2: "val12", field3: "val13" }, + { field1: "val21", field2: "val22", field3: "val23" }, + ], + { + header: true, + columns: { field1: "column1", field3: "column3" }, + }, + (err, data) => { + if (!err) { + data.should.eql( + dedent` + column1,column3\nval11,val13\nval21,val23 + ` + "\n", + ); + } + next(err); + }, + ); + }); + }); + + describe("nested columns", function () { + it("and nested properties", function (next) { + stringify( + [ + { field1: { nested: "val11" }, field2: "val12", field3: "val13" }, + { field1: {}, field2: "val22", field3: "val23" }, + ], + { + header: true, + columns: { "field1.nested": "column1", field3: "column3" }, + }, + (err, data) => { + if (!err) { + data.should.eql("column1,column3\nval11,val13\n,val23\n"); + } + next(err); + }, + ); + }); + + it("also work for nested properties", function (next) { + stringify( + [ + { field1: { nested: "val11" }, field2: "val12", field3: "val13" }, + { field1: {}, field2: "val22", field3: "val23" }, + ], + { + header: true, + columns: { "field1.nested": "column1", field3: "column3" }, + }, + (err, data) => { + if (!err) { + data.should.eql("column1,column3\nval11,val13\n,val23\n"); + } + next(err); + }, + ); + }); + }); +}); diff --git a/packages/csv-stringify/test/option.quote.coffee b/packages/csv-stringify/test/option.quote.coffee deleted file mode 100644 index 575265fc9..000000000 --- a/packages/csv-stringify/test/option.quote.coffee +++ /dev/null @@ -1,137 +0,0 @@ - -import { stringify } from '../lib/index.js' - -describe 'Option `quote`', -> - - it 'default', (next) -> - stringifier = stringify [], -> - stringifier.options.quote.should.eql('"') - next() - - it 'validation', -> - stringify [], quote: '' - stringify [], quote: '"' - stringify [], quote: '||' - stringify [], quote: Buffer.from '"' - stringify [], quote: true - stringify [], quote: false - ( -> - stringify [], quote: 123 - ).should.throw 'option `quote` must be a boolean, a buffer or a string, got 123' - - it 'disabled if empty', (next) -> - stringify [ - [ '20322051544','"','8.8017226E7',45,'"ok"' ] - [ '','1974','8.8392926E7','','' ] - ], {eof: false, quote: ''}, (err, data) -> - data.should.eql """ - 20322051544,",8.8017226E7,45,"ok" - ,1974,8.8392926E7,, - """ - next() - - it 'custom value with quoted', (next) -> - stringify [ - [ 'a','','b' ] - [ '','c','' ] - ], eof: false, quote: '|', quoted: true, (err, data) -> - data.should.eql """ - |a|,,|b| - ,|c|, - """ - next() - - it 'fields with separator inside fields', (next) -> - stringify [ - [ '20322051544','1979.0','8.8017226E7','ABC,45','2000-01-01' ] - [ '28392898392','1974.0','8.8392926E7','DEF','23','2050-11-27' ] - ], eof: false, (err, data) -> - data.should.eql """ - 20322051544,1979.0,8.8017226E7,"ABC,45",2000-01-01 - 28392898392,1974.0,8.8392926E7,DEF,23,2050-11-27 - """ - next() - - it 'fields containing delimiters', (next) -> - stringify [ - [ '20322051544',',1979.0,8.8017226E7,ABC,45,2000-01-01' ] - [ '28392898392','1974.0','8.8392926E7','DEF','23','2050-11-27' ] - [ '28392898392,1974.0','8.8392926E7','DEF,23,2050-11-27,' ] - ], eof: false, (err, data) -> - data.should.eql """ - 20322051544,",1979.0,8.8017226E7,ABC,45,2000-01-01" - 28392898392,1974.0,8.8392926E7,DEF,23,2050-11-27 - "28392898392,1974.0",8.8392926E7,"DEF,23,2050-11-27," - """ - next() - - it 'fields containing quotes', (next) -> - stringify [ - [ '20322051544','1979.0','8.801"7226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974.0','8.8392926E7','DEF','2"3','2050-11-27' ] - ], eof: false, (err, data) -> - data.should.eql """ - 20322051544,1979.0,"8.801""7226E7",ABC,45,2000-01-01 - 28392898392,1974.0,8.8392926E7,DEF,"2""3",2050-11-27 - """ - next() - - it 'empty fields', (next) -> - stringify [ - [ '20322051544','','8.8017226E7','45','' ] - [ '','1974','8.8392926E7','','' ] - ], eof: false, (err, data) -> - data.should.eql """ - 20322051544,,8.8017226E7,45, - ,1974,8.8392926E7,, - """ - next() - - it 'fields containing quotes and double quotes escape', (next) -> - stringify [ - [ '20322051544','"','8.8017226E7',45,'"ok"' ] - [ '','1974','8.8392926E7','','' ] - ], eof: false, (err, data) -> - data.should.eql """ - 20322051544,\"\"\"\",8.8017226E7,45,\"\"\"ok\"\"\" - ,1974,8.8392926E7,, - """ - next() - - it 'fields with line breaks inside quotes', (next) -> - stringify [ - [ '20322051544','\n',',8.8017226E7',45,'\nok\n' ] - [ '\n','1974','8.8392926E7','','\n' ] - ], eof: false, (err, data) -> - data.should.eql """ - 20322051544," - ",",8.8017226E7",45," - ok - " - " - ",1974,8.8392926E7,," - " - """ - next() - - it 'field where quote string is empty', (next) -> - stringify [ - [ '20322051544','"','8.8017226E7',45,'"ok"' ] - [ '','1974','8.8392926E7','','' ] - ], {eof: false, quote: ''}, (err, data) -> - data.should.eql """ - 20322051544,",8.8017226E7,45,"ok" - ,1974,8.8392926E7,, - """ - next() - - it 'fields with linebreaks and different record delimiter', (next) -> - stringify [ - [ '123\n456', 789] - [ '','1974' ] - ], {eof: false, record_delimiter: '__'}, (err, data) -> - data.should.eql """ - 123 - 456,789__,1974 - """ - next() diff --git a/packages/csv-stringify/test/option.quote.js b/packages/csv-stringify/test/option.quote.js new file mode 100644 index 000000000..dde617a74 --- /dev/null +++ b/packages/csv-stringify/test/option.quote.js @@ -0,0 +1,12 @@ +import "should"; +import { stringify } from "../lib/index.js"; + +describe("Option `quote`", function () { + it("validation", function () { + (() => { + stringify([], { quote: 123 }); + }).should.throw( + "option `quote` must be a boolean, a buffer or a string, got 123", + ); + }); +}); diff --git a/packages/csv-stringify/test/option.quote.ts b/packages/csv-stringify/test/option.quote.ts new file mode 100644 index 000000000..851b31501 --- /dev/null +++ b/packages/csv-stringify/test/option.quote.ts @@ -0,0 +1,228 @@ +import "should"; +import dedent from "dedent"; +import { stringify } from "../lib/index.js"; + +describe("Option `quote`", function () { + it("default", function (next) { + const stringifier = stringify([], () => { + stringifier.options.quote.should.eql('"'); + next(); + }); + }); + + it("validation", function () { + stringify([], { quote: "" }); + stringify([], { quote: '"' }); + stringify([], { quote: "||" }); + stringify([], { quote: Buffer.from('"') }); + stringify([], { quote: true }); + stringify([], { quote: false }); + }); + + it("disabled if empty", function (next) { + stringify( + [ + ["20322051544", '"', "8.8017226E7", 45, '"ok"'], + ["", "1974", "8.8392926E7", "", ""], + ], + { + eof: false, + quote: "", + }, + (err, data) => { + data.should.eql( + dedent` + 20322051544,",8.8017226E7,45,"ok" + ,1974,8.8392926E7,, + `, + ); + next(); + }, + ); + }); + + it("custom value with quoted", function (next) { + stringify( + [ + ["a", "", "b"], + ["", "c", ""], + ], + { + eof: false, + quote: "|", + quoted: true, + }, + (err, data) => { + data.should.eql("|a|,,|b|\n,|c|,"); + next(); + }, + ); + }); + + it("fields with separator inside fields", function (next) { + stringify( + [ + ["20322051544", "1979.0", "8.8017226E7", "ABC,45", "2000-01-01"], + ["28392898392", "1974.0", "8.8392926E7", "DEF", "23", "2050-11-27"], + ], + { + eof: false, + }, + (err, data) => { + data.should.eql( + dedent` + 20322051544,1979.0,8.8017226E7,"ABC,45",2000-01-01 + 28392898392,1974.0,8.8392926E7,DEF,23,2050-11-27 + `, + ); + next(); + }, + ); + }); + + it("fields containing delimiters", function (next) { + stringify( + [ + ["20322051544", ",1979.0,8.8017226E7,ABC,45,2000-01-01"], + ["28392898392", "1974.0", "8.8392926E7", "DEF", "23", "2050-11-27"], + ["28392898392,1974.0", "8.8392926E7", "DEF,23,2050-11-27,"], + ], + { + eof: false, + }, + (err, data) => { + data.should.eql( + dedent` + 20322051544,",1979.0,8.8017226E7,ABC,45,2000-01-01" + 28392898392,1974.0,8.8392926E7,DEF,23,2050-11-27\n"28392898392,1974.0",8.8392926E7,"DEF,23,2050-11-27," + `, + ); + next(); + }, + ); + }); + + it("fields containing quotes", function (next) { + stringify( + [ + ["20322051544", "1979.0", '8.801"7226E7', "ABC", "45", "2000-01-01"], + ["28392898392", "1974.0", "8.8392926E7", "DEF", '2"3', "2050-11-27"], + ], + { + eof: false, + }, + (err, data) => { + data.should.eql( + dedent` + 20322051544,1979.0,"8.801""7226E7",ABC,45,2000-01-01 + 28392898392,1974.0,8.8392926E7,DEF,"2""3",2050-11-27 + `, + ); + next(); + }, + ); + }); + + it("empty fields", function (next) { + stringify( + [ + ["20322051544", "", "8.8017226E7", "45", ""], + ["", "1974", "8.8392926E7", "", ""], + ], + { + eof: false, + }, + (err, data) => { + data.should.eql(dedent` + 20322051544,,8.8017226E7,45, + ,1974,8.8392926E7,, + `); + next(); + }, + ); + }); + + it("fields containing quotes and double quotes escape", function (next) { + stringify( + [ + ["20322051544", '"', "8.8017226E7", 45, '"ok"'], + ["", "1974", "8.8392926E7", "", ""], + ], + { + eof: false, + }, + (err, data) => { + data.should.eql( + dedent` + 20322051544,"""",8.8017226E7,45,"""ok""" + ,1974,8.8392926E7,, + `, + ); + next(); + }, + ); + }); + + it("fields with line breaks inside quotes", function (next) { + stringify( + [ + ["20322051544", "\n", ",8.8017226E7", 45, "\nok\n"], + ["\n", "1974", "8.8392926E7", "", "\n"], + ], + { + eof: false, + }, + (err, data) => { + data.should.eql( + dedent` + 20322051544,"\n",",8.8017226E7",45,"\nok\n" + "\n",1974,8.8392926E7,,"\n" + `, + ); + next(); + }, + ); + }); + + it("field where quote string is empty", function (next) { + stringify( + [ + ["20322051544", '"', "8.8017226E7", 45, '"ok"'], + ["", "1974", "8.8392926E7", "", ""], + ], + { + eof: false, + quote: "", + }, + (err, data) => { + data.should.eql( + dedent` + 20322051544,",8.8017226E7,45,"ok" + ,1974,8.8392926E7,, + `, + ); + next(); + }, + ); + }); + + it("fields with linebreaks and different record delimiter", function (next) { + stringify( + [ + ["123\n456", 789], + ["", "1974"], + ], + { + eof: false, + record_delimiter: "__", + }, + (err, data) => { + data.should.eql(dedent` + 123 + 456,789__,1974 + `); + next(); + }, + ); + }); +}); diff --git a/packages/csv-stringify/test/option.quoted.coffee b/packages/csv-stringify/test/option.quoted.coffee deleted file mode 100644 index a4b8b4ed4..000000000 --- a/packages/csv-stringify/test/option.quoted.coffee +++ /dev/null @@ -1,49 +0,0 @@ - -import { stringify } from '../lib/index.js' - -describe 'Option `quoted`', -> - - it 'surround fields', (next) -> - count = 0 - data = '' - stringifier = stringify quoted: true, eof: false - stringifier.on 'readable', -> - while(d = stringifier.read()) - data += d - stringifier.on 'record', (record, index) -> - count++ - stringifier.on 'finish', -> - count.should.eql 2 - data.should.eql """ - "20322051544","1979.0","8.801""7226E7","ABC" - "283928""98392","1974.0","8.8392926E7","DEF" - """ - next() - stringifier.write [ '20322051544','1979.0','8.801"7226E7','ABC' ] - stringifier.write [ '283928"98392','1974.0','8.8392926E7','DEF' ] - stringifier.end() - - it 'is executed after cast and apply to numbers', (next) -> - stringify [ - [10.1] - ], - delimiter: ';' - cast: number: (value) -> - value.toString().replace '.', ',' - quoted_match: ',' - , (err, data) -> - data.should.eql '"10,1"\n' unless err - next err - - it 'local option in cast overwriting global', (next) -> - stringify [ - ['10.1', '10.2'] - ], - delimiter: ';' - cast: string: (value, {index}) -> - value: value.replace '.', ',' - quoted_match: if index is 0 then ',' else null - quoted_match: ',' - , (err, data) -> - data.should.eql '"10,1";10,2\n' unless err - next err diff --git a/packages/csv-stringify/test/option.quoted.ts b/packages/csv-stringify/test/option.quoted.ts new file mode 100644 index 000000000..1358c0c79 --- /dev/null +++ b/packages/csv-stringify/test/option.quoted.ts @@ -0,0 +1,72 @@ +import "should"; +import dedent from "dedent"; +import { stringify } from "../lib/index.js"; + +describe("Option `quoted`", function () { + it("surround fields", function (next) { + let count = 0; + let data = ""; + const stringifier = stringify({ quoted: true, eof: false }); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + stringifier.on("record", () => { + count++; + }); + stringifier.on("finish", () => { + count.should.eql(2); + data.should.eql( + dedent` + "20322051544","1979.0","8.801""7226E7","ABC" + "283928""98392","1974.0","8.8392926E7","DEF" + `, + ); + next(); + }); + stringifier.write(["20322051544", "1979.0", '8.801"7226E7', "ABC"]); + stringifier.write(['283928"98392', "1974.0", "8.8392926E7", "DEF"]); + stringifier.end(); + }); + + it("is executed after cast and apply to numbers", function (next) { + stringify( + [[10.1]], + { + delimiter: ";", + cast: { + number: (value) => { + return value.toString().replace(".", ","); + }, + }, + quoted_match: ",", + }, + (err, data) => { + if (!err) data.should.eql('"10,1"\n'); + next(err); + }, + ); + }); + + it("local option in cast overwriting global", function (next) { + stringify( + [["10.1", "10.2"]], + { + delimiter: ";", + cast: { + string: (value, { index }) => ({ + value: value.replace(".", ","), + quoted_match: index === 0 ? "," : null, + }), + }, + quoted_match: ",", + }, + (err, data) => { + if (!err) data.should.eql('"10,1";10,2\n'); + next(err); + }, + ); + }); +}); diff --git a/packages/csv-stringify/test/option.quoted_empty.coffee b/packages/csv-stringify/test/option.quoted_empty.coffee deleted file mode 100644 index d019acbcb..000000000 --- a/packages/csv-stringify/test/option.quoted_empty.coffee +++ /dev/null @@ -1,76 +0,0 @@ - -import { stringify } from '../lib/index.js' - -describe 'Option `quoted_empty`', -> - - it 'quotes empty fields (when all not quoted)', (next) -> - count = 0 - data = '' - stringifier = stringify quoted: false, quoted_empty: true, eof: false - stringifier.on 'readable', -> - while(d = stringifier.read()) - data += d - stringifier.on 'record', (record, index) -> - count++ - stringifier.on 'finish', -> - count.should.eql 1 - data.should.eql """ - "","","", ,0,"" - """ - next() - stringifier.write [ undefined,null,'',' ',0,false ] - stringifier.end() - - it 'quotes empty fields (when strings quoted)', (next) -> - count = 0 - data = '' - stringifier = stringify quoted_empty: true, quoted_string: true, eof: false - stringifier.on 'readable', -> - while(d = stringifier.read()) - data += d - stringifier.on 'record', (record, index) -> - count++ - stringifier.on 'finish', -> - count.should.eql 1 - data.should.eql """ - "","",""," ",0,"" - """ - next() - stringifier.write [ undefined,null,'',' ',0,false ] - stringifier.end() - - it 'prevents quoting empty fields (when strings quoted)', (next) -> - count = 0 - data = '' - stringifier = stringify quoted_empty: false, quoted_string: true, eof: false - stringifier.on 'readable', -> - while(d = stringifier.read()) - data += d - stringifier.on 'record', (record, index) -> - count++ - stringifier.on 'finish', -> - count.should.eql 1 - data.should.eql """ - ,,," ",0, - """ - next() - stringifier.write [ undefined,null,'',' ',0,false ] - stringifier.end() - - it 'quotes empty fields (when all quoted)', (next) -> - count = 0 - data = '' - stringifier = stringify quoted: true, quoted_empty: true, eof: false - stringifier.on 'readable', -> - while(d = stringifier.read()) - data += d - stringifier.on 'record', (record, index) -> - count++ - stringifier.on 'finish', -> - count.should.eql 1 - data.should.eql """ - "","",""," ","0","" - """ - next() - stringifier.write [ undefined,null,'',' ',0,false ] - stringifier.end() diff --git a/packages/csv-stringify/test/option.quoted_empty.ts b/packages/csv-stringify/test/option.quoted_empty.ts new file mode 100644 index 000000000..46647b397 --- /dev/null +++ b/packages/csv-stringify/test/option.quoted_empty.ts @@ -0,0 +1,108 @@ +import "should"; +import { stringify } from "../lib/index.js"; + +describe("Option `quoted_empty`", function () { + it("quotes empty fields (when all not quoted)", function (next) { + let count = 0; + let data = ""; + const stringifier = stringify({ + quoted: false, + quoted_empty: true, + eof: false, + }); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + stringifier.on("record", () => { + count++; + }); + stringifier.on("finish", () => { + count.should.eql(1); + data.should.eql('"","","", ,0,""'); + next(); + }); + stringifier.write([undefined, null, "", " ", 0, false]); + stringifier.end(); + }); + + it("quotes empty fields (when strings quoted)", function (next) { + let count = 0; + let data = ""; + const stringifier = stringify({ + quoted_empty: true, + quoted_string: true, + eof: false, + }); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + stringifier.on("record", () => { + count++; + }); + stringifier.on("finish", () => { + count.should.eql(1); + data.should.eql('"","",""," ",0,""'); + next(); + }); + stringifier.write([undefined, null, "", " ", 0, false]); + stringifier.end(); + }); + + it("prevents quoting empty fields (when strings quoted)", function (next) { + let count = 0; + let data = ""; + const stringifier = stringify({ + quoted_empty: false, + quoted_string: true, + eof: false, + }); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + stringifier.on("record", () => { + count++; + }); + stringifier.on("finish", () => { + count.should.eql(1); + data.should.eql(',,," ",0,'); + next(); + }); + stringifier.write([undefined, null, "", " ", 0, false]); + stringifier.end(); + }); + + it("quotes empty fields (when all quoted)", function (next) { + let count = 0; + let data = ""; + const stringifier = stringify({ + quoted: true, + quoted_empty: true, + eof: false, + }); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + stringifier.on("record", () => { + count++; + }); + stringifier.on("finish", () => { + count.should.eql(1); + data.should.eql('"","",""," ","0",""'); + next(); + }); + stringifier.write([undefined, null, "", " ", 0, false]); + stringifier.end(); + }); +}); diff --git a/packages/csv-stringify/test/option.quoted_match.coffee b/packages/csv-stringify/test/option.quoted_match.coffee deleted file mode 100644 index dd4e7d3fc..000000000 --- a/packages/csv-stringify/test/option.quoted_match.coffee +++ /dev/null @@ -1,99 +0,0 @@ - -import { stringify } from '../lib/index.js' - -describe 'Option `quoted_match`', -> - - it 'default to `null`', (next) -> - stringifier = stringify [ - ['abc', 'def'] - ], -> - should(stringifier.options.quoted_match).be.null() - next() - - it 'a string', (next) -> - count = 0 - data = '' - stringify [ - ['abc', 'def'] - ], quoted_match: 'e', eof: false, (err, data) -> - data.should.eql ''' - abc,"def" - ''' unless err - next err - - it 'a regex', (next) -> - count = 0 - data = '' - stringify [ - ['abcd', 'efg'] - ], quoted_match: /^\w{3}$/, eof: false, (err, data) -> - data.should.eql ''' - abcd,"efg" - ''' unless err - next err - - it 'an array', (next) -> - count = 0 - data = '' - stringify [ - ['ab', 'cd', 'efg'] - ], quoted_match: ['d', /^\w{3}$/], eof: false, (err, data) -> - data.should.eql ''' - ab,"cd","efg" - ''' unless err - next err - - it 'an empty string regex with no other "quoted" options (#344)', (next) -> - count = 0 - data = '' - stringify [ - ['a', null, undefined, '', 'b'] - ], quoted_match: /^$/, eof: false, (err, data) -> - data.should.eql ''' - a,,,"",b - ''' unless err - next err - - it 'an empty string regex with all other "quoted" options set to false (#344)', (next) -> - count = 0 - data = '' - stringify [ - ['a', null, undefined, '', 'b'] - ], quoted: false, quoted_empty: false, quoted_string: false, quoted_match: /^$/, eof: false, (err, data) -> - data.should.eql ''' - a,,,"",b - ''' unless err - next err - - it 'an empty string regex has higher priority than the "quoted" option', (next) -> - count = 0 - data = '' - stringify [ - ['a', null, undefined, '', 'b'] - ], quoted: true, quoted_match: /^$/, eof: false, (err, data) -> - data.should.eql ''' - "a",,,"","b" - ''' unless err - next err - - it "an empty string regex does not conflict with quoted_string set to true", (next) -> - count = 0 - data = '' - stringify [ - ['a', null, undefined, '', 'b'] - ], quoted_string: true, quoted_match: /^$/, eof: false, (err, data) -> - data.should.eql ''' - "a",,,"","b" - ''' unless err - next err - - it "an empty string regex does not conflict with quoted_empty set to true", (next) -> - count = 0 - data = '' - stringify [ - ['a', null, undefined, '' , 'b'] - ], quoted_empty: true, quoted_match: /^$/, eof: false, (err, data) -> - data.should.eql ''' - a,"","","",b - ''' unless err - next err diff --git a/packages/csv-stringify/test/option.quoted_match.ts b/packages/csv-stringify/test/option.quoted_match.ts new file mode 100644 index 000000000..6609199fc --- /dev/null +++ b/packages/csv-stringify/test/option.quoted_match.ts @@ -0,0 +1,122 @@ +import "should"; +import should from "should"; +import { stringify } from "../lib/index.js"; + +describe("Option `quoted_match`", function () { + it("default to `null`", function (next) { + const stringifier = stringify([["abc", "def"]], () => { + should(stringifier.options.quoted_match).be.null(); + next(); + }); + }); + + it("a string", function (next) { + stringify( + [["abc", "def"]], + { quoted_match: "e", eof: false }, + (err, data) => { + if (!err) { + data.should.eql('abc,"def"'); + } + next(err); + }, + ); + }); + + it("a regex", function (next) { + stringify( + [["abcd", "efg"]], + { quoted_match: /^\w{3}$/, eof: false }, + (err, data) => { + if (!err) { + data.should.eql('abcd,"efg"'); + } + next(err); + }, + ); + }); + + it("an array", function (next) { + stringify( + [["ab", "cd", "efg"]], + { quoted_match: ["d", /^\w{3}$/], eof: false }, + (err, data) => { + if (!err) { + data.should.eql('ab,"cd","efg"'); + } + next(err); + }, + ); + }); + + it('an empty string regex with no other "quoted" options (#344)', function (next) { + stringify( + [["a", null, undefined, "", "b"]], + { quoted_match: /^$/, eof: false }, + (err, data) => { + if (!err) { + data.should.eql('a,,,"",b'); + } + next(err); + }, + ); + }); + + it('an empty string regex with all other "quoted" options set to false (#344)', function (next) { + stringify( + [["a", null, undefined, "", "b"]], + { + quoted: false, + quoted_empty: false, + quoted_string: false, + quoted_match: /^$/, + eof: false, + }, + (err, data) => { + if (!err) { + data.should.eql('a,,,"",b'); + } + next(err); + }, + ); + }); + + it('an empty string regex has higher priority than the "quoted" option', function (next) { + stringify( + [["a", null, undefined, "", "b"]], + { quoted: true, quoted_match: /^$/, eof: false }, + (err, data) => { + if (!err) { + data.should.eql('"a",,,"","b"'); + } + next(err); + }, + ); + }); + + it("an empty string regex does not conflict with quoted_string set to true", function (next) { + stringify( + [["a", null, undefined, "", "b"]], + { quoted_string: true, quoted_match: /^$/, eof: false }, + (err, data) => { + if (!err) { + data.should.eql('"a",,,"","b"'); + } + next(err); + }, + ); + }); + + it("an empty string regex does not conflict with quoted_empty set to true", function (next) { + stringify( + [["a", null, undefined, "", "b"]], + { quoted_empty: true, quoted_match: /^$/, eof: false }, + (err, data) => { + if (!err) { + data.should.eql('a,"","","",b'); + } + next(err); + }, + ); + }); +}); diff --git a/packages/csv-stringify/test/option.quoted_string.coffee b/packages/csv-stringify/test/option.quoted_string.coffee deleted file mode 100644 index 99343a7e3..000000000 --- a/packages/csv-stringify/test/option.quoted_string.coffee +++ /dev/null @@ -1,34 +0,0 @@ - -import { stringify } from '../lib/index.js' - -describe 'Option `quoted_string`', -> - - it 'quotes string fields', (next) -> - stringify [ - [ undefined,null,'',' ','x',0,false ] - ], - quoted_string: true - eof: false - , (err, data) -> - data.toString().should.eql """ - ,,""," ","x",0, - """ unless err - next err - - it 'quotes empty string fields (when all quoted)', (next) -> - count = 0 - data = '' - stringifier = stringify quoted: true, quoted_string: true, eof: false - stringifier.on 'readable', -> - while(d = stringifier.read()) - data += d - stringifier.on 'record', (record, index) -> - count++ - stringifier.on 'finish', -> - count.should.eql 1 - data.should.eql """ - ,,""," ","x","0", - """ - next() - stringifier.write [ undefined,null,'',' ','x',0,false ] - stringifier.end() diff --git a/packages/csv-stringify/test/option.quoted_string.ts b/packages/csv-stringify/test/option.quoted_string.ts new file mode 100644 index 000000000..f3ee7ca75 --- /dev/null +++ b/packages/csv-stringify/test/option.quoted_string.ts @@ -0,0 +1,45 @@ +import "should"; +import { stringify } from "../lib/index.js"; + +describe("Option `quoted_string`", function () { + it("quotes string fields", function (next) { + stringify( + [[undefined, null, "", " ", "x", 0, false]], + { + quoted_string: true, + eof: false, + }, + (err, data) => { + if (err) return next(err); + data.toString().should.eql(',,""," ","x",0,'); + next(); + }, + ); + }); + + it("quotes empty string fields (when all quoted)", function (next) { + let count = 0; + let data = ""; + const stringifier = stringify({ + quoted: true, + quoted_string: true, + eof: false, + }); + stringifier.on("readable", () => { + let d; + while ((d = stringifier.read())) { + data += d; + } + }); + stringifier.on("record", () => { + count++; + }); + stringifier.on("finish", () => { + count.should.eql(1); + data.should.eql(',,""," ","x","0",'); + next(); + }); + stringifier.write([undefined, null, "", " ", "x", 0, false]); + stringifier.end(); + }); +}); diff --git a/packages/csv-stringify/test/option.record_delimiter.coffee b/packages/csv-stringify/test/option.record_delimiter.coffee deleted file mode 100644 index c6b302a95..000000000 --- a/packages/csv-stringify/test/option.record_delimiter.coffee +++ /dev/null @@ -1,82 +0,0 @@ - -import { stringify } from '../lib/index.js' - -describe 'Option `record_delimiter`', -> - - it 'validation', -> - stringify [], record_delimiter: '' - stringify [], record_delimiter: ',' - stringify [], record_delimiter: ',,' - stringify [], record_delimiter: Buffer.from ',' - ( -> - stringify [], record_delimiter: true - ).should.throw 'Invalid Option: record_delimiter must be a buffer or a string, got true' - ( -> - stringify [], record_delimiter: false - ).should.throw 'Invalid Option: record_delimiter must be a buffer or a string, got false' - ( -> - stringify [], record_delimiter: 123 - ).should.throw 'Invalid Option: record_delimiter must be a buffer or a string, got 123' - - it 'Test line breaks custom string', (next) -> - stringify [ - [ '20322051544','8.8017226E7','ABC' ] - [ '28392898392','8.8392926E7','DEF' ] - ], record_delimiter: '::', (err, result) -> - return next err if err - result.should.eql '20322051544,8.8017226E7,ABC::28392898392,8.8392926E7,DEF::' - next() - - it 'Test line breaks custom buffer', (next) -> - stringify [ - [ '20322051544','8.8017226E7','ABC' ] - [ '28392898392','8.8392926E7','DEF' ] - ], record_delimiter: Buffer.from('::'), (err, result) -> - return next err if err - result.should.eql '20322051544,8.8017226E7,ABC::28392898392,8.8392926E7,DEF::' - next() - - it 'Test line breaks unix', (next) -> - stringify [ - [ '20322051544','8.8017226E7','ABC' ] - [ '28392898392','8.8392926E7','DEF' ] - ], record_delimiter: 'unix', (err, result) -> - return next err if err - result.should.eql '20322051544,8.8017226E7,ABC\n28392898392,8.8392926E7,DEF\n' - next() - - it 'Test line breaks unicode', (next) -> - stringify [ - [ '20322051544','8.8017226E7','ABC' ] - [ '28392898392','8.8392926E7','DEF' ] - ], record_delimiter: 'unicode', (err, result) -> - return next err if err - result.should.eql '20322051544,8.8017226E7,ABC\u202828392898392,8.8392926E7,DEF\u2028' - next() - - it 'Test line breaks mac', (next) -> - stringify [ - [ '20322051544','8.8017226E7','ABC' ] - [ '28392898392','8.8392926E7','DEF' ] - ], record_delimiter: 'mac', (err, result) -> - return next err if err - result.should.eql '20322051544,8.8017226E7,ABC\r28392898392,8.8392926E7,DEF\r' - next() - - it 'Test line breaks windows', (next) -> - stringify [ - [ '20322051544','8.8017226E7','ABC' ] - [ '28392898392','8.8392926E7','DEF' ] - ], record_delimiter: 'windows', (err, result) -> - return next err if err - result.should.eql '20322051544,8.8017226E7,ABC\r\n28392898392,8.8392926E7,DEF\r\n' - next() - - it 'Test line breaks ascii', (next) -> - stringify [ - [ '20322051544','8.8017226E7','ABC' ] - [ '28392898392','8.8392926E7','DEF' ] - ], record_delimiter: 'ascii', delimiter: '\u001f', (err, result) -> - return next err if err - result.should.eql '20322051544\u001f8.8017226E7\u001fABC\u001e28392898392\u001f8.8392926E7\u001fDEF\u001e' - next() diff --git a/packages/csv-stringify/test/option.record_delimiter.js b/packages/csv-stringify/test/option.record_delimiter.js new file mode 100644 index 000000000..86b745829 --- /dev/null +++ b/packages/csv-stringify/test/option.record_delimiter.js @@ -0,0 +1,21 @@ +import { stringify } from "../lib/index.js"; + +describe("Option `record_delimiter`", function () { + it("validation", function () { + (() => { + stringify([], { record_delimiter: true }); + }).should.throw( + "Invalid Option: record_delimiter must be a buffer or a string, got true", + ); + (() => { + stringify([], { record_delimiter: false }); + }).should.throw( + "Invalid Option: record_delimiter must be a buffer or a string, got false", + ); + (() => { + stringify([], { record_delimiter: 123 }); + }).should.throw( + "Invalid Option: record_delimiter must be a buffer or a string, got 123", + ); + }); +}); diff --git a/packages/csv-stringify/test/option.record_delimiter.ts b/packages/csv-stringify/test/option.record_delimiter.ts new file mode 100644 index 000000000..d8b539822 --- /dev/null +++ b/packages/csv-stringify/test/option.record_delimiter.ts @@ -0,0 +1,129 @@ +import { stringify } from "../lib/index.js"; + +describe("Option `record_delimiter`", function () { + it("validation", function () { + stringify([], { record_delimiter: "" }); + stringify([], { record_delimiter: "," }); + stringify([], { record_delimiter: ",," }); + stringify([], { record_delimiter: Buffer.from(",") }); + }); + + it("Test line breaks custom string", function (next) { + stringify( + [ + ["20322051544", "8.8017226E7", "ABC"], + ["28392898392", "8.8392926E7", "DEF"], + ], + { record_delimiter: "::" }, + (err, result) => { + if (err) return next(err); + result.should.eql( + "20322051544,8.8017226E7,ABC::28392898392,8.8392926E7,DEF::", + ); + next(); + }, + ); + }); + + it("Test line breaks custom buffer", function (next) { + stringify( + [ + ["20322051544", "8.8017226E7", "ABC"], + ["28392898392", "8.8392926E7", "DEF"], + ], + { record_delimiter: Buffer.from("::") }, + (err, result) => { + if (err) return next(err); + result.should.eql( + "20322051544,8.8017226E7,ABC::28392898392,8.8392926E7,DEF::", + ); + next(); + }, + ); + }); + + it("Test line breaks unix", function (next) { + stringify( + [ + ["20322051544", "8.8017226E7", "ABC"], + ["28392898392", "8.8392926E7", "DEF"], + ], + { record_delimiter: "unix" }, + (err, result) => { + if (err) return next(err); + result.should.eql( + "20322051544,8.8017226E7,ABC\n28392898392,8.8392926E7,DEF\n", + ); + next(); + }, + ); + }); + + it("Test line breaks unicode", function (next) { + stringify( + [ + ["20322051544", "8.8017226E7", "ABC"], + ["28392898392", "8.8392926E7", "DEF"], + ], + { record_delimiter: "unicode" }, + (err, result) => { + if (err) return next(err); + result.should.eql( + "20322051544,8.8017226E7,ABC\u202828392898392,8.8392926E7,DEF\u2028", + ); + next(); + }, + ); + }); + + it("Test line breaks mac", function (next) { + stringify( + [ + ["20322051544", "8.8017226E7", "ABC"], + ["28392898392", "8.8392926E7", "DEF"], + ], + { record_delimiter: "mac" }, + (err, result) => { + if (err) return next(err); + result.should.eql( + "20322051544,8.8017226E7,ABC\r28392898392,8.8392926E7,DEF\r", + ); + next(); + }, + ); + }); + + it("Test line breaks windows", function (next) { + stringify( + [ + ["20322051544", "8.8017226E7", "ABC"], + ["28392898392", "8.8392926E7", "DEF"], + ], + { record_delimiter: "windows" }, + (err, result) => { + if (err) return next(err); + result.should.eql( + "20322051544,8.8017226E7,ABC\r\n28392898392,8.8392926E7,DEF\r\n", + ); + next(); + }, + ); + }); + + it("Test line breaks ascii", function (next) { + stringify( + [ + ["20322051544", "8.8017226E7", "ABC"], + ["28392898392", "8.8392926E7", "DEF"], + ], + { record_delimiter: "ascii", delimiter: "\u001f" }, + (err, result) => { + if (err) return next(err); + result.should.eql( + "20322051544\u001f8.8017226E7\u001fABC\u001e28392898392\u001f8.8392926E7\u001fDEF\u001e", + ); + next(); + }, + ); + }); +}); diff --git a/packages/csv-stringify/test/options.coffee b/packages/csv-stringify/test/options.coffee deleted file mode 100644 index a0910ca60..000000000 --- a/packages/csv-stringify/test/options.coffee +++ /dev/null @@ -1,9 +0,0 @@ - -import { stringify } from '../lib/index.js' - -describe 'Options', -> - - it 'underscore options', -> - stringifier = stringify recordDelimiter: ':' - stringifier.options.record_delimiter.should.eql ':' - (stringifier.options.recordDelimiter is undefined).should.be.true() diff --git a/packages/csv-stringify/test/options.js b/packages/csv-stringify/test/options.js new file mode 100644 index 000000000..f0e9eac1b --- /dev/null +++ b/packages/csv-stringify/test/options.js @@ -0,0 +1,9 @@ +import { stringify } from "../lib/index.js"; + +describe("Options", function () { + it("underscore options", function () { + const stringifier = stringify({ recordDelimiter: ":" }); + stringifier.options.record_delimiter.should.eql(":"); + (stringifier.options.recordDelimiter === undefined).should.be.true(); + }); +}); diff --git a/packages/csv-stringify/test/samples.coffee b/packages/csv-stringify/test/samples.coffee deleted file mode 100644 index 500e7525f..000000000 --- a/packages/csv-stringify/test/samples.coffee +++ /dev/null @@ -1,30 +0,0 @@ - -import fs from 'node:fs/promises' -import path from 'node:path' -import { spawn } from 'node:child_process' - -__dirname = new URL( '.', import.meta.url).pathname -dir = path.resolve __dirname, '../samples' -samples = await fs.readdir dir - -describe 'Samples', -> - - samples - .filter (sample) -> - return false unless /\.(js|ts)?$/.test sample - true - .map (sample) -> - - it "Sample #{sample}", () -> - data = await fs.readFile path.resolve(dir, sample), 'utf8' - return if /^["|']skip test["|']/.test data - new Promise (resolve, reject) -> - ext = /\.(\w+)?$/.exec(sample)[0] - [cmd, ...args] = switch ext - when '.js' - ['node', path.resolve dir, sample] - when '.ts' - ['node', '--loader', 'ts-node/esm', path.resolve dir, sample] - spawn(cmd, args) - .on 'close', (code) -> if code is 0 then resolve() else reject(new Error 'Failure') - .stdout.on 'data', (->) diff --git a/packages/csv-stringify/test/samples.js b/packages/csv-stringify/test/samples.js new file mode 100644 index 000000000..5919a5514 --- /dev/null +++ b/packages/csv-stringify/test/samples.js @@ -0,0 +1,44 @@ +import fs from "node:fs/promises"; +import path from "node:path"; +import { spawn } from "node:child_process"; + +const __dirname = new URL(".", import.meta.url).pathname; +const dir = path.resolve(__dirname, "../samples"); +const samples = await fs.readdir(dir); + +describe("Samples", function () { + /* eslint mocha/no-setup-in-describe: "off" */ + samples + .filter((sample) => { + if (!/\.(js|ts)?$/.test(sample)) return false; + return true; + }) + .map((sample) => { + it(`Sample ${sample}`, async function () { + const data = await fs.readFile(path.resolve(dir, sample), "utf8"); + if (/^["|']skip test["|']/.test(data)) return; + return new Promise((resolve, reject) => { + const ext = /\.(\w+)?$/.exec(sample)[0]; + let cmd, args; + switch (ext) { + case ".js": + [cmd, ...args] = ["node", path.resolve(dir, sample)]; + break; + case ".ts": + [cmd, ...args] = [ + "node", + "--loader", + "ts-node/esm", + path.resolve(dir, sample), + ]; + break; + } + spawn(cmd, args) + .on("close", (code) => + code === 0 ? resolve() : reject(new Error("Failure")), + ) + .stdout.on("data", () => {}); + }); + }); + }); +}); diff --git a/packages/csv-stringify/test/types.js b/packages/csv-stringify/test/types.js new file mode 100644 index 000000000..ead04c9e7 --- /dev/null +++ b/packages/csv-stringify/test/types.js @@ -0,0 +1,27 @@ +import { stringify } from "../lib/index.js"; + +describe("types", function () { + describe("defaults", function () { + it("should map date to getTime", function (next) { + const date = new Date(); + stringify([{ value: date }], (err, data) => { + if (!err) data.should.eql(date.getTime() + "\n"); + next(err); + }); + }); + + it("should map true boolean value to 1", function (next) { + stringify([{ value: true }], (err, data) => { + if (!err) data.should.eql("1\n"); + next(err); + }); + }); + + it("should map object to its json representation", function (next) { + stringify([{ value: { a: 1 } }], (err, data) => { + if (!err) data.should.eql('"{""a"":1}"\n'); + next(err); + }); + }); + }); +}); diff --git a/packages/csv-stringify/tsconfig.json b/packages/csv-stringify/tsconfig.json index 4db508a7c..5da38148b 100644 --- a/packages/csv-stringify/tsconfig.json +++ b/packages/csv-stringify/tsconfig.json @@ -4,6 +4,6 @@ "esModuleInterop": true, "module": "ES2020", "moduleResolution": "node", - "strict": true, + "strict": true } } diff --git a/packages/csv/CHANGELOG.md b/packages/csv/CHANGELOG.md index 643fc6c62..fd910b4b9 100644 --- a/packages/csv/CHANGELOG.md +++ b/packages/csv/CHANGELOG.md @@ -3,6 +3,45 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [6.4.1](https://github.com/adaltas/node-csv/compare/csv@6.3.11...csv@6.4.1) (2025-07-16) + +**Note:** Version bump only for package csv + +## 6.4.0 (2025-07-10) + +### Features + +- add unicode chars to formula escape ([#387](https://github.com/adaltas/node-csv/issues/387)) ([1fc177c](https://github.com/adaltas/node-csv/commit/1fc177c605e8a88e403539806890695a6ba72dec)) +- backport support for node 14 ([dbfeb78](https://github.com/adaltas/node-csv/commit/dbfeb78f61ed36f02936d63a53345708ca213e45)) +- backward support for node 8 ([496231d](https://github.com/adaltas/node-csv/commit/496231dfd838f0a6a72269a5a2390a4c637cef95)) +- esm migration ([b5c0d4b](https://github.com/adaltas/node-csv/commit/b5c0d4b191c8b57397808c0922a3f08248506a9f)) +- export ts types in sync ([890bf8d](https://github.com/adaltas/node-csv/commit/890bf8d950c18a05cab5e35a461d0847d9425156)) +- replace ts types with typesVersions ([acb41d5](https://github.com/adaltas/node-csv/commit/acb41d5031669f2d582e40da1c80f5fd4738fee4)) +- ts module Node16 and type declaration to exports field ([#341](https://github.com/adaltas/node-csv/issues/341)) ([4b0283d](https://github.com/adaltas/node-csv/commit/4b0283d17b7fa46daa1f87380759ba72c71ec79b)) +- wg stream api ([8a5eb7d](https://github.com/adaltas/node-csv/commit/8a5eb7dfd31b22217db4fbbc832d707221850785)) + +### Bug Fixes + +- commonjs types, run tsc and lint to validate changes ([#397](https://github.com/adaltas/node-csv/issues/397)) ([e6870fe](https://github.com/adaltas/node-csv/commit/e6870fe272c119e273196522c9771d12ff8b2a35)) +- correct exports in package.json with webpack ([154eafb](https://github.com/adaltas/node-csv/commit/154eafbac866eb4499a0d392f8dcd057695c2586)) +- **csv-demo-ts-cjs-node16:** upgrade module definition after latest typescript ([87fe919](https://github.com/adaltas/node-csv/commit/87fe91996fb2a8895c252177fca4f0cb59a518f9)) +- **csv-demo-webpack-ts:** simplify export paths ([8d63a14](https://github.com/adaltas/node-csv/commit/8d63a14313bb6b26f13fafb740cc686f1dfaa65f)) +- **csv-generate:** finish called twice in node 16 ([3decdf1](https://github.com/adaltas/node-csv/commit/3decdf169ce3b8e0c5cadd257816c346c8e4d3fa)) +- **csv-stringify:** bom and header in sync mode with no records (fix [#343](https://github.com/adaltas/node-csv/issues/343)) ([bff158f](https://github.com/adaltas/node-csv/commit/bff158fbc9001b2cf7177ecd0f16dc97edac55f2)) +- **csv-stringify:** node 12 compatibility in flush ([9145b75](https://github.com/adaltas/node-csv/commit/9145b75012ec71a0b4152036af2275bf28c460e0)) +- **csv-stringify:** quote_match with empty string pattern quotes empty strings ([#345](https://github.com/adaltas/node-csv/issues/345)) ([1c22d2e](https://github.com/adaltas/node-csv/commit/1c22d2e07f66dd747150b5a7499b5ebd5bc0f25c)), closes [#344](https://github.com/adaltas/node-csv/issues/344) +- **csv:** export csv_sync ([1353284](https://github.com/adaltas/node-csv/commit/1353284aa02bb9f4f727d2653e398a869eebe20d)) +- **csv:** fixed CJS types under modern `modernResolution` options ([#388](https://github.com/adaltas/node-csv/issues/388)) ([54d03e4](https://github.com/adaltas/node-csv/commit/54d03e4779033ef7d574dffa98a7c3ce93da345d)) +- **csv:** remove ts files in cjs dist ([d0d1089](https://github.com/adaltas/node-csv/commit/d0d1089c3ef9053c9adb9a9747ce11d5ea5cfe49)) +- dont insert polyfills in cjs [#303](https://github.com/adaltas/node-csv/issues/303) ([9baf334](https://github.com/adaltas/node-csv/commit/9baf334044dab90b4a0d096a7e456d0fd5807d5b)) +- esm exports in package.json files ([c48fe47](https://github.com/adaltas/node-csv/commit/c48fe478ced7560aa078fbc36ec33d6007111e2b)), closes [#308](https://github.com/adaltas/node-csv/issues/308) +- export original lib esm modules ([be25349](https://github.com/adaltas/node-csv/commit/be2534928ba21156e9cde1e15d2e8593d62ffe71)) +- expose browser esm modules ([eb87355](https://github.com/adaltas/node-csv/commit/eb873557c65912f065d2581d30a17a96b0bfd2d6)) +- fallback to setTimeout is setImmediate is undefined ([3d6a2d0](https://github.com/adaltas/node-csv/commit/3d6a2d0a655af342f28456b46db7ccfe7ee9d664)) +- refer to esm files in dist ([b780fbd](https://github.com/adaltas/node-csv/commit/b780fbd26f5e54494e511eb2e004d3cdedee3593)) +- remove samples from publicatgion ([12c221d](https://github.com/adaltas/node-csv/commit/12c221dc37add26f094e3bb7f94b50ee06ff5be6)) +- uncaught errors with large stream chunks (fix [#386](https://github.com/adaltas/node-csv/issues/386)) ([1d500ed](https://github.com/adaltas/node-csv/commit/1d500edf38ba06fc80409974e08c37c6a40f27a1)) + ## [6.3.11](https://github.com/adaltas/node-csv/compare/csv@6.3.10...csv@6.3.11) (2024-11-21) **Note:** Version bump only for package csv diff --git a/packages/csv/dist/cjs/index.cjs b/packages/csv/dist/cjs/index.cjs index c3947d6e8..d4aa04a42 100644 --- a/packages/csv/dist/cjs/index.cjs +++ b/packages/csv/dist/cjs/index.cjs @@ -579,7 +579,7 @@ const normalize_options$1 = function (opts) { ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -1111,7 +1111,7 @@ const normalize_options$1 = function (opts) { // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -1130,7 +1130,7 @@ const normalize_options$1 = function (opts) { // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -1261,10 +1261,14 @@ const transform$1 = function (original_options = {}) { this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options$1({ + const options = normalize_options$1({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -2007,10 +2011,14 @@ const transform$1 = function (original_options = {}) { if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -2402,6 +2410,7 @@ const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv/dist/cjs/index.d.cts b/packages/csv/dist/cjs/index.d.cts index c9770f8df..9dc9a1ee7 100644 --- a/packages/csv/dist/cjs/index.d.cts +++ b/packages/csv/dist/cjs/index.d.cts @@ -1,14 +1,13 @@ - // Alias to the modules exposing the stream and callback APIs -import { generate } from 'csv-generate'; -import { parse } from 'csv-parse'; -import { transform } from 'stream-transform'; -import { stringify } from 'csv-stringify'; +import { generate } from "csv-generate"; +import { parse } from "csv-parse"; +import { transform } from "stream-transform"; +import { stringify } from "csv-stringify"; export { generate, parse, transform, stringify }; -export * as generator from 'csv-generate'; -export * as parser from 'csv-parse'; -export * as transformer from 'stream-transform'; -export * as stringifier from 'csv-stringify'; +export * as generator from "csv-generate"; +export * as parser from "csv-parse"; +export * as transformer from "stream-transform"; +export * as stringifier from "csv-stringify"; diff --git a/packages/csv/dist/cjs/sync.cjs b/packages/csv/dist/cjs/sync.cjs index 527f8b588..b762dc8ef 100644 --- a/packages/csv/dist/cjs/sync.cjs +++ b/packages/csv/dist/cjs/sync.cjs @@ -577,7 +577,7 @@ const normalize_options$1 = function (opts) { ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -1109,7 +1109,7 @@ const normalize_options$1 = function (opts) { // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -1128,7 +1128,7 @@ const normalize_options$1 = function (opts) { // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -1259,10 +1259,14 @@ const transform$1 = function (original_options = {}) { this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options$1({ + const options = normalize_options$1({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -2005,10 +2009,14 @@ const transform$1 = function (original_options = {}) { if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -2062,10 +2070,13 @@ const parse = function (data, opts = {}) { } }; const close = () => {}; - const err1 = parser.parse(data, false, push, close); - if (err1 !== undefined) throw err1; - const err2 = parser.parse(undefined, true, push, close); - if (err2 !== undefined) throw err2; + const error = parser.parse(data, true, push, close); + if (error !== undefined) throw error; + // 250606: `parser.parse` was implemented as 2 calls: + // const err1 = parser.parse(data, false, push, close); + // if (err1 !== undefined) throw err1; + // const err2 = parser.parse(undefined, true, push, close); + // if (err2 !== undefined) throw err2; return records; }; @@ -2094,6 +2105,7 @@ const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv/dist/cjs/sync.d.cts b/packages/csv/dist/cjs/sync.d.cts index b1812592d..8bdf6763f 100644 --- a/packages/csv/dist/cjs/sync.d.cts +++ b/packages/csv/dist/cjs/sync.d.cts @@ -1,14 +1,13 @@ - // Alias to the modules exposing the sync APIs -import { generate } from 'csv-generate/sync' -import { parse } from 'csv-parse/sync'; -import { transform } from 'stream-transform/sync'; -import { stringify } from 'csv-stringify/sync'; +import { generate } from "csv-generate/sync"; +import { parse } from "csv-parse/sync"; +import { transform } from "stream-transform/sync"; +import { stringify } from "csv-stringify/sync"; -export { generate, parse, transform, stringify } +export { generate, parse, transform, stringify }; -export * as generator from 'csv-generate/sync'; -export * as parser from 'csv-parse/sync'; -export * as transformer from 'stream-transform/sync'; -export * as stringifier from 'csv-stringify/sync'; +export * as generator from "csv-generate/sync"; +export * as parser from "csv-parse/sync"; +export * as transformer from "stream-transform/sync"; +export * as stringifier from "csv-stringify/sync"; diff --git a/packages/csv/dist/esm/index.d.ts b/packages/csv/dist/esm/index.d.ts index c9770f8df..9dc9a1ee7 100644 --- a/packages/csv/dist/esm/index.d.ts +++ b/packages/csv/dist/esm/index.d.ts @@ -1,14 +1,13 @@ - // Alias to the modules exposing the stream and callback APIs -import { generate } from 'csv-generate'; -import { parse } from 'csv-parse'; -import { transform } from 'stream-transform'; -import { stringify } from 'csv-stringify'; +import { generate } from "csv-generate"; +import { parse } from "csv-parse"; +import { transform } from "stream-transform"; +import { stringify } from "csv-stringify"; export { generate, parse, transform, stringify }; -export * as generator from 'csv-generate'; -export * as parser from 'csv-parse'; -export * as transformer from 'stream-transform'; -export * as stringifier from 'csv-stringify'; +export * as generator from "csv-generate"; +export * as parser from "csv-parse"; +export * as transformer from "stream-transform"; +export * as stringifier from "csv-stringify"; diff --git a/packages/csv/dist/esm/index.js b/packages/csv/dist/esm/index.js index 93a5b12ff..3c7b1f8a3 100644 --- a/packages/csv/dist/esm/index.js +++ b/packages/csv/dist/esm/index.js @@ -831,8 +831,8 @@ function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1591,7 +1591,7 @@ Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, no Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1601,7 +1601,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1614,7 +1614,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1627,7 +1627,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1642,7 +1642,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2000,7 +2000,9 @@ EventEmitter.init = function() { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2569,94 +2571,19 @@ function Item(fun, array) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; -var title = 'browser'; -var platform = 'browser'; -var browser = true; var env = {}; -var argv = []; -var version = ''; // empty string to avoid regexp issues -var versions = {}; -var release = {}; -var config = {}; - -function noop() {} - -var on = noop; -var addListener = noop; -var once = noop; -var off = noop; -var removeListener = noop; -var removeAllListeners = noop; -var emit = noop; - -function binding(name) { - throw new Error('process.binding is not supported'); -} - -function cwd () { return '/' } -function chdir (dir) { - throw new Error('process.chdir is not supported'); -}function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; -var performanceNow = - performance.now || +performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; -// generate timestamp or delta -// see http://nodejs.org/api/process.html#process_process_hrtime -function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] -} - -var startTime = new Date(); -function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; -} - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime -}; + env: env}; var inherits; if (typeof Object.create === 'function'){ @@ -5762,7 +5689,7 @@ const normalize_options$1 = function (opts) { ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -6294,7 +6221,7 @@ const normalize_options$1 = function (opts) { // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -6313,7 +6240,7 @@ const normalize_options$1 = function (opts) { // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -6444,10 +6371,14 @@ const transform$1 = function (original_options = {}) { this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options$1({ + const options = normalize_options$1({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -7190,10 +7121,14 @@ const transform$1 = function (original_options = {}) { if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -7577,6 +7512,7 @@ const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv/dist/esm/sync.d.ts b/packages/csv/dist/esm/sync.d.ts index b1812592d..8bdf6763f 100644 --- a/packages/csv/dist/esm/sync.d.ts +++ b/packages/csv/dist/esm/sync.d.ts @@ -1,14 +1,13 @@ - // Alias to the modules exposing the sync APIs -import { generate } from 'csv-generate/sync' -import { parse } from 'csv-parse/sync'; -import { transform } from 'stream-transform/sync'; -import { stringify } from 'csv-stringify/sync'; +import { generate } from "csv-generate/sync"; +import { parse } from "csv-parse/sync"; +import { transform } from "stream-transform/sync"; +import { stringify } from "csv-stringify/sync"; -export { generate, parse, transform, stringify } +export { generate, parse, transform, stringify }; -export * as generator from 'csv-generate/sync'; -export * as parser from 'csv-parse/sync'; -export * as transformer from 'stream-transform/sync'; -export * as stringifier from 'csv-stringify/sync'; +export * as generator from "csv-generate/sync"; +export * as parser from "csv-parse/sync"; +export * as transformer from "stream-transform/sync"; +export * as stringifier from "csv-stringify/sync"; diff --git a/packages/csv/dist/esm/sync.js b/packages/csv/dist/esm/sync.js index efc0e6d38..d49b9aca4 100644 --- a/packages/csv/dist/esm/sync.js +++ b/packages/csv/dist/esm/sync.js @@ -831,8 +831,8 @@ function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1591,7 +1591,7 @@ Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, no Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1601,7 +1601,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1614,7 +1614,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1627,7 +1627,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1642,7 +1642,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2000,7 +2000,9 @@ EventEmitter.init = function() { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2569,94 +2571,19 @@ function Item(fun, array) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; -var title = 'browser'; -var platform = 'browser'; -var browser = true; var env = {}; -var argv = []; -var version = ''; // empty string to avoid regexp issues -var versions = {}; -var release = {}; -var config = {}; - -function noop() {} - -var on = noop; -var addListener = noop; -var once = noop; -var off = noop; -var removeListener = noop; -var removeAllListeners = noop; -var emit = noop; - -function binding(name) { - throw new Error('process.binding is not supported'); -} - -function cwd () { return '/' } -function chdir (dir) { - throw new Error('process.chdir is not supported'); -}function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; -var performanceNow = - performance.now || +performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; -// generate timestamp or delta -// see http://nodejs.org/api/process.html#process_process_hrtime -function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] -} - -var startTime = new Date(); -function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; -} - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime -}; + env: env}; var inherits; if (typeof Object.create === 'function'){ @@ -5760,7 +5687,7 @@ const normalize_options$1 = function (opts) { ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -6292,7 +6219,7 @@ const normalize_options$1 = function (opts) { // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -6311,7 +6238,7 @@ const normalize_options$1 = function (opts) { // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -6442,10 +6369,14 @@ const transform$1 = function (original_options = {}) { this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options$1({ + const options = normalize_options$1({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -7188,10 +7119,14 @@ const transform$1 = function (original_options = {}) { if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -7245,10 +7180,13 @@ const parse = function (data, opts = {}) { } }; const close = () => {}; - const err1 = parser.parse(data, false, push, close); - if (err1 !== undefined) throw err1; - const err2 = parser.parse(undefined, true, push, close); - if (err2 !== undefined) throw err2; + const error = parser.parse(data, true, push, close); + if (error !== undefined) throw error; + // 250606: `parser.parse` was implemented as 2 calls: + // const err1 = parser.parse(data, false, push, close); + // if (err1 !== undefined) throw err1; + // const err2 = parser.parse(undefined, true, push, close); + // if (err2 !== undefined) throw err2; return records; }; @@ -7277,6 +7215,7 @@ const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv/dist/iife/index.js b/packages/csv/dist/iife/index.js index 3665e7439..c06182ad4 100644 --- a/packages/csv/dist/iife/index.js +++ b/packages/csv/dist/iife/index.js @@ -834,8 +834,8 @@ var csv = (function (exports) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1594,7 +1594,7 @@ var csv = (function (exports) { Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1604,7 +1604,7 @@ var csv = (function (exports) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1617,7 +1617,7 @@ var csv = (function (exports) { Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1630,7 +1630,7 @@ var csv = (function (exports) { Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1645,7 +1645,7 @@ var csv = (function (exports) { Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2003,7 +2003,9 @@ var csv = (function (exports) { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2572,94 +2574,19 @@ var csv = (function (exports) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ @@ -5765,7 +5692,7 @@ var csv = (function (exports) { ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -6297,7 +6224,7 @@ var csv = (function (exports) { // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -6316,7 +6243,7 @@ var csv = (function (exports) { // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -6447,10 +6374,14 @@ var csv = (function (exports) { this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options$1({ + const options = normalize_options$1({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -7193,10 +7124,14 @@ var csv = (function (exports) { if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -7580,6 +7515,7 @@ var csv = (function (exports) { const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv/dist/iife/sync.js b/packages/csv/dist/iife/sync.js index 30438d4f8..b856d5f29 100644 --- a/packages/csv/dist/iife/sync.js +++ b/packages/csv/dist/iife/sync.js @@ -834,8 +834,8 @@ var csv_sync = (function (exports) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1594,7 +1594,7 @@ var csv_sync = (function (exports) { Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1604,7 +1604,7 @@ var csv_sync = (function (exports) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1617,7 +1617,7 @@ var csv_sync = (function (exports) { Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1630,7 +1630,7 @@ var csv_sync = (function (exports) { Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1645,7 +1645,7 @@ var csv_sync = (function (exports) { Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2003,7 +2003,9 @@ var csv_sync = (function (exports) { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2572,94 +2574,19 @@ var csv_sync = (function (exports) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ @@ -5763,7 +5690,7 @@ var csv_sync = (function (exports) { ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -6295,7 +6222,7 @@ var csv_sync = (function (exports) { // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -6314,7 +6241,7 @@ var csv_sync = (function (exports) { // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -6445,10 +6372,14 @@ var csv_sync = (function (exports) { this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options$1({ + const options = normalize_options$1({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -7191,10 +7122,14 @@ var csv_sync = (function (exports) { if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -7248,10 +7183,13 @@ var csv_sync = (function (exports) { } }; const close = () => {}; - const err1 = parser.parse(data, false, push, close); - if (err1 !== undefined) throw err1; - const err2 = parser.parse(undefined, true, push, close); - if (err2 !== undefined) throw err2; + const error = parser.parse(data, true, push, close); + if (error !== undefined) throw error; + // 250606: `parser.parse` was implemented as 2 calls: + // const err1 = parser.parse(data, false, push, close); + // if (err1 !== undefined) throw err1; + // const err2 = parser.parse(undefined, true, push, close); + // if (err2 !== undefined) throw err2; return records; }; @@ -7280,6 +7218,7 @@ var csv_sync = (function (exports) { const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv/dist/umd/index.js b/packages/csv/dist/umd/index.js index f20f7f8ee..a9cc1bd73 100644 --- a/packages/csv/dist/umd/index.js +++ b/packages/csv/dist/umd/index.js @@ -837,8 +837,8 @@ byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1597,7 +1597,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1607,7 +1607,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1620,7 +1620,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1633,7 +1633,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1648,7 +1648,7 @@ Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2006,7 +2006,9 @@ this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2575,94 +2577,19 @@ Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ @@ -5768,7 +5695,7 @@ ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -6300,7 +6227,7 @@ // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -6319,7 +6246,7 @@ // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -6450,10 +6377,14 @@ this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options$1({ + const options = normalize_options$1({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -7196,10 +7127,14 @@ if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -7583,6 +7518,7 @@ const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv/dist/umd/sync.js b/packages/csv/dist/umd/sync.js index b9c23d14b..391b52b1a 100644 --- a/packages/csv/dist/umd/sync.js +++ b/packages/csv/dist/umd/sync.js @@ -837,8 +837,8 @@ byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -1597,7 +1597,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -1607,7 +1607,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1620,7 +1620,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -1633,7 +1633,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -1648,7 +1648,7 @@ Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2006,7 +2006,9 @@ this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -2575,94 +2577,19 @@ Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ @@ -5766,7 +5693,7 @@ ); } // Normalize option `columns` - options.cast_first_line_to_header = null; + options.cast_first_line_to_header = undefined; if (options.columns === true) { // Fields in the first line are converted as-is to columns options.cast_first_line_to_header = undefined; @@ -6298,7 +6225,7 @@ // Normalize option `to` if (options.to === undefined || options.to === null) { options.to = -1; - } else { + } else if (options.to !== -1) { if (typeof options.to === "string" && /\d+/.test(options.to)) { options.to = parseInt(options.to); } @@ -6317,7 +6244,7 @@ // Normalize option `to_line` if (options.to_line === undefined || options.to_line === null) { options.to_line = -1; - } else { + } else if (options.to_line !== -1) { if (typeof options.to_line === "string" && /\d+/.test(options.to_line)) { options.to_line = parseInt(options.to_line); } @@ -6448,10 +6375,14 @@ this.state.bufBytesStart += bomLength; buf = buf.slice(bomLength); // Renormalize original options with the new encoding - this.options = normalize_options$1({ + const options = normalize_options$1({ ...this.original_options, encoding: encoding, }); + // Properties are merged with the existing options instance + for (const key in options) { + this.options[key] = options[key]; + } // Options will re-evaluate the Buffer with the new encoding ({ comment, escape, quote } = this.options); break; @@ -7194,10 +7125,14 @@ if (skip_records_with_error) { this.state.recordHasError = true; if (this.options.on_skip !== undefined) { - this.options.on_skip( - err, - raw ? this.state.rawBuffer.toString(encoding) : undefined, - ); + try { + this.options.on_skip( + err, + raw ? this.state.rawBuffer.toString(encoding) : undefined, + ); + } catch (err) { + return err; + } } // this.emit('skip', err, raw ? this.state.rawBuffer.toString(encoding) : undefined); return undefined; @@ -7251,10 +7186,13 @@ } }; const close = () => {}; - const err1 = parser.parse(data, false, push, close); - if (err1 !== undefined) throw err1; - const err2 = parser.parse(undefined, true, push, close); - if (err2 !== undefined) throw err2; + const error = parser.parse(data, true, push, close); + if (error !== undefined) throw error; + // 250606: `parser.parse` was implemented as 2 calls: + // const err1 = parser.parse(data, false, push, close); + // if (err1 !== undefined) throw err1; + // const err2 = parser.parse(undefined, true, push, close); + // if (err2 !== undefined) throw err2; return records; }; @@ -7283,6 +7221,7 @@ const reIsPlainProp = /^\w*$/; const getTag = function (value) { + // if (!value) value === undefined ? "[object Undefined]" : "[object Null]"; return Object.prototype.toString.call(value); }; diff --git a/packages/csv/lib/index.d.ts b/packages/csv/lib/index.d.ts index c9770f8df..9dc9a1ee7 100644 --- a/packages/csv/lib/index.d.ts +++ b/packages/csv/lib/index.d.ts @@ -1,14 +1,13 @@ - // Alias to the modules exposing the stream and callback APIs -import { generate } from 'csv-generate'; -import { parse } from 'csv-parse'; -import { transform } from 'stream-transform'; -import { stringify } from 'csv-stringify'; +import { generate } from "csv-generate"; +import { parse } from "csv-parse"; +import { transform } from "stream-transform"; +import { stringify } from "csv-stringify"; export { generate, parse, transform, stringify }; -export * as generator from 'csv-generate'; -export * as parser from 'csv-parse'; -export * as transformer from 'stream-transform'; -export * as stringifier from 'csv-stringify'; +export * as generator from "csv-generate"; +export * as parser from "csv-parse"; +export * as transformer from "stream-transform"; +export * as stringifier from "csv-stringify"; diff --git a/packages/csv/lib/sync.d.ts b/packages/csv/lib/sync.d.ts index b1812592d..8bdf6763f 100644 --- a/packages/csv/lib/sync.d.ts +++ b/packages/csv/lib/sync.d.ts @@ -1,14 +1,13 @@ - // Alias to the modules exposing the sync APIs -import { generate } from 'csv-generate/sync' -import { parse } from 'csv-parse/sync'; -import { transform } from 'stream-transform/sync'; -import { stringify } from 'csv-stringify/sync'; +import { generate } from "csv-generate/sync"; +import { parse } from "csv-parse/sync"; +import { transform } from "stream-transform/sync"; +import { stringify } from "csv-stringify/sync"; -export { generate, parse, transform, stringify } +export { generate, parse, transform, stringify }; -export * as generator from 'csv-generate/sync'; -export * as parser from 'csv-parse/sync'; -export * as transformer from 'stream-transform/sync'; -export * as stringifier from 'csv-stringify/sync'; +export * as generator from "csv-generate/sync"; +export * as parser from "csv-parse/sync"; +export * as transformer from "stream-transform/sync"; +export * as stringifier from "csv-stringify/sync"; diff --git a/packages/csv/package.json b/packages/csv/package.json index b41fef512..471d4ed39 100644 --- a/packages/csv/package.json +++ b/packages/csv/package.json @@ -1,6 +1,6 @@ { "name": "csv", - "version": "6.3.11", + "version": "6.4.1", "description": "A mature CSV toolset with simple api, full of options and tested against large datasets.", "keywords": [ "node", @@ -23,30 +23,24 @@ "David Worms (https://www.adaltas.com)" ], "dependencies": { - "csv-generate": "^4.4.2", - "csv-parse": "^5.6.0", - "csv-stringify": "^6.5.2", - "stream-transform": "^3.3.3" + "csv-generate": "^4.5.0", + "csv-parse": "^6.1.0", + "csv-stringify": "^6.6.0", + "stream-transform": "^3.4.0" }, "devDependencies": { - "@eslint/js": "^9.15.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@types/mocha": "^10.0.9", - "@types/node": "^22.9.1", - "coffeescript": "~2.7.0", + "@rollup/plugin-node-resolve": "^16.0.1", + "@types/mocha": "^10.0.10", + "@types/node": "^22.15.30", "each": "^2.7.2", - "eslint": "^9.15.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-mocha": "^10.5.0", - "eslint-plugin-prettier": "^5.2.1", - "mocha": "~10.8.2", - "prettier": "^3.3.3", - "rollup": "^4.27.3", + "mocha": "~11.5.0", + "prettier": "^3.5.3", + "rollup": "^4.41.1", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "should": "~13.2.3", "ts-node": "^10.9.2", - "typescript": "^5.6.3" + "typescript": "^5.8.3" }, "engines": { "node": ">= 0.1.90" @@ -90,19 +84,12 @@ "main": "./dist/cjs/index.cjs", "mocha": { "inline-diffs": true, - "loader": "./test/loaders/all.js", + "loader": "ts-node/esm", "recursive": true, "reporter": "spec", - "require": [ - "should" - ], "throw-deprecation": false, "timeout": 40000 }, - "lint-staged": { - "*.js": "npm run lint:fix", - "*.md": "prettier -w" - }, "repository": { "type": "git", "url": "https://github.com/adaltas/node-csv.git", @@ -117,8 +104,8 @@ "lint:fix": "eslint --fix", "lint:ts": "tsc --noEmit true", "preversion": "npm run build && git add dist", - "test": "mocha 'test/**/*.{coffee,ts}'", - "test:legacy": "mocha --ignore test/samples.coffee --loader=./test/loaders/legacy/all.js 'test/**/*.{coffee,ts}'" + "test": "mocha 'test/**/*.{js,ts}'", + "test:legacy": "mocha --ignore test/samples.js 'test/**/*.{js,ts}'" }, "type": "module", "types": "dist/esm/index.d.ts", diff --git a/packages/csv/test/api.coffee b/packages/csv/test/api.coffee deleted file mode 100644 index f467fc7f8..000000000 --- a/packages/csv/test/api.coffee +++ /dev/null @@ -1,32 +0,0 @@ - -import {generate, parse, stringify, transform} from '../lib/index.js' - -describe 'api', -> - - it 'generate', (next) -> - generate length: 1, columns: 1, seed: 1, encoding: 'utf8', (err, data) -> - data.should.eql 'OMH' unless err - next err - - it 'parse', (next) -> - parse 'abc,def', (err, data) -> - data.should.eql [ [ 'abc', 'def' ] ] unless err - next err - - it 'stringify', (next) -> - stringify [ [ 'abc', 'def' ] ], (err, data) -> - data.should.eql 'abc,def\n' unless err - next err - - it 'transform', (next) -> - transform [ - ['abc','def'] - ], (record) -> - record.push(record.shift()) - record - , (err, output) -> - output.should.eql [ - [ 'def', 'abc' ] - ] unless err - next err - diff --git a/packages/csv/test/api.js b/packages/csv/test/api.js new file mode 100644 index 000000000..3e743dc6f --- /dev/null +++ b/packages/csv/test/api.js @@ -0,0 +1,42 @@ +import "should"; +import { generate, parse, stringify, transform } from "../lib/index.js"; + +describe("api", function () { + it("generate", function (next) { + generate( + { length: 1, columns: 1, seed: 1, encoding: "utf8" }, + (err, data) => { + if (!err) data.should.eql("OMH"); + next(err); + }, + ); + }); + + it("parse", function (next) { + parse("abc,def", (err, data) => { + if (!err) data.should.eql([["abc", "def"]]); + next(err); + }); + }); + + it("stringify", function (next) { + stringify([["abc", "def"]], (err, data) => { + if (!err) data.should.eql("abc,def\n"); + next(err); + }); + }); + + it("transform", function (next) { + transform( + [["abc", "def"]], + (record) => { + record.push(record.shift()); + return record; + }, + (err, output) => { + if (!err) output.should.eql([["def", "abc"]]); + next(err); + }, + ); + }); +}); diff --git a/packages/csv/test/api.types.sync.ts b/packages/csv/test/api.types.sync.ts index 66aefcd4d..f61e98fcc 100644 --- a/packages/csv/test/api.types.sync.ts +++ b/packages/csv/test/api.types.sync.ts @@ -1,56 +1,49 @@ +import "should"; +import csv, { generate, parse, stringify, transform } from "../lib/sync.js"; -import 'should' -import csv, {generate, parse, stringify, transform} from '../lib/sync.js' - -describe('API Types', () => { - - describe('usage', () => { - - it('generate', () => { +describe("API Types", function () { + describe("usage with named export", function () { + it("generate", function () { // with options + handler const output: string = generate(1); return output; - }) + }); - it('parse', () => { - const output: string = parse(''); + it("parse", function () { + const output: string[][] = parse(""); return output; - }) + }); - it('stringify', () => { + it("stringify", function () { const output: string = stringify([]); return output; - }) + }); - it('transform', () => { - const output: any = transform([], () => {}); + it("transform", function () { + const output: void[] = transform([], () => {}); return output; - }) - - }) + }); + }); - describe('usage', () => { - - it('csv.generate', () => { - const options: csv.generator.Options = {} + describe("usage with default export", function () { + it("csv.generate", function () { + const options: csv.generator.Options = {}; return options; - }) - - it('csv.parse', () => { - const options: csv.parser.Options = {} - return options; - }) - - it('csv.stringifier', () => { - const options: csv.stringifier.Options = {} + }); + + it("csv.parse", function () { + const options: csv.parser.Options = {}; return options; - }) - - it('csv.transform', () => { - const options: csv.transformer.Options = {} + }); + + it("csv.stringifier", function () { + const options: csv.stringifier.Options = {}; return options; - }) - - }) + }); -}) + it("csv.transform", function () { + const options: csv.transformer.Options = {}; + return options; + }); + }); +}); diff --git a/packages/csv/test/api.types.ts b/packages/csv/test/api.types.ts index 9bb15c0db..4bd4f7422 100644 --- a/packages/csv/test/api.types.ts +++ b/packages/csv/test/api.types.ts @@ -1,42 +1,54 @@ +import "should"; +import { generate, parse, parser, stringify, transform } from "../lib/index.js"; -import 'should' -import {generate, parse, parser, stringify, transform} from '../lib/index.js' - -describe('API Types', () => { - - describe('Initialisation', () => { - - it('generate', () => { +describe("API Types", function () { + describe("Initialisation", function () { + it("generate", function () { // with options + handler - generate({length: 1}, (err: Error | undefined, records: Array>) => err || records) - }) - - it('parse', () => { + generate( + { length: 1 }, + (err: Error | undefined, records: Array>) => + err || records, + ); + }); + + it("parse", function () { // With input + handler - parse('abc,def', {}, (err: parser.CsvError | undefined, records: Array>) => err?.message || records) - }) - - it('stringify', () => { + parse( + "abc,def", + {}, + (err: parser.CsvError | undefined, records: Array>) => + err?.message || records, + ); + }); + + it("stringify", function () { // With handler - stringify( (err: Error | undefined, output: string) => err || output ) - }) + stringify((err: Error | undefined, output: string) => err || output); + }); - it('transform', () => { + it("transform", function () { // With handler - const transformer = transform( record => record ) - transformer.should.be.an.Object() // Disable unused variable warning + const transformer = transform((record) => record); + transformer.should.be.an.Object(); // Disable unused variable warning // With handler + callback - transform( record => record, (err, records) => err || records ) + transform( + (record) => record, + (err, records) => err || records, + ); // With records + handler - transform( ['record'], record => record ) + transform(["record"], (record) => record); // With options + handler - transform( {consume: true}, record => record ) + transform({ consume: true }, (record) => record); // With records + options + handler - transform( ['record'], {consume: true}, record => record ) + transform(["record"], { consume: true }, (record) => record); // With records + options + handler + callback - transform( ['record'], {consume: true}, record => record, (err, records) => err || records ) - }) - - }) - -}) + transform( + ["record"], + { consume: true }, + (record) => record, + (err, records) => err || records, + ); + }); + }); +}); diff --git a/packages/csv/test/loaders/all.js b/packages/csv/test/loaders/all.js deleted file mode 100644 index 4e81c3449..000000000 --- a/packages/csv/test/loaders/all.js +++ /dev/null @@ -1,15 +0,0 @@ -import * as coffee from "./coffee.js"; -import * as ts from "ts-node/esm"; - -const coffeeRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; -const tsRegex = /\.ts$/; - -export function load(url, context, next) { - if (coffeeRegex.test(url)) { - return coffee.load.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.load.apply(this, arguments); - } - return next(url, context, next); -} diff --git a/packages/csv/test/loaders/coffee.js b/packages/csv/test/loaders/coffee.js deleted file mode 100644 index 75b15abe0..000000000 --- a/packages/csv/test/loaders/coffee.js +++ /dev/null @@ -1,20 +0,0 @@ -import CoffeeScript from "coffeescript"; - -// See https://github.com/nodejs/node/issues/36396 -const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; - -export async function load(url, context, next) { - if (extensionsRegex.test(url)) { - const format = "module"; - const { source: rawSource } = await next(url, { format }); - const source = CoffeeScript.compile(rawSource.toString(), { - bare: true, - inlineMap: true, - filename: url, - header: false, - sourceMap: false, - }); - return { format, source }; - } - return next(url, context); -} diff --git a/packages/csv/test/loaders/legacy/all.js b/packages/csv/test/loaders/legacy/all.js deleted file mode 100644 index f5e57e542..000000000 --- a/packages/csv/test/loaders/legacy/all.js +++ /dev/null @@ -1,36 +0,0 @@ -import * as coffee from "./coffee.js"; -import * as ts from "ts-node/esm"; - -const coffeeRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; -const tsRegex = /\.ts$/; - -export function resolve(specifier) { - if (coffeeRegex.test(specifier)) { - return coffee.resolve.apply(this, arguments); - } - if (tsRegex.test(specifier)) { - return ts.resolve.apply(this, arguments); - } - return ts.resolve.apply(this, arguments); -} - -export function getFormat(url) { - if (coffeeRegex.test(url)) { - return coffee.getFormat.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.getFormat.apply(this, arguments); - } - return ts.getFormat.apply(this, arguments); -} - -export function transformSource(source, context) { - const { url } = context; - if (coffeeRegex.test(url)) { - return coffee.transformSource.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.transformSource.apply(this, arguments); - } - return ts.transformSource.apply(this, arguments); -} diff --git a/packages/csv/test/loaders/legacy/coffee.js b/packages/csv/test/loaders/legacy/coffee.js deleted file mode 100644 index 6a9975db9..000000000 --- a/packages/csv/test/loaders/legacy/coffee.js +++ /dev/null @@ -1,50 +0,0 @@ -// coffeescript-loader.mjs -import { URL, pathToFileURL } from "url"; -import CoffeeScript from "coffeescript"; -import { cwd } from "process"; - -const baseURL = pathToFileURL(`${cwd()}/`).href; - -// CoffeeScript files end in .coffee, .litcoffee or .coffee.md. -const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; - -export function resolve(specifier, context, defaultResolve) { - const { parentURL = baseURL } = context; - // Node.js normally errors on unknown file extensions, so return a URL for - // specifiers ending in the CoffeeScript file extensions. - if (extensionsRegex.test(specifier)) { - return { - url: new URL(specifier, parentURL).href, - stop: true, - }; - } - // Let Node.js handle all other specifiers. - return defaultResolve(specifier, context, defaultResolve); -} - -export function getFormat(url, context, defaultGetFormat) { - // Now that we patched resolve to let CoffeeScript URLs through, we need to - // tell Node.js what format such URLs should be interpreted as. For the - // purposes of this loader, all CoffeeScript URLs are ES modules. - if (extensionsRegex.test(url)) { - return { - format: "module", - stop: true, - }; - } - // Let Node.js handle all other URLs. - return defaultGetFormat(url, context, defaultGetFormat); -} - -export function transformSource(source, context, defaultTransformSource) { - const { url } = context; - - if (extensionsRegex.test(url)) { - return { - source: CoffeeScript.compile(String(source), { bare: true }), - }; - } - - // Let Node.js handle all other sources. - return defaultTransformSource(source, context, defaultTransformSource); -} diff --git a/packages/csv/test/samples.coffee b/packages/csv/test/samples.coffee deleted file mode 100644 index 500e7525f..000000000 --- a/packages/csv/test/samples.coffee +++ /dev/null @@ -1,30 +0,0 @@ - -import fs from 'node:fs/promises' -import path from 'node:path' -import { spawn } from 'node:child_process' - -__dirname = new URL( '.', import.meta.url).pathname -dir = path.resolve __dirname, '../samples' -samples = await fs.readdir dir - -describe 'Samples', -> - - samples - .filter (sample) -> - return false unless /\.(js|ts)?$/.test sample - true - .map (sample) -> - - it "Sample #{sample}", () -> - data = await fs.readFile path.resolve(dir, sample), 'utf8' - return if /^["|']skip test["|']/.test data - new Promise (resolve, reject) -> - ext = /\.(\w+)?$/.exec(sample)[0] - [cmd, ...args] = switch ext - when '.js' - ['node', path.resolve dir, sample] - when '.ts' - ['node', '--loader', 'ts-node/esm', path.resolve dir, sample] - spawn(cmd, args) - .on 'close', (code) -> if code is 0 then resolve() else reject(new Error 'Failure') - .stdout.on 'data', (->) diff --git a/packages/csv/test/samples.js b/packages/csv/test/samples.js new file mode 100644 index 000000000..5919a5514 --- /dev/null +++ b/packages/csv/test/samples.js @@ -0,0 +1,44 @@ +import fs from "node:fs/promises"; +import path from "node:path"; +import { spawn } from "node:child_process"; + +const __dirname = new URL(".", import.meta.url).pathname; +const dir = path.resolve(__dirname, "../samples"); +const samples = await fs.readdir(dir); + +describe("Samples", function () { + /* eslint mocha/no-setup-in-describe: "off" */ + samples + .filter((sample) => { + if (!/\.(js|ts)?$/.test(sample)) return false; + return true; + }) + .map((sample) => { + it(`Sample ${sample}`, async function () { + const data = await fs.readFile(path.resolve(dir, sample), "utf8"); + if (/^["|']skip test["|']/.test(data)) return; + return new Promise((resolve, reject) => { + const ext = /\.(\w+)?$/.exec(sample)[0]; + let cmd, args; + switch (ext) { + case ".js": + [cmd, ...args] = ["node", path.resolve(dir, sample)]; + break; + case ".ts": + [cmd, ...args] = [ + "node", + "--loader", + "ts-node/esm", + path.resolve(dir, sample), + ]; + break; + } + spawn(cmd, args) + .on("close", (code) => + code === 0 ? resolve() : reject(new Error("Failure")), + ) + .stdout.on("data", () => {}); + }); + }); + }); +}); diff --git a/packages/csv/test/sync.coffee b/packages/csv/test/sync.coffee deleted file mode 100644 index 7122fe231..000000000 --- a/packages/csv/test/sync.coffee +++ /dev/null @@ -1,25 +0,0 @@ - -import {generate, parse, transform, stringify} from '../lib/sync.js' - -describe 'api sync', -> - - it 'generate', -> - generate length: 1, columns: 1, seed: 1, objectMode: true - .should.eql [ [ 'OMH' ] ] - - it 'parse', -> - parse 'abc,def' - .should.eql [ [ 'abc', 'def' ] ] - - it 'transform', -> - transform [ - [ 'abc', 'def' ] - ], (record) -> - record.push record.shift() - record - .should.eql [ [ 'def', 'abc' ] ] - - it 'stringify', -> - stringify [ [ 'abc', 'def' ] ] - .should.eql 'abc,def\n' - diff --git a/packages/csv/test/sync.js b/packages/csv/test/sync.js new file mode 100644 index 000000000..6f3ad8077 --- /dev/null +++ b/packages/csv/test/sync.js @@ -0,0 +1,25 @@ +import "should"; +import { generate, parse, transform, stringify } from "../lib/sync.js"; + +describe("api sync", function () { + it("generate", function () { + generate({ length: 1, columns: 1, seed: 1, objectMode: true }).should.eql([ + ["OMH"], + ]); + }); + + it("parse", function () { + parse("abc,def").should.eql([["abc", "def"]]); + }); + + it("transform", function () { + transform([["abc", "def"]], (record) => { + record.push(record.shift()); + return record; + }).should.eql([["def", "abc"]]); + }); + + it("stringify", function () { + stringify([["abc", "def"]]).should.eql("abc,def\n"); + }); +}); diff --git a/packages/stream-transform/CHANGELOG.md b/packages/stream-transform/CHANGELOG.md index 89ca86deb..7a750552e 100644 --- a/packages/stream-transform/CHANGELOG.md +++ b/packages/stream-transform/CHANGELOG.md @@ -3,6 +3,41 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 3.4.0 (2025-07-10) + +### Features + +- backport support for node 14 ([dbfeb78](https://github.com/adaltas/node-csv/commit/dbfeb78f61ed36f02936d63a53345708ca213e45)) +- backward support for node 8 ([496231d](https://github.com/adaltas/node-csv/commit/496231dfd838f0a6a72269a5a2390a4c637cef95)) +- esm migration ([b5c0d4b](https://github.com/adaltas/node-csv/commit/b5c0d4b191c8b57397808c0922a3f08248506a9f)) +- export ts types in sync ([890bf8d](https://github.com/adaltas/node-csv/commit/890bf8d950c18a05cab5e35a461d0847d9425156)) +- replace ts types with typesVersions ([acb41d5](https://github.com/adaltas/node-csv/commit/acb41d5031669f2d582e40da1c80f5fd4738fee4)) +- **stream-transform:** handler promise support ([df337ec](https://github.com/adaltas/node-csv/commit/df337ec44cfd9a4536641ca7e2f0f5c1404ea74d)) +- **stream-transform:** ts extends options with stream.TransformOptions ([eb64b12](https://github.com/adaltas/node-csv/commit/eb64b12774e8371cb1043a0c4a33ed9dc73a1c50)) +- ts module Node16 and type declaration to exports field ([#341](https://github.com/adaltas/node-csv/issues/341)) ([4b0283d](https://github.com/adaltas/node-csv/commit/4b0283d17b7fa46daa1f87380759ba72c71ec79b)) +- wg stream api ([8a5eb7d](https://github.com/adaltas/node-csv/commit/8a5eb7dfd31b22217db4fbbc832d707221850785)) + +### Bug Fixes + +- commonjs types, run tsc and lint to validate changes ([#397](https://github.com/adaltas/node-csv/issues/397)) ([e6870fe](https://github.com/adaltas/node-csv/commit/e6870fe272c119e273196522c9771d12ff8b2a35)) +- correct exports in package.json with webpack ([154eafb](https://github.com/adaltas/node-csv/commit/154eafbac866eb4499a0d392f8dcd057695c2586)) +- **csv-demo-ts-cjs-node16:** upgrade module definition after latest typescript ([87fe919](https://github.com/adaltas/node-csv/commit/87fe91996fb2a8895c252177fca4f0cb59a518f9)) +- **csv-demo-webpack-ts:** remove polyfill ([47a99bd](https://github.com/adaltas/node-csv/commit/47a99bd944d1d943e6374227dbc4e20aaa2c8c7f)) +- **csv-demo-webpack-ts:** simplify export paths ([8d63a14](https://github.com/adaltas/node-csv/commit/8d63a14313bb6b26f13fafb740cc686f1dfaa65f)) +- **csv-generate:** finish called twice in node 16 ([3decdf1](https://github.com/adaltas/node-csv/commit/3decdf169ce3b8e0c5cadd257816c346c8e4d3fa)) +- dont insert polyfills in cjs [#303](https://github.com/adaltas/node-csv/issues/303) ([9baf334](https://github.com/adaltas/node-csv/commit/9baf334044dab90b4a0d096a7e456d0fd5807d5b)) +- esm exports in package.json files ([c48fe47](https://github.com/adaltas/node-csv/commit/c48fe478ced7560aa078fbc36ec33d6007111e2b)), closes [#308](https://github.com/adaltas/node-csv/issues/308) +- export original lib esm modules ([be25349](https://github.com/adaltas/node-csv/commit/be2534928ba21156e9cde1e15d2e8593d62ffe71)) +- expose browser esm modules ([eb87355](https://github.com/adaltas/node-csv/commit/eb873557c65912f065d2581d30a17a96b0bfd2d6)) +- fallback to setTimeout is setImmediate is undefined ([3d6a2d0](https://github.com/adaltas/node-csv/commit/3d6a2d0a655af342f28456b46db7ccfe7ee9d664)) +- refer to esm files in dist ([b780fbd](https://github.com/adaltas/node-csv/commit/b780fbd26f5e54494e511eb2e004d3cdedee3593)) +- remove samples from publicatgion ([12c221d](https://github.com/adaltas/node-csv/commit/12c221dc37add26f094e3bb7f94b50ee06ff5be6)) +- **stream-transform:** backpressure after push ([3e83f4e](https://github.com/adaltas/node-csv/commit/3e83f4e604b7b944835de18afcb41716ce4bbfad)) +- **stream-transform:** finish event call multiple times ([4f45103](https://github.com/adaltas/node-csv/commit/4f451038ef083b65d58ccee6fe3d041b106cc1cf)) +- **stream-transform:** sync callback usage in async handler ([4dd562b](https://github.com/adaltas/node-csv/commit/4dd562b65b99803b45858f449f67e52e2ef15726)) +- support ts node16 resolution in cjs ([#354](https://github.com/adaltas/node-csv/issues/354)) ([fa09d03](https://github.com/adaltas/node-csv/commit/fa09d03aaf0008b2790656871ca6b2c4be12d14c)) +- support TypeScript moduleResolution node16 ([#368](https://github.com/adaltas/node-csv/issues/368)) ([f4d7c97](https://github.com/adaltas/node-csv/commit/f4d7c97f39fb73e9d248eee21e61e7dc48015c78)) + ## [3.3.3](https://github.com/adaltas/node-csv/compare/stream-transform@3.3.2...stream-transform@3.3.3) (2024-11-21) **Note:** Version bump only for package stream-transform diff --git a/packages/stream-transform/dist/cjs/index.d.cts b/packages/stream-transform/dist/cjs/index.d.cts index 396629866..fb703dbd7 100644 --- a/packages/stream-transform/dist/cjs/index.d.cts +++ b/packages/stream-transform/dist/cjs/index.d.cts @@ -2,39 +2,59 @@ import * as stream from "stream"; -export type Handler = (record: T, callback: HandlerCallback, params?: any) => U -export type HandlerCallback = (err?: null | Error, record?: T) => void -export type Callback = (err?: null | Error, output?: string) => void +export type Handler = ( + record: T, + callback: HandlerCallback, + params?: any, +) => U; +export type HandlerCallback = (err?: null | Error, record?: T) => void; +export type Callback = (err?: null | Error, output?: string) => void; export interface Options extends stream.TransformOptions { - /** - * In the absence of a consumer, like a `stream.Readable`, trigger the consumption of the stream. - */ - consume?: boolean - /** - * The number of transformation callbacks to run in parallel; only apply with asynchronous handlers; default to "100". - */ - parallel?: number - /** - * Pass user defined parameters to the user handler as last argument. - */ - params?: any + /** + * In the absence of a consumer, like a `stream.Readable`, trigger the consumption of the stream. + */ + consume?: boolean; + /** + * The number of transformation callbacks to run in parallel; only apply with asynchronous handlers; default to "100". + */ + parallel?: number; + /** + * Pass user defined parameters to the user handler as last argument. + */ + params?: any; } export interface State { - finished: number - running: number - started: number + finished: number; + running: number; + started: number; } export class Transformer extends stream.Transform { - constructor(options: Options) - readonly options: Options - readonly state: State + constructor(options: Options); + readonly options: Options; + readonly state: State; } -declare function transform(handler: Handler, callback?: Callback): Transformer -declare function transform(records: Array, handler: Handler, callback?: Callback): Transformer -declare function transform(options: Options, handler: Handler, callback?: Callback): Transformer -declare function transform(records: Array, options: Options, handler: Handler, callback?: Callback): Transformer +declare function transform( + handler: Handler, + callback?: Callback, +): Transformer; +declare function transform( + records: Array, + handler: Handler, + callback?: Callback, +): Transformer; +declare function transform( + options: Options, + handler: Handler, + callback?: Callback, +): Transformer; +declare function transform( + records: Array, + options: Options, + handler: Handler, + callback?: Callback, +): Transformer; export default transform; -export { transform } +export { transform }; diff --git a/packages/stream-transform/dist/cjs/sync.d.cts b/packages/stream-transform/dist/cjs/sync.d.cts index 03f421701..772b9ce20 100644 --- a/packages/stream-transform/dist/cjs/sync.d.cts +++ b/packages/stream-transform/dist/cjs/sync.d.cts @@ -1,10 +1,17 @@ /// -import { Options } from './index.cjs'; +import { Options } from "./index.cjs"; -export type Handler = (record: T) => U +export type Handler = (record: T) => U; // export default transform; -export function transform(records: Array, handler: Handler): Array -export function transform(records: Array, options: Options, handler: Handler): Array +export function transform( + records: Array, + handler: Handler, +): Array; +export function transform( + records: Array, + options: Options, + handler: Handler, +): Array; export { Options }; diff --git a/packages/stream-transform/dist/esm/index.d.ts b/packages/stream-transform/dist/esm/index.d.ts index 396629866..fb703dbd7 100644 --- a/packages/stream-transform/dist/esm/index.d.ts +++ b/packages/stream-transform/dist/esm/index.d.ts @@ -2,39 +2,59 @@ import * as stream from "stream"; -export type Handler = (record: T, callback: HandlerCallback, params?: any) => U -export type HandlerCallback = (err?: null | Error, record?: T) => void -export type Callback = (err?: null | Error, output?: string) => void +export type Handler = ( + record: T, + callback: HandlerCallback, + params?: any, +) => U; +export type HandlerCallback = (err?: null | Error, record?: T) => void; +export type Callback = (err?: null | Error, output?: string) => void; export interface Options extends stream.TransformOptions { - /** - * In the absence of a consumer, like a `stream.Readable`, trigger the consumption of the stream. - */ - consume?: boolean - /** - * The number of transformation callbacks to run in parallel; only apply with asynchronous handlers; default to "100". - */ - parallel?: number - /** - * Pass user defined parameters to the user handler as last argument. - */ - params?: any + /** + * In the absence of a consumer, like a `stream.Readable`, trigger the consumption of the stream. + */ + consume?: boolean; + /** + * The number of transformation callbacks to run in parallel; only apply with asynchronous handlers; default to "100". + */ + parallel?: number; + /** + * Pass user defined parameters to the user handler as last argument. + */ + params?: any; } export interface State { - finished: number - running: number - started: number + finished: number; + running: number; + started: number; } export class Transformer extends stream.Transform { - constructor(options: Options) - readonly options: Options - readonly state: State + constructor(options: Options); + readonly options: Options; + readonly state: State; } -declare function transform(handler: Handler, callback?: Callback): Transformer -declare function transform(records: Array, handler: Handler, callback?: Callback): Transformer -declare function transform(options: Options, handler: Handler, callback?: Callback): Transformer -declare function transform(records: Array, options: Options, handler: Handler, callback?: Callback): Transformer +declare function transform( + handler: Handler, + callback?: Callback, +): Transformer; +declare function transform( + records: Array, + handler: Handler, + callback?: Callback, +): Transformer; +declare function transform( + options: Options, + handler: Handler, + callback?: Callback, +): Transformer; +declare function transform( + records: Array, + options: Options, + handler: Handler, + callback?: Callback, +): Transformer; export default transform; -export { transform } +export { transform }; diff --git a/packages/stream-transform/dist/esm/index.js b/packages/stream-transform/dist/esm/index.js index 9fa056bf9..4452b7ecf 100644 --- a/packages/stream-transform/dist/esm/index.js +++ b/packages/stream-transform/dist/esm/index.js @@ -28,7 +28,9 @@ EventEmitter.init = function() { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -1297,8 +1299,8 @@ function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -2057,7 +2059,7 @@ Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, no Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -2067,7 +2069,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2080,7 +2082,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -2093,7 +2095,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2108,7 +2110,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2569,94 +2571,19 @@ function Item(fun, array) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; -var title = 'browser'; -var platform = 'browser'; -var browser = true; var env = {}; -var argv = []; -var version = ''; // empty string to avoid regexp issues -var versions = {}; -var release = {}; -var config = {}; - -function noop() {} - -var on = noop; -var addListener = noop; -var once = noop; -var off = noop; -var removeListener = noop; -var removeAllListeners = noop; -var emit = noop; - -function binding(name) { - throw new Error('process.binding is not supported'); -} - -function cwd () { return '/' } -function chdir (dir) { - throw new Error('process.chdir is not supported'); -}function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; -var performanceNow = - performance.now || +performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; -// generate timestamp or delta -// see http://nodejs.org/api/process.html#process_process_hrtime -function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] -} - -var startTime = new Date(); -function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; -} - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime -}; + env: env}; var inherits; if (typeof Object.create === 'function'){ diff --git a/packages/stream-transform/dist/esm/sync.d.ts b/packages/stream-transform/dist/esm/sync.d.ts index 538c3e5ff..1e7bd7986 100644 --- a/packages/stream-transform/dist/esm/sync.d.ts +++ b/packages/stream-transform/dist/esm/sync.d.ts @@ -1,10 +1,17 @@ /// -import { Options } from './index.js'; +import { Options } from "./index.js"; -export type Handler = (record: T) => U +export type Handler = (record: T) => U; // export default transform; -export function transform(records: Array, handler: Handler): Array -export function transform(records: Array, options: Options, handler: Handler): Array +export function transform( + records: Array, + handler: Handler, +): Array; +export function transform( + records: Array, + options: Options, + handler: Handler, +): Array; export { Options }; diff --git a/packages/stream-transform/dist/esm/sync.js b/packages/stream-transform/dist/esm/sync.js index b16eb1094..301803a99 100644 --- a/packages/stream-transform/dist/esm/sync.js +++ b/packages/stream-transform/dist/esm/sync.js @@ -28,7 +28,9 @@ EventEmitter.init = function() { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -1297,8 +1299,8 @@ function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -2057,7 +2059,7 @@ Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, no Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -2067,7 +2069,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2080,7 +2082,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -2093,7 +2095,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2108,7 +2110,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2569,94 +2571,19 @@ function Item(fun, array) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; -var title = 'browser'; -var platform = 'browser'; -var browser = true; var env = {}; -var argv = []; -var version = ''; // empty string to avoid regexp issues -var versions = {}; -var release = {}; -var config = {}; - -function noop() {} - -var on = noop; -var addListener = noop; -var once = noop; -var off = noop; -var removeListener = noop; -var removeAllListeners = noop; -var emit = noop; - -function binding(name) { - throw new Error('process.binding is not supported'); -} - -function cwd () { return '/' } -function chdir (dir) { - throw new Error('process.chdir is not supported'); -}function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; -var performanceNow = - performance.now || +performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; -// generate timestamp or delta -// see http://nodejs.org/api/process.html#process_process_hrtime -function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] -} - -var startTime = new Date(); -function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; -} - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime -}; + env: env}; var inherits; if (typeof Object.create === 'function'){ diff --git a/packages/stream-transform/dist/iife/index.js b/packages/stream-transform/dist/iife/index.js index 4f79bdd75..8c9a04903 100644 --- a/packages/stream-transform/dist/iife/index.js +++ b/packages/stream-transform/dist/iife/index.js @@ -31,7 +31,9 @@ var stream_transform = (function (exports) { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -1300,8 +1302,8 @@ var stream_transform = (function (exports) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -2060,7 +2062,7 @@ var stream_transform = (function (exports) { Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -2070,7 +2072,7 @@ var stream_transform = (function (exports) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2083,7 +2085,7 @@ var stream_transform = (function (exports) { Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -2096,7 +2098,7 @@ var stream_transform = (function (exports) { Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2111,7 +2113,7 @@ var stream_transform = (function (exports) { Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2572,94 +2574,19 @@ var stream_transform = (function (exports) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ diff --git a/packages/stream-transform/dist/iife/sync.js b/packages/stream-transform/dist/iife/sync.js index ca4cc08c7..6aebe58a6 100644 --- a/packages/stream-transform/dist/iife/sync.js +++ b/packages/stream-transform/dist/iife/sync.js @@ -31,7 +31,9 @@ var stream_transform_sync = (function (exports) { this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -1300,8 +1302,8 @@ var stream_transform_sync = (function (exports) { byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -2060,7 +2062,7 @@ var stream_transform_sync = (function (exports) { Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -2070,7 +2072,7 @@ var stream_transform_sync = (function (exports) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2083,7 +2085,7 @@ var stream_transform_sync = (function (exports) { Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -2096,7 +2098,7 @@ var stream_transform_sync = (function (exports) { Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2111,7 +2113,7 @@ var stream_transform_sync = (function (exports) { Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2572,94 +2574,19 @@ var stream_transform_sync = (function (exports) { Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ diff --git a/packages/stream-transform/dist/umd/index.js b/packages/stream-transform/dist/umd/index.js index 3992db383..b6ee5684e 100644 --- a/packages/stream-transform/dist/umd/index.js +++ b/packages/stream-transform/dist/umd/index.js @@ -34,7 +34,9 @@ this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -1303,8 +1305,8 @@ byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -2063,7 +2065,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -2073,7 +2075,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2086,7 +2088,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -2099,7 +2101,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2114,7 +2116,7 @@ Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2575,94 +2577,19 @@ Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ diff --git a/packages/stream-transform/dist/umd/sync.js b/packages/stream-transform/dist/umd/sync.js index c5e979980..33a0957d1 100644 --- a/packages/stream-transform/dist/umd/sync.js +++ b/packages/stream-transform/dist/umd/sync.js @@ -34,7 +34,9 @@ this.domain = null; if (EventEmitter.usingDomains) { // if there is an active domain, then attach to it. - if (domain.active) ; + if (domain.active && !(this instanceof domain.Domain)) { + this.domain = domain.active; + } } if (!this._events || this._events === Object.getPrototypeOf(this)._events) { @@ -1303,8 +1305,8 @@ byteOffset = 0; } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff; - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000; + } else if (byteOffset < -2147483648) { + byteOffset = -2147483648; } byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { @@ -2063,7 +2065,7 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -128); if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); if (value < 0) value = 0xff + value + 1; this[offset] = (value & 0xff); @@ -2073,7 +2075,7 @@ Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2086,7 +2088,7 @@ Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -32768); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff); @@ -2099,7 +2101,7 @@ Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8); @@ -2114,7 +2116,7 @@ Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value; offset = offset | 0; - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -2147483648); if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24); @@ -2575,94 +2577,19 @@ Item.prototype.run = function () { this.fun.apply(null, this.array); }; - var title = 'browser'; - var platform = 'browser'; - var browser = true; var env = {}; - var argv = []; - var version = ''; // empty string to avoid regexp issues - var versions = {}; - var release = {}; - var config = {}; - - function noop() {} - - var on = noop; - var addListener = noop; - var once = noop; - var off = noop; - var removeListener = noop; - var removeAllListeners = noop; - var emit = noop; - - function binding(name) { - throw new Error('process.binding is not supported'); - } - - function cwd () { return '/' } - function chdir (dir) { - throw new Error('process.chdir is not supported'); - }function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {}; - var performanceNow = - performance.now || + performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() }; - // generate timestamp or delta - // see http://nodejs.org/api/process.html#process_process_hrtime - function hrtime(previousTimestamp){ - var clocktime = performanceNow.call(performance)*1e-3; - var seconds = Math.floor(clocktime); - var nanoseconds = Math.floor((clocktime%1)*1e9); - if (previousTimestamp) { - seconds = seconds - previousTimestamp[0]; - nanoseconds = nanoseconds - previousTimestamp[1]; - if (nanoseconds<0) { - seconds--; - nanoseconds += 1e9; - } - } - return [seconds,nanoseconds] - } - - var startTime = new Date(); - function uptime() { - var currentTime = new Date(); - var dif = currentTime - startTime; - return dif / 1000; - } - var process = { - nextTick: nextTick, - title: title, - browser: browser, - env: env, - argv: argv, - version: version, - versions: versions, - on: on, - addListener: addListener, - once: once, - off: off, - removeListener: removeListener, - removeAllListeners: removeAllListeners, - emit: emit, - binding: binding, - cwd: cwd, - chdir: chdir, - umask: umask, - hrtime: hrtime, - platform: platform, - release: release, - config: config, - uptime: uptime - }; + env: env}; var inherits; if (typeof Object.create === 'function'){ diff --git a/packages/stream-transform/lib/index.d.ts b/packages/stream-transform/lib/index.d.ts index 396629866..fb703dbd7 100644 --- a/packages/stream-transform/lib/index.d.ts +++ b/packages/stream-transform/lib/index.d.ts @@ -2,39 +2,59 @@ import * as stream from "stream"; -export type Handler = (record: T, callback: HandlerCallback, params?: any) => U -export type HandlerCallback = (err?: null | Error, record?: T) => void -export type Callback = (err?: null | Error, output?: string) => void +export type Handler = ( + record: T, + callback: HandlerCallback, + params?: any, +) => U; +export type HandlerCallback = (err?: null | Error, record?: T) => void; +export type Callback = (err?: null | Error, output?: string) => void; export interface Options extends stream.TransformOptions { - /** - * In the absence of a consumer, like a `stream.Readable`, trigger the consumption of the stream. - */ - consume?: boolean - /** - * The number of transformation callbacks to run in parallel; only apply with asynchronous handlers; default to "100". - */ - parallel?: number - /** - * Pass user defined parameters to the user handler as last argument. - */ - params?: any + /** + * In the absence of a consumer, like a `stream.Readable`, trigger the consumption of the stream. + */ + consume?: boolean; + /** + * The number of transformation callbacks to run in parallel; only apply with asynchronous handlers; default to "100". + */ + parallel?: number; + /** + * Pass user defined parameters to the user handler as last argument. + */ + params?: any; } export interface State { - finished: number - running: number - started: number + finished: number; + running: number; + started: number; } export class Transformer extends stream.Transform { - constructor(options: Options) - readonly options: Options - readonly state: State + constructor(options: Options); + readonly options: Options; + readonly state: State; } -declare function transform(handler: Handler, callback?: Callback): Transformer -declare function transform(records: Array, handler: Handler, callback?: Callback): Transformer -declare function transform(options: Options, handler: Handler, callback?: Callback): Transformer -declare function transform(records: Array, options: Options, handler: Handler, callback?: Callback): Transformer +declare function transform( + handler: Handler, + callback?: Callback, +): Transformer; +declare function transform( + records: Array, + handler: Handler, + callback?: Callback, +): Transformer; +declare function transform( + options: Options, + handler: Handler, + callback?: Callback, +): Transformer; +declare function transform( + records: Array, + options: Options, + handler: Handler, + callback?: Callback, +): Transformer; export default transform; -export { transform } +export { transform }; diff --git a/packages/stream-transform/lib/sync.d.ts b/packages/stream-transform/lib/sync.d.ts index 538c3e5ff..1e7bd7986 100644 --- a/packages/stream-transform/lib/sync.d.ts +++ b/packages/stream-transform/lib/sync.d.ts @@ -1,10 +1,17 @@ /// -import { Options } from './index.js'; +import { Options } from "./index.js"; -export type Handler = (record: T) => U +export type Handler = (record: T) => U; // export default transform; -export function transform(records: Array, handler: Handler): Array -export function transform(records: Array, options: Options, handler: Handler): Array +export function transform( + records: Array, + handler: Handler, +): Array; +export function transform( + records: Array, + options: Options, + handler: Handler, +): Array; export { Options }; diff --git a/packages/stream-transform/package.json b/packages/stream-transform/package.json index 875e0e38b..e3a068dc7 100644 --- a/packages/stream-transform/package.json +++ b/packages/stream-transform/package.json @@ -1,5 +1,5 @@ { - "version": "3.3.3", + "version": "3.4.0", "name": "stream-transform", "description": "Object transformations implementing the Node.js `stream.Transform` API", "keywords": [ @@ -12,26 +12,21 @@ ], "author": "David Worms (https://www.adaltas.com)", "devDependencies": { - "@eslint/js": "^9.15.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@types/mocha": "^10.0.9", - "@types/node": "^22.9.1", - "coffeescript": "~2.7.0", - "csv-generate": "^4.4.2", + "@rollup/plugin-node-resolve": "^16.0.1", + "@types/mocha": "^10.0.10", + "@types/node": "^22.15.30", + "csv-generate": "^4.5.0", "each": "^2.7.2", - "eslint": "^9.15.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-mocha": "^10.5.0", - "eslint-plugin-prettier": "^5.2.1", - "mocha": "~10.8.2", + "mocha": "~11.5.0", "pad": "~3.3.0", - "prettier": "^3.3.3", - "rollup": "^4.27.3", + "prettier": "^3.5.3", + "rollup": "^4.41.1", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "should": "~13.2.3", "ts-node": "^10.9.2", - "typescript": "^5.6.3" + "tsx": "^4.19.4", + "typescript": "^5.8.3" }, "exports": { ".": { @@ -72,19 +67,12 @@ "main": "./dist/cjs/index.cjs", "mocha": { "inline-diffs": true, - "loader": "./test/loaders/all.js", + "loader": "ts-node/esm", "recursive": true, "reporter": "spec", - "require": [ - "should" - ], "throw-deprecation": false, "timeout": 40000 }, - "lint-staged": { - "*.js": "npm run lint:fix", - "*.md": "prettier -w" - }, "repository": { "type": "git", "url": "https://github.com/adaltas/node-csv.git", @@ -96,10 +84,11 @@ "build:ts": "cp lib/index.d.ts dist/cjs/index.d.cts && cp lib/sync.d.ts dist/cjs/sync.d.cts && cp lib/*.ts dist/esm", "postbuild:ts": "find dist/cjs -name '*.d.cts' -exec sh -c \"sed -i \"s/\\.js'/\\.cjs'/g\" {} || sed -i '' \"s/\\.js'/\\.cjs'/g\" {}\" \\;", "lint:check": "eslint && tsc --noEmit true", - "lint:fix": "eslint --fix && tsc --noEmit true", + "lint:fix": "eslint --fix", + "lint:ts": "tsc --noEmit true", "preversion": "npm run build && git add dist", - "test": "mocha 'test/**/*.{coffee,ts}'", - "test:legacy": "mocha --loader=./test/loaders/legacy/all.js --ignore test/handler.mode.callback.coffee --ignore test/handler.mode.callback.error.coffee 'test/**/*.{coffee,ts}'" + "test": "mocha 'test/**/*.{js,ts}'", + "test:legacy": "mocha --ignore test/handler.mode.callback.js --ignore test/handler.mode.callback.error.js 'test/**/*.{js,ts}'" }, "type": "module", "types": "dist/esm/index.d.ts", diff --git a/packages/stream-transform/test/api.callback.coffee b/packages/stream-transform/test/api.callback.coffee deleted file mode 100644 index 49182dafa..000000000 --- a/packages/stream-transform/test/api.callback.coffee +++ /dev/null @@ -1,23 +0,0 @@ - -import { generate } from 'csv-generate' -import { transform } from '../lib/index.js' - -describe 'api.callback', -> - - it 'input is data', (next) -> - data = for i in [0...100] then i - transform data, ((record) -> value: record), (err, result) -> - result.length.should.eql 100 unless err - result[0].should.eql value: 0 unless err - next err - - it 'input is a readable stream', (next) -> - generate length: 1000, objectMode: true, seed: 1, columns: 2 - .pipe transform ((record) -> value: record), (err, result) -> - result.length.should.eql 1000 unless err - result[0].should.eql value: [ 'OMH', 'ONKCHhJmjadoA' ] unless err - next err - - - - diff --git a/packages/stream-transform/test/api.callback.js b/packages/stream-transform/test/api.callback.js new file mode 100644 index 000000000..999ca4bc7 --- /dev/null +++ b/packages/stream-transform/test/api.callback.js @@ -0,0 +1,44 @@ +import "should"; +import { generate } from "csv-generate"; +import { transform } from "../lib/index.js"; + +describe("api.callback", function () { + it("input is data", function (next) { + const data = Array.from({ length: 100 }, (_, i) => i); + transform( + data, + function (record) { + return { value: record }; + }, + function (err, result) { + if (!err) { + result.length.should.eql(100); + result[0].should.eql({ value: 0 }); + } + next(err); + }, + ); + }); + + it("input is a readable stream", function (next) { + generate({ + length: 1000, + objectMode: true, + seed: 1, + columns: 2, + }).pipe( + transform( + function (record) { + return { value: record }; + }, + function (err, result) { + if (!err) { + result.length.should.eql(1000); + result[0].should.eql({ value: ["OMH", "ONKCHhJmjadoA"] }); + } + next(err); + }, + ), + ); + }); +}); diff --git a/packages/stream-transform/test/api.pipe.coffee b/packages/stream-transform/test/api.pipe.coffee deleted file mode 100644 index 0139b7b34..000000000 --- a/packages/stream-transform/test/api.pipe.coffee +++ /dev/null @@ -1,69 +0,0 @@ - -import stream from 'stream' -import { generate } from 'csv-generate' -import { transform } from '../lib/index.js' - -describe 'api.pipe', -> - - describe 'source', -> - - it 'in sync mode', (next) -> - data = [] - generator = generate length: 1000, objectMode: true, seed: 1, columns: 2 - transformer = generator.pipe transform (record) -> - record.push record.shift() - record - transformer.on 'readable', -> - while(d = transformer.read()) - data.push d - transformer.on 'end', -> - data.length.should.eql 1000 - data.slice(0,2).should.eql [ - [ 'ONKCHhJmjadoA', 'OMH' ] - [ 'GeACHiN', 'D' ] - ] - next() - - it 'in async mode', (next) -> - data = [] - generator = generate length: 1000, objectMode: true, seed: 1, columns: 2 - transformer = generator.pipe transform (record, callback) -> - record.push record.shift() - callback null, record - transformer.on 'readable', -> - while(d = transformer.read()) - data.push d - transformer.on 'end', -> - data.slice(0,2).should.eql [ - [ 'ONKCHhJmjadoA', 'OMH' ] - [ 'GeACHiN', 'D' ] - ] - next() - - describe 'source and destination', -> - - it 'in sync mode', (next) -> - @timeout 0 - count = 0 - generator = generate length: 10000, objectMode: true, seed: 1, columns: 2 - destination = new stream.Writable - destination._write = (chunk, encoding, callback) -> - setImmediate callback - destination.on 'finish', next - generator - .pipe transform (record) -> - record.join ',' - .pipe destination - - it 'in async mode', (next) -> - @timeout 0 - generator = generate length: 10000, objectMode: true, seed: 1, columns: 2 - destination = new stream.Writable - destination._write = (chunk, encoding, callback) -> - setImmediate callback - destination.on 'finish', next - generator - .pipe transform (record, callback) -> - setImmediate -> - callback null, record.join ',' - .pipe destination diff --git a/packages/stream-transform/test/api.pipe.js b/packages/stream-transform/test/api.pipe.js new file mode 100644 index 000000000..ba9417cf8 --- /dev/null +++ b/packages/stream-transform/test/api.pipe.js @@ -0,0 +1,115 @@ +import "should"; +import stream from "stream"; +import { generate } from "csv-generate"; +import { transform } from "../lib/index.js"; + +describe("api.pipe", function () { + describe("source", function () { + it("in sync mode", function (next) { + const data = []; + const generator = generate({ + length: 1000, + objectMode: true, + seed: 1, + columns: 2, + }); + const transformer = generator.pipe( + transform(function (record) { + record.push(record.shift()); + return record; + }), + ); + transformer.on("readable", function () { + let d; + while ((d = transformer.read())) { + data.push(d); + } + }); + transformer.on("end", function () { + data.length.should.eql(1000); + data.slice(0, 2).should.eql([ + ["ONKCHhJmjadoA", "OMH"], + ["GeACHiN", "D"], + ]); + next(); + }); + }); + + it("in async mode", function (next) { + const data = []; + const generator = generate({ + length: 1000, + objectMode: true, + seed: 1, + columns: 2, + }); + const transformer = generator.pipe( + transform(function (record, callback) { + record.push(record.shift()); + callback(null, record); + }), + ); + transformer.on("readable", function () { + let d; + while ((d = transformer.read())) { + data.push(d); + } + }); + transformer.on("end", function () { + data.slice(0, 2).should.eql([ + ["ONKCHhJmjadoA", "OMH"], + ["GeACHiN", "D"], + ]); + next(); + }); + }); + }); + + describe("source and destination", function () { + it("in sync mode", function (next) { + this.timeout(0); + const generator = generate({ + length: 10000, + objectMode: true, + seed: 1, + columns: 2, + }); + const destination = new stream.Writable(); + destination._write = function (chunk, encoding, callback) { + setImmediate(callback); + }; + destination.on("finish", next); + generator + .pipe( + transform(function (record) { + return record.join(","); + }), + ) + .pipe(destination); + }); + + it("in async mode", function (next) { + this.timeout(0); + const generator = generate({ + length: 10000, + objectMode: true, + seed: 1, + columns: 2, + }); + const destination = new stream.Writable(); + destination._write = function (chunk, encoding, callback) { + setImmediate(callback); + }; + destination.on("finish", next); + generator + .pipe( + transform(function (record, callback) { + setImmediate(function () { + callback(null, record.join(",")); + }); + }), + ) + .pipe(destination); + }); + }); +}); diff --git a/packages/stream-transform/test/api.sync.coffee b/packages/stream-transform/test/api.sync.coffee deleted file mode 100644 index 05cbdd421..000000000 --- a/packages/stream-transform/test/api.sync.coffee +++ /dev/null @@ -1,42 +0,0 @@ - -import { transform } from '../lib/sync.js' - -describe 'api.sync', -> - - it 'accept data and handler without options', -> - data = transform [ - ['a', 'b', 'c'] - ['1', '2', '3'] - ], (record) -> - record.join '|' - data.should.eql [ - 'a|b|c' - '1|2|3' - ] - - it 'honors params option', -> - data = transform [ - ['a', 'b', 'c'] - ['1', '2', '3'] - ], params: separator: '|', (record, params) -> - record.join params.separator - data.should.eql [ - 'a|b|c' - '1|2|3' - ] - - it 'only sync handlers are supported', -> - # Without options - (-> - transform [ - ['a', 'b', 'c'] - ['1', '2', '3'] - ], ((record, callback) ->) - ).should.throw 'Invalid Handler: only synchonous handlers are supported' - # With options - (-> - transform [ - ['a', 'b', 'c'] - ['1', '2', '3'] - ], params: a_key: 'a value', ((record, callback, params) ->) - ).should.throw 'Invalid Handler: only synchonous handlers are supported' diff --git a/packages/stream-transform/test/api.sync.js b/packages/stream-transform/test/api.sync.js new file mode 100644 index 000000000..addc52704 --- /dev/null +++ b/packages/stream-transform/test/api.sync.js @@ -0,0 +1,66 @@ +import "should"; +import { transform } from "../lib/sync.js"; + +describe("api.sync", function () { + it("accept data and handler without options", function () { + const data = transform( + [ + ["a", "b", "c"], + ["1", "2", "3"], + ], + function (record) { + return record.join("|"); + }, + ); + data.should.eql(["a|b|c", "1|2|3"]); + }); + + it("honors params option", function () { + const data = transform( + [ + ["a", "b", "c"], + ["1", "2", "3"], + ], + { + params: { separator: "|" }, + }, + function (record, params) { + return record.join(params.separator); + }, + ); + data.should.eql(["a|b|c", "1|2|3"]); + }); + + it("only sync handlers are supported", function () { + // Without options + (function () { + transform( + [ + ["a", "b", "c"], + ["1", "2", "3"], + ], + function (record, callback) { + record; + callback; + }, + ); + }).should.throw("Invalid Handler: only synchonous handlers are supported"); + // With options + (function () { + transform( + [ + ["a", "b", "c"], + ["1", "2", "3"], + ], + { + params: { a_key: "a value" }, + }, + function (record, callback, params) { + record; + callback; + params; + }, + ); + }).should.throw("Invalid Handler: only synchonous handlers are supported"); + }); +}); diff --git a/packages/stream-transform/test/api.types.sync.ts b/packages/stream-transform/test/api.types.sync.ts index 8395c13f3..50d24419f 100644 --- a/packages/stream-transform/test/api.types.sync.ts +++ b/packages/stream-transform/test/api.types.sync.ts @@ -1,24 +1,21 @@ +import "should"; +import { transform, Options } from "../lib/sync.js"; -import 'should' -import { transform, Options } from '../lib/sync.js' - -describe('api.types', () => { - - it('sync', () => { +describe("api.types", function () { + it("sync", function () { // With records + handler - const transformer: Array = transform( ['record'], record => record ) - transformer.should.be.an.Array() + const transformer: string[] = transform(["record"], (record) => record); + transformer.should.be.an.Array(); // With records + options + handler - transform( ['record'], {consume: true}, record => record ) - }) + transform(["record"], { consume: true }, (record) => record); + }); - it('Options', () => { + it("Options", function () { (options: Options) => { const consume: boolean | undefined = options.consume; - const parallel: number | undefined = options.parallel - const params: number = options.params - return {consume, parallel, params} - } - }) - -}) + const parallel: number | undefined = options.parallel; + const params: number = options.params; + return { consume, parallel, params }; + }; + }); +}); diff --git a/packages/stream-transform/test/api.types.ts b/packages/stream-transform/test/api.types.ts index 6703617eb..40571f695 100644 --- a/packages/stream-transform/test/api.types.ts +++ b/packages/stream-transform/test/api.types.ts @@ -1,81 +1,76 @@ +import "should"; +import { transform, Options, Transformer } from "../lib/index.js"; -import 'should' -import { transform, Options, Transformer } from '../lib/index.js' - -describe('api.types', () => { - - describe('Initialisation', () => { - - it('stream', () => { +describe("api.types", function () { + describe("Initialisation", function () { + it("stream", function () { // With handler - const transformer: Transformer = transform( record => record ) - transformer.should.be.an.Object() + const transformer: Transformer = transform((record) => record); + transformer.should.be.an.Object(); // With handler + callback - transform( record => record, (err, records) => err || records ) + transform( + (record) => record, + (err, records) => err || records, + ); // With records + handler - transform( ['record'], record => record ) + transform(["record"], (record) => record); // With options + handler - transform( {consume: true}, record => record ) + transform({ consume: true }, (record) => record); // With records + options + handler - transform( ['record'], {consume: true}, record => record ) + transform(["record"], { consume: true }, (record) => record); // With records + options + handler + callback - transform( ['record'], {consume: true}, record => record, (err, records) => err || records ) - }) - - }) - - describe('Parser', () => { - - it('Expose options', () => { - const transformer: Transformer = transform( record => record ) - const options: Options = transformer.options - const keys: any = Object.keys(options) - keys.sort().should.eql([ - 'consume', 'objectMode', 'parallel', 'params' - ]) - }) - - }) - - describe('Options', () => { - - it('consume', () => { - const options: Options = {} - options.consume = true - }) - - it('parallel', () => { - const options: Options = {} - options.parallel = 100 - }) - - it('params', () => { - const options: Options = {} - options.params = { my_key: 'my value' } - }) - - }) - - describe('State', () => { - - it('finished', () => { - const transformer: Transformer = transform( record => record ) - const finished: number = transformer.state.finished - finished.should.eql(0) - }) - - it('running', () => { - const transformer: Transformer = transform( record => record ) - const running: number = transformer.state.running - running.should.eql(0) - }) - - it('started', () => { - const transformer: Transformer = transform( record => record ) - const started: number = transformer.state.started - started.should.eql(0) - }) - - }) - -}) + transform( + ["record"], + { consume: true }, + (record) => record, + (err, records) => err || records, + ); + }); + }); + + describe("Parser", function () { + it("Expose options", function () { + const transformer: Transformer = transform((record) => record); + const options: Options = transformer.options; + const keys = Object.keys(options); + keys.sort().should.eql(["consume", "objectMode", "parallel", "params"]); + }); + }); + + describe("Options", function () { + it("consume", function () { + const options: Options = {}; + options.consume = true; + }); + + it("parallel", function () { + const options: Options = {}; + options.parallel = 100; + }); + + it("params", function () { + const options: Options = {}; + options.params = { my_key: "my value" }; + }); + }); + + describe("State", function () { + it("finished", function () { + const transformer: Transformer = transform((record) => record); + const finished: number = transformer.state.finished; + finished.should.eql(0); + }); + + it("running", function () { + const transformer: Transformer = transform((record) => record); + const running: number = transformer.state.running; + running.should.eql(0); + }); + + it("started", function () { + const transformer: Transformer = transform((record) => record); + const started: number = transformer.state.started; + started.should.eql(0); + }); + }); +}); diff --git a/packages/stream-transform/test/handler.async.coffee b/packages/stream-transform/test/handler.async.coffee deleted file mode 100644 index 5930d9d49..000000000 --- a/packages/stream-transform/test/handler.async.coffee +++ /dev/null @@ -1,135 +0,0 @@ - -import { transform } from '../lib/index.js' - -describe 'handler.async', -> - - it 'modify the received object', (next) -> - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - [ '83929843999','1944','8.8349294E2','HIJ','17','2060-08-28' ] - ], (record, callback) -> - process.nextTick -> - record.push record.shift() - callback null, record - , (err, data) -> - return next err if err - data.should.eql [ - [ '1979','8.8017226E7','ABC','45','2000-01-01', '20322051544' ] - [ '1974','8.8392926E7','DEF','23','2050-11-27', '28392898392' ] - [ '1944','8.8349294E2','HIJ','17','2060-08-28', '83929843999' ] - ] - next() - - it 'skip lines when undefined is returned', (next) -> - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - [ '83929843999','1944','8.8349294E2','HIJ','17','2060-08-28' ] - ], (record, callback) -> - process.nextTick callback - , (err, data) -> - return next err if err - data.should.eql [] - next() - - it 'skip lines when undefined is returned', (next) -> - index = 0 - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - [ '83929843999','1944','8.8349294E2','HIJ','17','2060-08-28' ] - [ '47191084482','1978','8.8392926E7','2FF','23','2064-02-15' ] - ], (record, callback) -> - process.nextTick -> - index++ - callback null, if index % 2 then record else null - , (err, data) -> - return next err if err - data.should.eql [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '83929843999','1944','8.8349294E2','HIJ','17','2060-08-28' ] - ] - next() - - it 'receive an array and return an object', (next) -> - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - ], (record, callback) -> - process.nextTick -> - callback null, field_1: record[4], field_2: record[3] - , (err, data) -> - return next err if err - data.should.eql [ - { field_1: '45', field_2: 'ABC' } - { field_1: '23', field_2: 'DEF' } - ] - next() - - it 'should accept a returned string', (next) -> - index = -1 - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - ], (record, callback) -> - process.nextTick -> - index++ - callback null, ( if index > 0 then ',' else '' ) + "#{record[4]}:#{record[3]}" - , (err, data) -> - return next err if err - data.join('').should.eql '45:ABC,23:DEF' - next() - - it 'should accept a returned number', (next) -> - index = 0 - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - [ '83929843999','1944','8.8349294E2','HIJ','17','2060-08-28' ] - ], (record, callback) -> - process.nextTick -> - callback null, index++ - , (err, data) -> - return next err if err - data.join('').should.eql '012' - next() - - it 'should accept a returned array with different types', (next) -> - transform [ - [ '20322051544','1979','8.8017226E7','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','2050-11-27' ] - [ '83929843999','1944','8.8349294E2','2060-08-28' ] - ], (record, callback) -> - process.nextTick -> - [year, month, day] = record[3].split('-') - callback null, [parseInt(record[0]), parseFloat(record[2]) ,Date.UTC(year, month, day)] - , (err, data) -> - return next err if err - data.should.eql [ - [ 20322051544, 88017226, 949363200000 ] - [ 28392898392, 88392926, 2555712000000 ] - [ 83929843999, 883.49294, 2863555200000 ] - ] - next() - - it 'should accept multiple emit', (next) -> - chunks = [ - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - [ '47191084482','1978','8.8392926E7','2FF','23','2064-02-15' ] - ] - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '83929843999','1944','8.8349294E2','HIJ','17','2060-08-28' ] - ], (record, callback) -> - process.nextTick -> - callback null, record, chunks.shift() - , (err, data) -> - return next err if err - data.should.eql [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - [ '83929843999','1944','8.8349294E2','HIJ','17','2060-08-28' ] - [ '47191084482','1978','8.8392926E7','2FF','23','2064-02-15' ] - ] - next() diff --git a/packages/stream-transform/test/handler.async.js b/packages/stream-transform/test/handler.async.js new file mode 100644 index 000000000..45388a209 --- /dev/null +++ b/packages/stream-transform/test/handler.async.js @@ -0,0 +1,194 @@ +import "should"; +import { transform } from "../lib/index.js"; + +describe("handler.async", function () { + it("modify the received object", function (next) { + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ["83929843999", "1944", "8.8349294E2", "HIJ", "17", "2060-08-28"], + ], + function (record, callback) { + process.nextTick(function () { + record.push(record.shift()); + callback(null, record); + }); + }, + function (err, data) { + if (err) return next(err); + data.should.eql([ + ["1979", "8.8017226E7", "ABC", "45", "2000-01-01", "20322051544"], + ["1974", "8.8392926E7", "DEF", "23", "2050-11-27", "28392898392"], + ["1944", "8.8349294E2", "HIJ", "17", "2060-08-28", "83929843999"], + ]); + next(); + }, + ); + }); + + it("skip all records when undefined", function (next) { + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ["83929843999", "1944", "8.8349294E2", "HIJ", "17", "2060-08-28"], + ], + function (record, callback) { + process.nextTick(callback); + }, + function (err, data) { + if (err) return next(err); + data.should.eql([]); + next(); + }, + ); + }); + + it("skip individual records when undefined", function (next) { + let index = 0; + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ["83929843999", "1944", "8.8349294E2", "HIJ", "17", "2060-08-28"], + ["47191084482", "1978", "8.8392926E7", "2FF", "23", "2064-02-15"], + ], + function (record, callback) { + process.nextTick(function () { + index++; + callback(null, index % 2 ? record : null); + }); + }, + function (err, data) { + if (err) return next(err); + data.should.eql([ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["83929843999", "1944", "8.8349294E2", "HIJ", "17", "2060-08-28"], + ]); + next(); + }, + ); + }); + + it("receive an array and return an object", function (next) { + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ], + function (record, callback) { + process.nextTick(function () { + callback(null, { field_1: record[4], field_2: record[3] }); + }); + }, + function (err, data) { + if (err) return next(err); + data.should.eql([ + { field_1: "45", field_2: "ABC" }, + { field_1: "23", field_2: "DEF" }, + ]); + next(); + }, + ); + }); + + it("should accept a returned string", function (next) { + let index = -1; + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ], + function (record, callback) { + process.nextTick(function () { + index++; + callback(null, (index > 0 ? "," : "") + `${record[4]}:${record[3]}`); + }); + }, + function (err, data) { + if (err) return next(err); + data.join("").should.eql("45:ABC,23:DEF"); + next(); + }, + ); + }); + + it("should accept a returned number", function (next) { + let index = 0; + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ["83929843999", "1944", "8.8349294E2", "HIJ", "17", "2060-08-28"], + ], + function (record, callback) { + process.nextTick(function () { + callback(null, index++); + }); + }, + function (err, data) { + if (err) return next(err); + data.join("").should.eql("012"); + next(); + }, + ); + }); + + it("should accept a returned array with different types", function (next) { + transform( + [ + ["20322051544", "1979", "8.8017226E7", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "2050-11-27"], + ["83929843999", "1944", "8.8349294E2", "2060-08-28"], + ], + function (record, callback) { + process.nextTick(function () { + const [year, month, day] = record[3].split("-"); + callback(null, [ + parseInt(record[0]), + parseFloat(record[2]), + Date.UTC(year, month, day), + ]); + }); + }, + function (err, data) { + if (err) return next(err); + data.should.eql([ + [20322051544, 88017226, 949363200000], + [28392898392, 88392926, 2555712000000], + [83929843999, 883.49294, 2863555200000], + ]); + next(); + }, + ); + }); + + it("should accept multiple emit", function (next) { + const chunks = [ + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ["47191084482", "1978", "8.8392926E7", "2FF", "23", "2064-02-15"], + ]; + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["83929843999", "1944", "8.8349294E2", "HIJ", "17", "2060-08-28"], + ], + function (record, callback) { + process.nextTick(function () { + callback(null, record, chunks.shift()); + }); + }, + function (err, data) { + if (err) return next(err); + data.should.eql([ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ["83929843999", "1944", "8.8349294E2", "HIJ", "17", "2060-08-28"], + ["47191084482", "1978", "8.8392926E7", "2FF", "23", "2064-02-15"], + ]); + next(); + }, + ); + }); +}); diff --git a/packages/stream-transform/test/handler.coffee b/packages/stream-transform/test/handler.coffee deleted file mode 100644 index 9059e76e9..000000000 --- a/packages/stream-transform/test/handler.coffee +++ /dev/null @@ -1,24 +0,0 @@ - -import { transform } from '../lib/index.js' - -describe 'handler', -> - - it 'context sync', (next) -> - transformer = transform [ - [ 'a','b','c' ] - [ '1','2','3' ] - ], (record) -> - transformer.should.eql this - return record - , next - - it 'context async', (next) -> - transformer = transform [ - [ 'a','b','c' ] - [ '1','2','3' ] - ], (record, callback) -> - transformer.should.eql this - callback null, record - , next - - diff --git a/packages/stream-transform/test/handler.js b/packages/stream-transform/test/handler.js new file mode 100644 index 000000000..a29157312 --- /dev/null +++ b/packages/stream-transform/test/handler.js @@ -0,0 +1,32 @@ +import "should"; +import { transform } from "../lib/index.js"; + +describe("handler", function () { + it("context sync", function (next) { + const transformer = transform( + [ + ["a", "b", "c"], + ["1", "2", "3"], + ], + function (record) { + transformer.should.eql(this); + return record; + }, + next, + ); + }); + + it("context async", function (next) { + const transformer = transform( + [ + ["a", "b", "c"], + ["1", "2", "3"], + ], + function (record, callback) { + transformer.should.eql(this); + callback(null, record); + }, + next, + ); + }); +}); diff --git a/packages/stream-transform/test/handler.mode.callback.coffee b/packages/stream-transform/test/handler.mode.callback.coffee deleted file mode 100644 index 7e805533b..000000000 --- a/packages/stream-transform/test/handler.mode.callback.coffee +++ /dev/null @@ -1,46 +0,0 @@ - -import { Writable } from 'node:stream' -import { pipeline } from 'node:stream/promises' -import { generate } from 'csv-generate' -import { transform } from '../lib/index.js' - -describe 'handler.mode.callback', -> - - it 'handler with callback with parallel 1', -> - chunks = [] - consumer = new Writable - write: (chunk, _, callback) -> - chunks.push chunk.toString() - callback() - await pipeline( - generate length: 1000 - , - transform parallel: 1, (chunk, callback) -> - setImmediate -> - callback null, chunk - , - consumer - ) - chunks.join('').split('\n').length.should.eql 1000 - - it 'handler with callback with parallel 2', -> - count = 0 - clear = setInterval -> - count++ - , 10 - chunks = [] - consumer = new Writable - write: (chunk, _, callback) -> - chunks.push chunk.toString() - callback() - await pipeline( - generate columns: 10, objectMode: true, length: 1000, seed: true - , - transform parallel: 2, (chunk, callback) -> - setImmediate -> - callback null, JSON.stringify(chunk)+'\n' - , - consumer - ) - clearInterval(clear) - count.should.be.above 1 diff --git a/packages/stream-transform/test/handler.mode.callback.error.coffee b/packages/stream-transform/test/handler.mode.callback.error.coffee deleted file mode 100644 index 152d24f3b..000000000 --- a/packages/stream-transform/test/handler.mode.callback.error.coffee +++ /dev/null @@ -1,56 +0,0 @@ - -import { Writable } from 'node:stream' -import { pipeline } from 'node:stream/promises' -import { generate } from 'csv-generate' -import { stringify } from 'csv-stringify' -import { transform } from '../lib/index.js' - -describe 'handler.mode.callback.error', -> - - it 'with parallel 1', -> - count = 0 - consumer = new Writable - write: (_, __, callback) -> - callback() - try - await pipeline( - generate length: 1000, highWaterMark: 1 - , - transform parallel: 1, highWaterMark: 1, (chunk, callback) -> - setImmediate -> - if ++count < 4 - callback null, chunk - else - callback new Error 'Catchme' - , - consumer - ) - throw Error 'Oh no!' - catch err - count.should.eql 4 - err.message.should.eql 'Catchme' - - it 'handler with callback with parallel 10', -> - count = 0 - consumer = new Writable - objectMode: true, - write: (_, __, callback) -> - callback() - try - await pipeline( - generate length: 1000, objectMode: true - , - transform parallel: 10, (record, callback) -> - setTimeout -> - if ++count < 4 - callback null, record - else - callback new Error 'Catchme' - , 10 - , - consumer - ) - throw Error 'Oh no!' - catch err - count.should.eql 4 - err.message.should.eql 'Catchme' diff --git a/packages/stream-transform/test/handler.mode.callback.error.js b/packages/stream-transform/test/handler.mode.callback.error.js new file mode 100644 index 000000000..26d8d03c5 --- /dev/null +++ b/packages/stream-transform/test/handler.mode.callback.error.js @@ -0,0 +1,67 @@ +import "should"; +import { Writable } from "node:stream"; +import { pipeline } from "node:stream/promises"; +import { generate } from "csv-generate"; +import { transform } from "../lib/index.js"; + +describe("handler.mode.callback.error", function () { + it("with parallel 1", async function () { + let count = 0; + const consumer = new Writable({ + write: function (_, __, callback) { + callback(); + }, + }); + try { + await pipeline( + generate({ length: 1000, highWaterMark: 1 }), + transform( + { parallel: 1, highWaterMark: 1 }, + function (chunk, callback) { + setImmediate(function () { + if (++count < 4) { + callback(null, chunk); + } else { + callback(new Error("Catchme")); + } + }); + }, + ), + consumer, + ); + throw Error("Oh no!"); + } catch (err) { + count.should.eql(4); + err.message.should.eql("Catchme"); + } + }); + + it("handler with callback with parallel 10", async function () { + let count = 0; + const consumer = new Writable({ + objectMode: true, + write: function (_, __, callback) { + callback(); + }, + }); + try { + await pipeline( + generate({ length: 1000, objectMode: true }), + transform({ parallel: 10 }, function (record, callback) { + setTimeout(function () { + if (++count < 4) { + callback(null, record); + } else { + callback(new Error("Catchme")); + } + }, 10); + }), + consumer, + ); + throw Error("Oh no!"); + } catch (err) { + count.should.eql(4); + err.message.should.eql("Catchme"); + } + }); +}); diff --git a/packages/stream-transform/test/handler.mode.callback.js b/packages/stream-transform/test/handler.mode.callback.js new file mode 100644 index 000000000..140a46091 --- /dev/null +++ b/packages/stream-transform/test/handler.mode.callback.js @@ -0,0 +1,57 @@ +import "should"; +import { Writable } from "node:stream"; +import { pipeline } from "node:stream/promises"; +import { generate } from "csv-generate"; +import { transform } from "../lib/index.js"; + +describe("handler.mode.callback", function () { + it("handler with callback with parallel 1", async function () { + const chunks = []; + const consumer = new Writable({ + write: function (chunk, _, callback) { + chunks.push(chunk.toString()); + callback(); + }, + }); + await pipeline( + generate({ length: 1000 }), + transform({ parallel: 1 }, function (chunk, callback) { + setImmediate(function () { + callback(null, chunk); + }); + }), + consumer, + ); + chunks.join("").split("\n").length.should.eql(1000); + }); + + it("handler with callback with parallel 2", async function () { + let count = 0; + const clear = setInterval(function () { + count++; + }, 10); + const chunks = []; + const consumer = new Writable({ + write: function (chunk, _, callback) { + chunks.push(chunk.toString()); + callback(); + }, + }); + await pipeline( + generate({ + columns: 10, + objectMode: true, + length: 1000, + seed: true, + }), + transform({ parallel: 2 }, function (chunk, callback) { + setTimeout(function () { + callback(null, JSON.stringify(chunk) + "\n"); + }, 1); + }), + consumer, + ); + clearInterval(clear); + count.should.be.above(1); + }); +}); diff --git a/packages/stream-transform/test/handler.mode.sync.coffee b/packages/stream-transform/test/handler.mode.sync.coffee deleted file mode 100644 index c35e473b4..000000000 --- a/packages/stream-transform/test/handler.mode.sync.coffee +++ /dev/null @@ -1,145 +0,0 @@ - -import { generate } from 'csv-generate' -import { transform } from '../lib/index.js' - -describe 'handler.mode.sync', -> - - describe 'api', -> - - it 'take array, handler and pipe', (next) -> - t = transform [ - ['1','2','3','4'], - ['a','b','c','d'] - ], (data) -> - data.push data.shift() - data.join(',') + '\n' - results = '' - t.on 'readable', -> - while(r = t.read()) then results += r - t.on 'error', next - t.on 'end', -> - results.should.eql '2,3,4,1\nb,c,d,a\n' - next() - - it 'take array, handler, callback', (next) -> - transform [ - [ '1', '2', '3', '4' ] - [ 'a', 'b', 'c', 'd' ] - ], (data) -> - data.push data.shift() - data.join(',') + '\n' - , (err, output) -> - output.should.eql [ '2,3,4,1\n', 'b,c,d,a\n' ] - next() - - it 'modify the recieved object', (next) -> - - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - [ '83929843999','1944','8.8349294E2','HIJ','17','2060-08-28' ] - ], (record) -> - record.push record.shift() - record - , (err, data) -> - return next err if err - data.should.eql [ - [ '1979','8.8017226E7','ABC','45','2000-01-01', '20322051544' ] - [ '1974','8.8392926E7','DEF','23','2050-11-27', '28392898392' ] - [ '1944','8.8349294E2','HIJ','17','2060-08-28', '83929843999' ] - ] - next() - - it 'skip all lines when undefined is returned', (next) -> - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - [ '83929843999','1944','8.8349294E2','HIJ','17','2060-08-28' ] - ], (record) -> - null - , (err, data) -> - return next err if err - data.should.eql [] - next() - - it 'skip lines when undefined is returned', (next) -> - index = 0 - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - [ '83929843999','1944','8.8349294E2','HIJ','17','2060-08-28' ] - [ '47191084482','1978','8.8392926E7','2FF','23','2064-02-15' ] - ], (record) -> - index++ - if index % 2 then record else null - , (err, data) -> - return next err if err - data.should.eql [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '83929843999','1944','8.8349294E2','HIJ','17','2060-08-28' ] - ] - next() - - it 'recieve an array and return an object', (next) -> - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - ], (record) -> - field_1: record[4], field_2: record[3] - , (err, data) -> - return next err if err - data.should.eql [ - { field_1: '45', field_2: 'ABC' } - { field_1: '23', field_2: 'DEF' } - ] - next() - - it 'should accept a returned string', (next) -> - index = -1 - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - ], (record) -> - index++ - ( if index > 0 then ',' else '' ) + "#{record[4]}:#{record[3]}" - , (err, data) -> - return next err if err - data.join('').should.eql '45:ABC,23:DEF' - next() - - it 'should accept a returned number', (next) -> - index = 0 - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - [ '83929843999','1944','8.8349294E2','HIJ','17','2060-08-28' ] - ], (record) -> - index++ - , (err, data) -> - return next err if err - data.join('').should.eql '012' - next() - - it 'should accept a returned array with different types', (next) -> - transform [ - [ '20322051544','1979','8.8017226E7','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','2050-11-27' ] - [ '83929843999','1944','8.8349294E2','2060-08-28' ] - ], (record) -> - [year, month, day] = record[3].split('-') - [parseInt(record[0]), parseFloat(record[2]) ,Date.UTC(year, month, day)] - , (err, data) -> - return next err if err - data.should.eql [ - [ 20322051544, 88017226, 949363200000 ] - [ 28392898392, 88392926, 2555712000000 ] - [ 83929843999, 883.49294, 2863555200000 ] - ] - next() - - describe 'behavior', -> - - it 'respect order', -> - generate length: 1000, objectMode: true, seed: 1, columns: 2, (err, source) -> - transform source, parralel: 1, ((record) -> record), (err, result) -> - result.should.eql source diff --git a/packages/stream-transform/test/handler.mode.sync.error.coffee b/packages/stream-transform/test/handler.mode.sync.error.coffee deleted file mode 100644 index c125ea172..000000000 --- a/packages/stream-transform/test/handler.mode.sync.error.coffee +++ /dev/null @@ -1,38 +0,0 @@ - -import { generate } from 'csv-generate' -import { transform } from '../lib/index.js' - -describe 'handler.mode.sync.error', -> - - it 'catch using stream api', (next) -> - transformer = transform (record) -> - throw new Error 'Custom Error' - transformer.on 'error', (err) -> - err.message.should.eql 'Custom Error' - next() - transformer.on 'finish', -> - next new Error 'Should not be called' - transformer.write [ 'trigger 1', 'trigger 2' ] - - it 'catch using pipe api', (next) -> - generator = generate length: 1000, objectMode: true, seed: 1, headers: 2 - transformer = generator.pipe transform (record) -> - throw new Error 'Custom Error' - transformer.on 'error', (err) -> - err.message.should.eql 'Custom Error' - next() - transformer.on 'finish', -> - next new Error 'Should not be called' - transformer.write [ 'trigger 1', 'trigger 2' ] - - it 'catch using callback api', (next) -> - transform [ - [ 'trigger 1' ] - [ 'trigger 2' ] - [ 'trigger 3' ] - ], (record) -> - throw new Error 'Custom Error' - , (err, data) -> - # thrown multiple times for now - err.message.should.eql 'Custom Error' - next() diff --git a/packages/stream-transform/test/handler.mode.sync.error.js b/packages/stream-transform/test/handler.mode.sync.error.js new file mode 100644 index 000000000..e048c2515 --- /dev/null +++ b/packages/stream-transform/test/handler.mode.sync.error.js @@ -0,0 +1,58 @@ +import "should"; +import { generate } from "csv-generate"; +import { transform } from "../lib/index.js"; + +describe("handler.mode.sync.error", function () { + it("catch using stream api", function (next) { + const transformer = transform((record) => { + record; + throw new Error("Custom Error"); + }); + transformer.on("error", (err) => { + err.message.should.eql("Custom Error"); + next(); + }); + transformer.on("finish", () => { + next(new Error("Should not be called")); + }); + transformer.write(["trigger 1", "trigger 2"]); + }); + + it("catch using pipe api", function (next) { + const generator = generate({ + length: 1000, + objectMode: true, + seed: 1, + headers: 2, + }); + const transformer = generator.pipe( + transform((record) => { + record; + throw new Error("Custom Error"); + }), + ); + transformer.on("error", (err) => { + err.message.should.eql("Custom Error"); + next(); + }); + transformer.on("finish", () => { + next(new Error("Should not be called")); + }); + transformer.write(["trigger 1", "trigger 2"]); + }); + + it("catch using callback api", function (next) { + transform( + [["trigger 1"], ["trigger 2"], ["trigger 3"]], + (record) => { + record; + throw new Error("Custom Error"); + }, + (err) => { + // thrown multiple times for now + err.message.should.eql("Custom Error"); + next(); + }, + ); + }); +}); diff --git a/packages/stream-transform/test/handler.mode.sync.js b/packages/stream-transform/test/handler.mode.sync.js new file mode 100644 index 000000000..5cb1c22ae --- /dev/null +++ b/packages/stream-transform/test/handler.mode.sync.js @@ -0,0 +1,212 @@ +import "should"; +import { generate } from "csv-generate"; +import { transform } from "../lib/index.js"; + +describe("handler.mode.sync", function () { + describe("api", function () { + it("take array, handler and pipe", function (next) { + const t = transform( + [ + ["1", "2", "3", "4"], + ["a", "b", "c", "d"], + ], + (data) => { + data.push(data.shift()); + return data.join(",") + "\n"; + }, + ); + let results = ""; + t.on("readable", () => { + let r; + while ((r = t.read())) results += r; + }); + t.on("error", next); + t.on("end", () => { + results.should.eql("2,3,4,1\nb,c,d,a\n"); + next(); + }); + }); + + it("take array, handler, callback", function (next) { + transform( + [ + ["1", "2", "3", "4"], + ["a", "b", "c", "d"], + ], + (data) => { + data.push(data.shift()); + return data.join(",") + "\n"; + }, + (err, output) => { + output.should.eql(["2,3,4,1\n", "b,c,d,a\n"]); + next(); + }, + ); + }); + }); + + it("modify the recieved object", function (next) { + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ["83929843999", "1944", "8.8349294E2", "HIJ", "17", "2060-08-28"], + ], + (record) => { + record.push(record.shift()); + return record; + }, + (err, data) => { + if (err) return next(err); + data.should.eql([ + ["1979", "8.8017226E7", "ABC", "45", "2000-01-01", "20322051544"], + ["1974", "8.8392926E7", "DEF", "23", "2050-11-27", "28392898392"], + ["1944", "8.8349294E2", "HIJ", "17", "2060-08-28", "83929843999"], + ]); + next(); + }, + ); + }); + + it("skip all lines when undefined is returned", function (next) { + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ["83929843999", "1944", "8.8349294E2", "HIJ", "17", "2060-08-28"], + ], + (record) => { + record; + }, + (err, data) => { + if (err) return next(err); + data.should.eql([]); + next(); + }, + ); + }); + + it("skip lines when undefined is returned", function (next) { + let index = 0; + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ["83929843999", "1944", "8.8349294E2", "HIJ", "17", "2060-08-28"], + ["47191084482", "1978", "8.8392926E7", "2FF", "23", "2064-02-15"], + ], + (record) => { + index++; + return index % 2 ? record : null; + }, + (err, data) => { + if (err) return next(err); + data.should.eql([ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["83929843999", "1944", "8.8349294E2", "HIJ", "17", "2060-08-28"], + ]); + next(); + }, + ); + }); + + it("recieve an array and return an object", function (next) { + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ], + (record) => ({ field_1: record[4], field_2: record[3] }), + (err, data) => { + if (err) return next(err); + data.should.eql([ + { field_1: "45", field_2: "ABC" }, + { field_1: "23", field_2: "DEF" }, + ]); + next(); + }, + ); + }); + + it("should accept a returned string", function (next) { + let index = -1; + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ], + (record) => { + index++; + return (index > 0 ? "," : "") + `${record[4]}:${record[3]}`; + }, + (err, data) => { + if (err) return next(err); + data.join("").should.eql("45:ABC,23:DEF"); + next(); + }, + ); + }); + + it("should accept a returned number", function (next) { + let index = 0; + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ["83929843999", "1944", "8.8349294E2", "HIJ", "17", "2060-08-28"], + ], + (record) => { + record; + return index++; + }, + (err, data) => { + if (err) return next(err); + data.join("").should.eql("012"); + next(); + }, + ); + }); + + it("should accept a returned array with different types", function (next) { + transform( + [ + ["20322051544", "1979", "8.8017226E7", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "2050-11-27"], + ["83929843999", "1944", "8.8349294E2", "2060-08-28"], + ], + (record) => { + const [year, month, day] = record[3].split("-"); + return [ + parseInt(record[0]), + parseFloat(record[2]), + Date.UTC(year, month, day), + ]; + }, + (err, data) => { + if (err) return next(err); + data.should.eql([ + [20322051544, 88017226, 949363200000], + [28392898392, 88392926, 2555712000000], + [83929843999, 883.49294, 2863555200000], + ]); + next(); + }, + ); + }); + + describe("behavior", function () { + it("respect order", function () { + generate( + { length: 1000, objectMode: true, seed: 1, columns: 2 }, + function (err, source) { + transform( + source, + { parralel: 1 }, + (record) => record, + (err, result) => result.should.eql(source), + ); + }, + ); + }); + }); +}); diff --git a/packages/stream-transform/test/handler.promise.coffee b/packages/stream-transform/test/handler.promise.coffee deleted file mode 100644 index 56c98dbff..000000000 --- a/packages/stream-transform/test/handler.promise.coffee +++ /dev/null @@ -1,38 +0,0 @@ - -import { transform } from '../lib/index.js' - -describe 'handler.promise', -> - - it 'handle records', (next) -> - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - [ '83929843999','1944','8.8349294E2','HIJ','17','2060-08-28' ] - ], (record) -> - new Promise (resolve) -> - process.nextTick -> - record.push record.shift() - resolve record - , (err, data) -> - return next err if err - data.should.eql [ - [ '1979','8.8017226E7','ABC','45','2000-01-01', '20322051544' ] - [ '1974','8.8392926E7','DEF','23','2050-11-27', '28392898392' ] - [ '1944','8.8349294E2','HIJ','17','2060-08-28', '83929843999' ] - ] - next() - - it 'handle errors', (next) -> - transform [ - [ '20322051544','1979','8.8017226E7','ABC','45','2000-01-01' ] - [ '28392898392','1974','8.8392926E7','DEF','23','2050-11-27' ] - [ '83929843999','1944','8.8349294E2','HIJ','17','2060-08-28' ] - ], (record) -> - new Promise (_, reject) -> - process.nextTick -> - record.push record.shift() - reject new Error('Catchme') - , (err, data) -> - err.message.should.eql 'Catchme' - next() - diff --git a/packages/stream-transform/test/handler.promise.js b/packages/stream-transform/test/handler.promise.js new file mode 100644 index 000000000..e45085a52 --- /dev/null +++ b/packages/stream-transform/test/handler.promise.js @@ -0,0 +1,53 @@ +import "should"; +import { transform } from "../lib/index.js"; + +describe("handler.promise", function () { + it("handle records", function (next) { + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ["83929843999", "1944", "8.8349294E2", "HIJ", "17", "2060-08-28"], + ], + (record) => { + return new Promise((resolve) => { + process.nextTick(() => { + record.push(record.shift()); + resolve(record); + }); + }); + }, + (err, data) => { + if (err) return next(err); + data.should.eql([ + ["1979", "8.8017226E7", "ABC", "45", "2000-01-01", "20322051544"], + ["1974", "8.8392926E7", "DEF", "23", "2050-11-27", "28392898392"], + ["1944", "8.8349294E2", "HIJ", "17", "2060-08-28", "83929843999"], + ]); + next(); + }, + ); + }); + + it("handle errors", function (next) { + transform( + [ + ["20322051544", "1979", "8.8017226E7", "ABC", "45", "2000-01-01"], + ["28392898392", "1974", "8.8392926E7", "DEF", "23", "2050-11-27"], + ["83929843999", "1944", "8.8349294E2", "HIJ", "17", "2060-08-28"], + ], + (record) => { + return new Promise((_, reject) => { + process.nextTick(() => { + record.push(record.shift()); + reject(new Error("Catchme")); + }); + }); + }, + (err) => { + err.message.should.eql("Catchme"); + next(); + }, + ); + }); +}); diff --git a/packages/stream-transform/test/handler.types.coffee b/packages/stream-transform/test/handler.types.coffee deleted file mode 100644 index 3976aea64..000000000 --- a/packages/stream-transform/test/handler.types.coffee +++ /dev/null @@ -1,43 +0,0 @@ - -import { transform } from '../lib/index.js' - -describe 'handler.types', -> - - it 'receive object and add new column', (next) -> - transform [ - { FIELD_1: '20322051544', FIELD_2: '1979', FIELD_3: 'ABC' } - { FIELD_1: '28392898392', FIELD_2: '1974', FIELD_3: 'DEF' } - { FIELD_1: '83929843999', FIELD_2: '1944', FIELD_3: 'HIJ' } - ], (record) -> - record.should.not.be.an.Array - record.FIELD_4 = 'new_field' - record - , (err, data) -> - return next err if err - data.should.eql [ - { FIELD_1: '20322051544', FIELD_2: '1979', FIELD_3: 'ABC', FIELD_4: 'new_field' } - { FIELD_1: '28392898392', FIELD_2: '1974', FIELD_3: 'DEF', FIELD_4: 'new_field' } - { FIELD_1: '83929843999', FIELD_2: '1944', FIELD_3: 'HIJ', FIELD_4: 'new_field' } - ] - next() - - it 'receive string and return object', (next) -> - transform [ - '20322-051544' - '28392-898392' - '83929-843999' - ], (record) -> - record.should.not.be.an.Array - [value_1, value_2] = record.split '-' - record = - FIELD_1: value_1 - FIELD_2: value_2 - record - , (err, data) -> - return next err if err - data.should.eql [ - { FIELD_1: '20322', FIELD_2: '051544' } - { FIELD_1: '28392', FIELD_2: '898392' } - { FIELD_1: '83929', FIELD_2: '843999' } - ] - next() diff --git a/packages/stream-transform/test/handler.types.js b/packages/stream-transform/test/handler.types.js new file mode 100644 index 000000000..8f3d696b3 --- /dev/null +++ b/packages/stream-transform/test/handler.types.js @@ -0,0 +1,66 @@ +import { transform } from "../lib/index.js"; + +describe("handler.types", function () { + it("receive object and add new column", function (next) { + transform( + [ + { FIELD_1: "20322051544", FIELD_2: "1979", FIELD_3: "ABC" }, + { FIELD_1: "28392898392", FIELD_2: "1974", FIELD_3: "DEF" }, + { FIELD_1: "83929843999", FIELD_2: "1944", FIELD_3: "HIJ" }, + ], + (record) => { + record.should.not.be.an.Array; + record.FIELD_4 = "new_field"; + return record; + }, + (err, data) => { + if (err) return next(err); + data.should.eql([ + { + FIELD_1: "20322051544", + FIELD_2: "1979", + FIELD_3: "ABC", + FIELD_4: "new_field", + }, + { + FIELD_1: "28392898392", + FIELD_2: "1974", + FIELD_3: "DEF", + FIELD_4: "new_field", + }, + { + FIELD_1: "83929843999", + FIELD_2: "1944", + FIELD_3: "HIJ", + FIELD_4: "new_field", + }, + ]); + next(); + }, + ); + }); + + it("receive string and return object", function (next) { + transform( + ["20322-051544", "28392-898392", "83929-843999"], + (record) => { + record.should.not.be.an.Array; + const [value_1, value_2] = record.split("-"); + record = { + FIELD_1: value_1, + FIELD_2: value_2, + }; + return record; + }, + (err, data) => { + if (err) return next(err); + data.should.eql([ + { FIELD_1: "20322", FIELD_2: "051544" }, + { FIELD_1: "28392", FIELD_2: "898392" }, + { FIELD_1: "83929", FIELD_2: "843999" }, + ]); + next(); + }, + ); + }); +}); diff --git a/packages/stream-transform/test/loaders/all.js b/packages/stream-transform/test/loaders/all.js deleted file mode 100644 index 4e81c3449..000000000 --- a/packages/stream-transform/test/loaders/all.js +++ /dev/null @@ -1,15 +0,0 @@ -import * as coffee from "./coffee.js"; -import * as ts from "ts-node/esm"; - -const coffeeRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; -const tsRegex = /\.ts$/; - -export function load(url, context, next) { - if (coffeeRegex.test(url)) { - return coffee.load.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.load.apply(this, arguments); - } - return next(url, context, next); -} diff --git a/packages/stream-transform/test/loaders/coffee.js b/packages/stream-transform/test/loaders/coffee.js deleted file mode 100644 index 75b15abe0..000000000 --- a/packages/stream-transform/test/loaders/coffee.js +++ /dev/null @@ -1,20 +0,0 @@ -import CoffeeScript from "coffeescript"; - -// See https://github.com/nodejs/node/issues/36396 -const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; - -export async function load(url, context, next) { - if (extensionsRegex.test(url)) { - const format = "module"; - const { source: rawSource } = await next(url, { format }); - const source = CoffeeScript.compile(rawSource.toString(), { - bare: true, - inlineMap: true, - filename: url, - header: false, - sourceMap: false, - }); - return { format, source }; - } - return next(url, context); -} diff --git a/packages/stream-transform/test/loaders/legacy/all.js b/packages/stream-transform/test/loaders/legacy/all.js deleted file mode 100644 index f5e57e542..000000000 --- a/packages/stream-transform/test/loaders/legacy/all.js +++ /dev/null @@ -1,36 +0,0 @@ -import * as coffee from "./coffee.js"; -import * as ts from "ts-node/esm"; - -const coffeeRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; -const tsRegex = /\.ts$/; - -export function resolve(specifier) { - if (coffeeRegex.test(specifier)) { - return coffee.resolve.apply(this, arguments); - } - if (tsRegex.test(specifier)) { - return ts.resolve.apply(this, arguments); - } - return ts.resolve.apply(this, arguments); -} - -export function getFormat(url) { - if (coffeeRegex.test(url)) { - return coffee.getFormat.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.getFormat.apply(this, arguments); - } - return ts.getFormat.apply(this, arguments); -} - -export function transformSource(source, context) { - const { url } = context; - if (coffeeRegex.test(url)) { - return coffee.transformSource.apply(this, arguments); - } - if (tsRegex.test(url)) { - return ts.transformSource.apply(this, arguments); - } - return ts.transformSource.apply(this, arguments); -} diff --git a/packages/stream-transform/test/loaders/legacy/coffee.js b/packages/stream-transform/test/loaders/legacy/coffee.js deleted file mode 100644 index 6a9975db9..000000000 --- a/packages/stream-transform/test/loaders/legacy/coffee.js +++ /dev/null @@ -1,50 +0,0 @@ -// coffeescript-loader.mjs -import { URL, pathToFileURL } from "url"; -import CoffeeScript from "coffeescript"; -import { cwd } from "process"; - -const baseURL = pathToFileURL(`${cwd()}/`).href; - -// CoffeeScript files end in .coffee, .litcoffee or .coffee.md. -const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/; - -export function resolve(specifier, context, defaultResolve) { - const { parentURL = baseURL } = context; - // Node.js normally errors on unknown file extensions, so return a URL for - // specifiers ending in the CoffeeScript file extensions. - if (extensionsRegex.test(specifier)) { - return { - url: new URL(specifier, parentURL).href, - stop: true, - }; - } - // Let Node.js handle all other specifiers. - return defaultResolve(specifier, context, defaultResolve); -} - -export function getFormat(url, context, defaultGetFormat) { - // Now that we patched resolve to let CoffeeScript URLs through, we need to - // tell Node.js what format such URLs should be interpreted as. For the - // purposes of this loader, all CoffeeScript URLs are ES modules. - if (extensionsRegex.test(url)) { - return { - format: "module", - stop: true, - }; - } - // Let Node.js handle all other URLs. - return defaultGetFormat(url, context, defaultGetFormat); -} - -export function transformSource(source, context, defaultTransformSource) { - const { url } = context; - - if (extensionsRegex.test(url)) { - return { - source: CoffeeScript.compile(String(source), { bare: true }), - }; - } - - // Let Node.js handle all other sources. - return defaultTransformSource(source, context, defaultTransformSource); -} diff --git a/packages/stream-transform/test/option.consume.coffee b/packages/stream-transform/test/option.consume.coffee deleted file mode 100644 index 6e6f0bd69..000000000 --- a/packages/stream-transform/test/option.consume.coffee +++ /dev/null @@ -1,62 +0,0 @@ - -import { generate } from 'csv-generate' -import { transform } from '../lib/index.js' - -describe 'option.consume', -> - - it 'async', (next) -> - @timeout 0 - data = [] - count = 0 - generator = generate length: 100000, objectMode: true - transformer = generator.pipe transform (record, callback) -> - count++ - setImmediate -> callback null, '' - , parallel: 7, consume: true - transformer.on 'error', next - transformer.on 'finish', -> - count.should.eql 100000 - next() - - it 'sync', (next) -> - @timeout 0 - data = [] - count = 0 - generator = generate length: 100000, objectMode: true - transformer = generator.pipe transform (record) -> - count++ - '' - , parallel: 10, consume: true - transformer.on 'error', next - transformer.on 'end', -> - count.should.eql 100000 - next() - - describe 'sequential', -> - - it 'async', (next) -> - @timeout 0 - data = [] - count = 0 - generator = generate length: 100000, objectMode: true - transformer = generator.pipe transform (record, callback) -> - count++ - setImmediate -> callback null, '' - , parallel: 1, consume: true - transformer.on 'finish', -> - count.should.eql 100000 - next() - - it 'sync', (next) -> - @timeout 0 - data = [] - count = 0 - generator = generate length: 100000, objectMode: true - transformer = generator.pipe transform (record) -> - count++ - '' - , parallel: 1, consume: true - transformer.on 'finish', -> - count.should.eql 100000 - next() - diff --git a/packages/stream-transform/test/option.consume.js b/packages/stream-transform/test/option.consume.js new file mode 100644 index 000000000..395ad3e58 --- /dev/null +++ b/packages/stream-transform/test/option.consume.js @@ -0,0 +1,86 @@ +import { generate } from "csv-generate"; +import { transform } from "../lib/index.js"; + +describe("option.consume", function () { + it("async", function (next) { + this.timeout(0); + let count = 0; + const generator = generate({ length: 100000, objectMode: true }); + const transformer = generator.pipe( + transform( + (record, callback) => { + count++; + setImmediate(() => callback(null, "")); + }, + { parallel: 7, consume: true }, + ), + ); + transformer.on("error", next); + transformer.on("finish", () => { + count.should.eql(100000); + next(); + }); + }); + + it("sync", function (next) { + this.timeout(0); + let count = 0; + const generator = generate({ length: 100000, objectMode: true }); + const transformer = generator.pipe( + transform( + (record) => { + record; + count++; + return ""; + }, + { parallel: 10, consume: true }, + ), + ); + transformer.on("error", next); + transformer.on("end", () => { + count.should.eql(100000); + next(); + }); + }); + + describe("sequential", function () { + it("async", function (next) { + this.timeout(0); + let count = 0; + const generator = generate({ length: 100000, objectMode: true }); + const transformer = generator.pipe( + transform( + (record, callback) => { + count++; + setImmediate(() => callback(null, "")); + }, + { parallel: 1, consume: true }, + ), + ); + transformer.on("finish", () => { + count.should.eql(100000); + next(); + }); + }); + + it("sync", function (next) { + this.timeout(0); + let count = 0; + const generator = generate({ length: 100000, objectMode: true }); + const transformer = generator.pipe( + transform( + (record) => { + record; + count++; + return ""; + }, + { parallel: 1, consume: true }, + ), + ); + transformer.on("finish", () => { + count.should.eql(100000); + next(); + }); + }); + }); +}); diff --git a/packages/stream-transform/test/option.parallel.coffee b/packages/stream-transform/test/option.parallel.coffee deleted file mode 100644 index 55e8c7cb8..000000000 --- a/packages/stream-transform/test/option.parallel.coffee +++ /dev/null @@ -1,53 +0,0 @@ - -import pad from 'pad' -import { generate } from 'csv-generate' -import { transform } from '../lib/index.js' - -letters = (number) -> - text = "#{number}" - text = "#{pad 3, text, '0'}" - text = for c in text - 65 - 49 + 1 + c.charCodeAt 0 - String.fromCharCode text... - -describe 'option.parallel', -> - - it 'respect running', (next) -> - @timeout 0 - data = [] - count = 0 - running = 0 - headers = -1 - generator = generate length: 1000, objectMode: true, highWaterMark: 40, headers: 2, seed: 1, columns: [ - (g) -> - letters pad 3, g.state.count_created, '0' - (g) -> pad 3, g.state.count_created-1, '0' - ] - transformer = generator.pipe transform (record, next) -> - count++ - record[1] = letters count-1 - running++ - running.should.be.below 6 - setTimeout -> - running-- - next null, "#{record[0]},#{record[1]}" - , 1 + Math.ceil count % 5 - , parallel: 5 - transformer.on 'readable', -> - while(d = transformer.read()) - data.push d - transformer.on 'error', next - transformer.on 'finish', -> - data = data.sort() - data = data.slice 0, 8 - data.should.eql [ - 'AAA,AAA' - 'AAB,AAB' - 'AAC,AAC' - 'AAD,AAD' - 'AAE,AAE' - 'AAF,AAF' - 'AAG,AAG' - 'AAH,AAH' - ] - next() diff --git a/packages/stream-transform/test/option.parallel.js b/packages/stream-transform/test/option.parallel.js new file mode 100644 index 000000000..b721cd430 --- /dev/null +++ b/packages/stream-transform/test/option.parallel.js @@ -0,0 +1,70 @@ +import pad from "pad"; +import { generate } from "csv-generate"; +import { transform } from "../lib/index.js"; + +const letters = (number) => { + let text = `${number}`; + text = `${pad(3, text, "0")}`; + text = [...text].map((c) => 65 - 49 + 1 + c.charCodeAt(0)); + return String.fromCharCode(...text); +}; + +describe("option.parallel", function () { + it("respect running", function (next) { + this.timeout(0); + let data = []; + let count = 0; + let running = 0; + const generator = generate({ + length: 1000, + objectMode: true, + highWaterMark: 40, + headers: 2, + seed: 1, + columns: [ + (g) => letters(pad(3, g.state.count_created, "0")), + (g) => pad(3, g.state.count_created - 1, "0"), + ], + }); + const transformer = generator.pipe( + transform( + (record, next) => { + count++; + record[1] = letters(count - 1); + running++; + running.should.be.below(6); + setTimeout( + () => { + running--; + next(null, `${record[0]},${record[1]}`); + }, + 1 + Math.ceil(count % 5), + ); + }, + { parallel: 5 }, + ), + ); + transformer.on("readable", () => { + let d; + while ((d = transformer.read())) { + data.push(d); + } + }); + transformer.on("error", next); + transformer.on("finish", () => { + data.sort(); + data = data.slice(0, 8); + data.should.eql([ + "AAA,AAA", + "AAB,AAB", + "AAC,AAC", + "AAD,AAD", + "AAE,AAE", + "AAF,AAF", + "AAG,AAG", + "AAH,AAH", + ]); + next(); + }); + }); +}); diff --git a/packages/stream-transform/test/option.params.coffee b/packages/stream-transform/test/option.params.coffee deleted file mode 100644 index 767dcb6f9..000000000 --- a/packages/stream-transform/test/option.params.coffee +++ /dev/null @@ -1,24 +0,0 @@ - -import { generate } from 'csv-generate' -import { transform } from '../lib/index.js' - -describe 'option.params', -> - - it 'sync', (next) -> - generator = generate length: 100, objectMode: true, seed: 1 - transformer = generator.pipe transform (record, params) -> - params.my_key.should.eql 'my value' - , parallel: 10, consume: true, params: my_key: 'my value' - transformer.on 'error', next - transformer.on 'finish', -> - next() - - it 'async', (next) -> - generator = generate length: 100, objectMode: true, seed: 1 - transformer = generator.pipe transform (record, callback, params) -> - params.my_key.should.eql 'my value' - setImmediate -> callback null, '' - , parallel: 10, consume: true, params: my_key: 'my value' - transformer.on 'error', next - transformer.on 'finish', -> - next() diff --git a/packages/stream-transform/test/option.params.js b/packages/stream-transform/test/option.params.js new file mode 100644 index 000000000..17579d9af --- /dev/null +++ b/packages/stream-transform/test/option.params.js @@ -0,0 +1,45 @@ +import { generate } from "csv-generate"; +import { transform } from "../lib/index.js"; + +describe("option.params", function () { + it("sync", function (next) { + const generator = generate({ length: 100, objectMode: true, seed: 1 }); + const transformer = generator.pipe( + transform( + (record, params) => { + params.my_key.should.eql("my value"); + }, + { + parallel: 10, + consume: true, + params: { my_key: "my value" }, + }, + ), + ); + transformer.on("error", next); + transformer.on("finish", () => { + next(); + }); + }); + + it("async", function (next) { + const generator = generate({ length: 100, objectMode: true, seed: 1 }); + const transformer = generator.pipe( + transform( + (record, callback, params) => { + params.my_key.should.eql("my value"); + setImmediate(() => callback(null, "")); + }, + { + parallel: 10, + consume: true, + params: { my_key: "my value" }, + }, + ), + ); + transformer.on("error", next); + transformer.on("finish", () => { + next(); + }); + }); +}); diff --git a/packages/stream-transform/test/samples.coffee b/packages/stream-transform/test/samples.coffee deleted file mode 100644 index 500e7525f..000000000 --- a/packages/stream-transform/test/samples.coffee +++ /dev/null @@ -1,30 +0,0 @@ - -import fs from 'node:fs/promises' -import path from 'node:path' -import { spawn } from 'node:child_process' - -__dirname = new URL( '.', import.meta.url).pathname -dir = path.resolve __dirname, '../samples' -samples = await fs.readdir dir - -describe 'Samples', -> - - samples - .filter (sample) -> - return false unless /\.(js|ts)?$/.test sample - true - .map (sample) -> - - it "Sample #{sample}", () -> - data = await fs.readFile path.resolve(dir, sample), 'utf8' - return if /^["|']skip test["|']/.test data - new Promise (resolve, reject) -> - ext = /\.(\w+)?$/.exec(sample)[0] - [cmd, ...args] = switch ext - when '.js' - ['node', path.resolve dir, sample] - when '.ts' - ['node', '--loader', 'ts-node/esm', path.resolve dir, sample] - spawn(cmd, args) - .on 'close', (code) -> if code is 0 then resolve() else reject(new Error 'Failure') - .stdout.on 'data', (->) diff --git a/packages/stream-transform/test/samples.js b/packages/stream-transform/test/samples.js new file mode 100644 index 000000000..5919a5514 --- /dev/null +++ b/packages/stream-transform/test/samples.js @@ -0,0 +1,44 @@ +import fs from "node:fs/promises"; +import path from "node:path"; +import { spawn } from "node:child_process"; + +const __dirname = new URL(".", import.meta.url).pathname; +const dir = path.resolve(__dirname, "../samples"); +const samples = await fs.readdir(dir); + +describe("Samples", function () { + /* eslint mocha/no-setup-in-describe: "off" */ + samples + .filter((sample) => { + if (!/\.(js|ts)?$/.test(sample)) return false; + return true; + }) + .map((sample) => { + it(`Sample ${sample}`, async function () { + const data = await fs.readFile(path.resolve(dir, sample), "utf8"); + if (/^["|']skip test["|']/.test(data)) return; + return new Promise((resolve, reject) => { + const ext = /\.(\w+)?$/.exec(sample)[0]; + let cmd, args; + switch (ext) { + case ".js": + [cmd, ...args] = ["node", path.resolve(dir, sample)]; + break; + case ".ts": + [cmd, ...args] = [ + "node", + "--loader", + "ts-node/esm", + path.resolve(dir, sample), + ]; + break; + } + spawn(cmd, args) + .on("close", (code) => + code === 0 ? resolve() : reject(new Error("Failure")), + ) + .stdout.on("data", () => {}); + }); + }); + }); +}); diff --git a/packages/stream-transform/test/state.finished.coffee b/packages/stream-transform/test/state.finished.coffee deleted file mode 100644 index 9ecff2b17..000000000 --- a/packages/stream-transform/test/state.finished.coffee +++ /dev/null @@ -1,31 +0,0 @@ - -import { transform } from '../lib/index.js' - -describe 'state.finished', -> - - it 'start at 0', (next) -> - transformer = transform ( (val) -> val), (err, data) -> - next err - transformer.state.finished.should.eql 0 - transformer.write [i] for i in [1..3] - transformer.end() - - it 'equals parallel', (next) -> - transformer = transform (val, callback) -> - setTimeout => - @state.finished.should.be.within 0, 9 - callback null, val - , 100 - , - parallel: 3 - , (err, data) -> - next err - transformer.write [i] for i in [1..10] - transformer.end() - - it 'end at 0', (next) -> - transformer = transform ( (val) -> val), (err, data) -> - transformer.state.finished.should.eql 3 - next err - transformer.write [i] for i in [1..3] - transformer.end() diff --git a/packages/stream-transform/test/state.finished.js b/packages/stream-transform/test/state.finished.js new file mode 100644 index 000000000..c0892bfaf --- /dev/null +++ b/packages/stream-transform/test/state.finished.js @@ -0,0 +1,48 @@ +import { transform } from "../lib/index.js"; + +describe("state.finished", function () { + it("start at 0", function (next) { + const transformer = transform( + (val) => val, + (err) => next(err), + ); + transformer.state.finished.should.eql(0); + for (let i = 1; i <= 3; i++) { + transformer.write([i]); + } + transformer.end(); + }); + + it("equals parallel", function (next) { + const transformer = transform( + function (val, callback) { + setTimeout(() => { + this.state.finished.should.be.within(0, 9); + callback(null, val); + }, 100); + }, + { + parallel: 3, + }, + (err) => next(err), + ); + for (let i = 1; i <= 10; i++) { + transformer.write([i]); + } + transformer.end(); + }); + + it("end at 0", function (next) { + const transformer = transform( + (val) => val, + (err) => { + transformer.state.finished.should.eql(3); + next(err); + }, + ); + for (let i = 1; i <= 3; i++) { + transformer.write([i]); + } + transformer.end(); + }); +}); diff --git a/packages/stream-transform/test/state.running.coffee b/packages/stream-transform/test/state.running.coffee deleted file mode 100644 index f95c44b7a..000000000 --- a/packages/stream-transform/test/state.running.coffee +++ /dev/null @@ -1,31 +0,0 @@ - -import { transform } from '../lib/index.js' - -describe 'state.running', -> - - it 'start at 0', (next) -> - transformer = transform ( (val) -> val), (err, data) -> - next err - transformer.state.running.should.eql 0 - transformer.write [i] for i in [1..3] - transformer.end() - - it 'equals parallel', (next) -> - transformer = transform (val, callback) -> - setTimeout => - @state.running.should.be.within 1, 3 - callback null, val - , 100 - , - parallel: 3 - , (err, data) -> - next err - transformer.write [i] for i in [1..10] - transformer.end() - - it 'end at 0', (next) -> - transformer = transform ( (val) -> val), (err, data) -> - transformer.state.running.should.eql 0 - next err - transformer.write [i] for i in [1..3] - transformer.end() diff --git a/packages/stream-transform/test/state.running.js b/packages/stream-transform/test/state.running.js new file mode 100644 index 000000000..8cdbdcf96 --- /dev/null +++ b/packages/stream-transform/test/state.running.js @@ -0,0 +1,48 @@ +import { transform } from "../lib/index.js"; + +describe("state.running", function () { + it("start at 0", function (next) { + const transformer = transform( + (val) => val, + (err) => next(err), + ); + transformer.state.running.should.eql(0); + for (let i = 1; i <= 3; i++) { + transformer.write([i]); + } + transformer.end(); + }); + + it("equals parallel", function (next) { + const transformer = transform( + function (val, callback) { + setTimeout(() => { + this.state.running.should.be.within(1, 3); + callback(null, val); + }, 100); + }, + { + parallel: 3, + }, + (err) => next(err), + ); + for (let i = 1; i <= 10; i++) { + transformer.write([i]); + } + transformer.end(); + }); + + it("end at 0", function (next) { + const transformer = transform( + (val) => val, + (err) => { + transformer.state.running.should.eql(0); + next(err); + }, + ); + for (let i = 1; i <= 3; i++) { + transformer.write([i]); + } + transformer.end(); + }); +}); diff --git a/packages/stream-transform/test/state.started.coffee b/packages/stream-transform/test/state.started.coffee deleted file mode 100644 index 44c14cc23..000000000 --- a/packages/stream-transform/test/state.started.coffee +++ /dev/null @@ -1,31 +0,0 @@ - -import { transform } from '../lib/index.js' - -describe 'state.started', -> - - it 'start at 0', (next) -> - transformer = transform ( (val) -> val), (err, data) -> - next err - transformer.state.started.should.eql 0 - transformer.write [i] for i in [1..3] - transformer.end() - - it 'equals parallel', (next) -> - transformer = transform (val, callback) -> - setTimeout => - @state.started.should.be.within 1, 10 - callback null, val - , 100 - , - parallel: 3 - , (err, data) -> - next err - transformer.write [i] for i in [1..10] - transformer.end() - - it 'end at 0', (next) -> - transformer = transform ( (val) -> val), (err, data) -> - transformer.state.started.should.eql 3 - next err - transformer.write [i] for i in [1..3] - transformer.end() diff --git a/packages/stream-transform/test/state.started.js b/packages/stream-transform/test/state.started.js new file mode 100644 index 000000000..f484a072c --- /dev/null +++ b/packages/stream-transform/test/state.started.js @@ -0,0 +1,50 @@ +import { transform } from "../lib/index.js"; + +describe("state.started", function () { + it("start at 0", function (next) { + const transformer = transform( + (val) => val, + (err) => { + next(err); + }, + ); + transformer.state.started.should.eql(0); + for (let i = 1; i <= 3; i++) { + transformer.write([i]); + } + transformer.end(); + }); + + it("equals parallel", function (next) { + const transformer = transform( + function (val, callback) { + setTimeout(() => { + this.state.started.should.be.within(1, 10); + callback(null, val); + }, 100); + }, + { + parallel: 3, + }, + (err) => next(err), + ); + for (let i = 1; i <= 10; i++) { + transformer.write([i]); + } + transformer.end(); + }); + + it("end at 0", function (next) { + const transformer = transform( + (val) => val, + (err) => { + transformer.state.started.should.eql(3); + next(err); + }, + ); + for (let i = 1; i <= 3; i++) { + transformer.write([i]); + } + transformer.end(); + }); +}); diff --git a/packages/stream-transform/tsconfig.json b/packages/stream-transform/tsconfig.json index 4db508a7c..5da38148b 100644 --- a/packages/stream-transform/tsconfig.json +++ b/packages/stream-transform/tsconfig.json @@ -4,6 +4,6 @@ "esModuleInterop": true, "module": "ES2020", "moduleResolution": "node", - "strict": true, + "strict": true } }