From ccdd517783c80399f51b8419ad867238c047406c Mon Sep 17 00:00:00 2001 From: ffelizp Date: Thu, 19 Oct 2023 10:55:39 -0400 Subject: [PATCH 1/7] Nodejs - Project Creation --- package.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 0000000..d632128 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "edam-interview-test", + "version": "1.0.0", + "description": "Choose whatever language you're most comfortable with to solve these problems.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ffelizp/interview-test.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/ffelizp/interview-test/issues" + }, + "homepage": "https://github.com/ffelizp/interview-test#readme" +} From 7e65806e6fb9d0bc7ee45e0a9e5b5f6a51266d71 Mon Sep 17 00:00:00 2001 From: ffelizp Date: Thu, 19 Oct 2023 10:59:13 -0400 Subject: [PATCH 2/7] Nodejs Library - Installing CSV Libraries --- node_modules/.bin/csv-parser | 1 + node_modules/.package-lock.json | 40 ++ node_modules/csv-parser/LICENSE | 21 + node_modules/csv-parser/README.md | 358 ++++++++++++++++++ node_modules/csv-parser/bin/csv-parser | 94 +++++ node_modules/csv-parser/index.d.ts | 146 +++++++ node_modules/csv-parser/index.js | 275 ++++++++++++++ node_modules/csv-parser/package.json | 92 +++++ node_modules/csv-writer/CHANGELOG.md | 58 +++ node_modules/csv-writer/README.md | 328 ++++++++++++++++ node_modules/csv-writer/dist/index.js | 19 + node_modules/csv-writer/dist/index.js.map | 1 + .../dist/lib/csv-stringifier-factory.js | 20 + .../dist/lib/csv-stringifier-factory.js.map | 1 + .../dist/lib/csv-stringifiers/abstract.js | 38 ++ .../dist/lib/csv-stringifiers/abstract.js.map | 1 + .../dist/lib/csv-stringifiers/array.js | 33 ++ .../dist/lib/csv-stringifiers/array.js.map | 1 + .../dist/lib/csv-stringifiers/object.js | 57 +++ .../dist/lib/csv-stringifiers/object.js.map | 1 + .../csv-writer/dist/lib/csv-writer-factory.js | 30 ++ .../dist/lib/csv-writer-factory.js.map | 1 + .../csv-writer/dist/lib/csv-writer.js | 76 ++++ .../csv-writer/dist/lib/csv-writer.js.map | 1 + .../csv-writer/dist/lib/field-stringifier.js | 69 ++++ .../dist/lib/field-stringifier.js.map | 1 + .../csv-writer/dist/lib/file-writer.js | 72 ++++ .../csv-writer/dist/lib/file-writer.js.map | 1 + .../csv-writer/dist/lib/lang/object.js | 6 + .../csv-writer/dist/lib/lang/object.js.map | 1 + .../csv-writer/dist/lib/lang/promise.js | 28 ++ .../csv-writer/dist/lib/lang/promise.js.map | 1 + node_modules/csv-writer/dist/lib/record.js | 3 + .../csv-writer/dist/lib/record.js.map | 1 + .../dist/test/csv-stringifiers/array.test.js | 114 ++++++ .../test/csv-stringifiers/array.test.js.map | 1 + .../dist/test/csv-stringifiers/object.test.js | 156 ++++++++ .../test/csv-stringifiers/object.test.js.map | 1 + .../dist/test/field-stringifier.test.js | 79 ++++ .../dist/test/field-stringifier.test.js.map | 1 + node_modules/csv-writer/dist/test/helper.js | 13 + .../csv-writer/dist/test/helper.js.map | 1 + .../csv-writer/dist/test/helper/delimiter.js | 10 + .../dist/test/helper/delimiter.js.map | 1 + .../csv-writer/dist/test/lang/promise.test.js | 76 ++++ .../dist/test/lang/promise.test.js.map | 1 + .../dist/test/write-array-records.test.js | 209 ++++++++++ .../dist/test/write-array-records.test.js.map | 1 + .../dist/test/write-object-records.test.js | 252 ++++++++++++ .../test/write-object-records.test.js.map | 1 + node_modules/csv-writer/package.json | 43 +++ node_modules/csv-writer/src/index.ts | 21 + .../src/lib/csv-stringifier-factory.ts | 33 ++ .../src/lib/csv-stringifiers/abstract.ts | 43 +++ .../src/lib/csv-stringifiers/array.ts | 20 + .../src/lib/csv-stringifiers/object.ts | 36 ++ .../csv-writer/src/lib/csv-writer-factory.ts | 49 +++ node_modules/csv-writer/src/lib/csv-writer.ts | 27 ++ .../csv-writer/src/lib/field-stringifier.ts | 47 +++ .../csv-writer/src/lib/file-writer.ts | 26 ++ .../csv-writer/src/lib/lang/object.ts | 6 + .../csv-writer/src/lib/lang/promise.ts | 14 + node_modules/csv-writer/src/lib/record.ts | 5 + .../src/test/csv-stringifiers/array.test.ts | 100 +++++ .../src/test/csv-stringifiers/object.test.ts | 150 ++++++++ .../src/test/field-stringifier.test.ts | 97 +++++ node_modules/csv-writer/src/test/helper.ts | 16 + .../csv-writer/src/test/helper/delimiter.ts | 6 + .../csv-writer/src/test/lang/promise.test.ts | 21 + .../src/test/write-array-records.test.ts | 124 ++++++ .../src/test/write-object-records.test.ts | 158 ++++++++ node_modules/fs/README.md | 9 + node_modules/fs/package.json | 20 + node_modules/minimist/.eslintrc | 29 ++ node_modules/minimist/.github/FUNDING.yml | 12 + node_modules/minimist/.nycrc | 14 + node_modules/minimist/CHANGELOG.md | 298 +++++++++++++++ node_modules/minimist/LICENSE | 18 + node_modules/minimist/README.md | 121 ++++++ node_modules/minimist/example/parse.js | 4 + node_modules/minimist/index.js | 263 +++++++++++++ node_modules/minimist/package.json | 75 ++++ node_modules/minimist/test/all_bool.js | 34 ++ node_modules/minimist/test/bool.js | 177 +++++++++ node_modules/minimist/test/dash.js | 43 +++ node_modules/minimist/test/default_bool.js | 37 ++ node_modules/minimist/test/dotted.js | 24 ++ node_modules/minimist/test/kv_short.js | 32 ++ node_modules/minimist/test/long.js | 33 ++ node_modules/minimist/test/num.js | 38 ++ node_modules/minimist/test/parse.js | 209 ++++++++++ node_modules/minimist/test/parse_modified.js | 11 + node_modules/minimist/test/proto.js | 64 ++++ node_modules/minimist/test/short.js | 69 ++++ node_modules/minimist/test/stop_early.js | 17 + node_modules/minimist/test/unknown.js | 104 +++++ node_modules/minimist/test/whitespace.js | 10 + package-lock.json | 75 ++++ package.json | 7 +- 99 files changed, 5681 insertions(+), 1 deletion(-) create mode 120000 node_modules/.bin/csv-parser create mode 100644 node_modules/.package-lock.json create mode 100644 node_modules/csv-parser/LICENSE create mode 100644 node_modules/csv-parser/README.md create mode 100755 node_modules/csv-parser/bin/csv-parser create mode 100644 node_modules/csv-parser/index.d.ts create mode 100644 node_modules/csv-parser/index.js create mode 100644 node_modules/csv-parser/package.json create mode 100644 node_modules/csv-writer/CHANGELOG.md create mode 100644 node_modules/csv-writer/README.md create mode 100644 node_modules/csv-writer/dist/index.js create mode 100644 node_modules/csv-writer/dist/index.js.map create mode 100644 node_modules/csv-writer/dist/lib/csv-stringifier-factory.js create mode 100644 node_modules/csv-writer/dist/lib/csv-stringifier-factory.js.map create mode 100644 node_modules/csv-writer/dist/lib/csv-stringifiers/abstract.js create mode 100644 node_modules/csv-writer/dist/lib/csv-stringifiers/abstract.js.map create mode 100644 node_modules/csv-writer/dist/lib/csv-stringifiers/array.js create mode 100644 node_modules/csv-writer/dist/lib/csv-stringifiers/array.js.map create mode 100644 node_modules/csv-writer/dist/lib/csv-stringifiers/object.js create mode 100644 node_modules/csv-writer/dist/lib/csv-stringifiers/object.js.map create mode 100644 node_modules/csv-writer/dist/lib/csv-writer-factory.js create mode 100644 node_modules/csv-writer/dist/lib/csv-writer-factory.js.map create mode 100644 node_modules/csv-writer/dist/lib/csv-writer.js create mode 100644 node_modules/csv-writer/dist/lib/csv-writer.js.map create mode 100644 node_modules/csv-writer/dist/lib/field-stringifier.js create mode 100644 node_modules/csv-writer/dist/lib/field-stringifier.js.map create mode 100644 node_modules/csv-writer/dist/lib/file-writer.js create mode 100644 node_modules/csv-writer/dist/lib/file-writer.js.map create mode 100644 node_modules/csv-writer/dist/lib/lang/object.js create mode 100644 node_modules/csv-writer/dist/lib/lang/object.js.map create mode 100644 node_modules/csv-writer/dist/lib/lang/promise.js create mode 100644 node_modules/csv-writer/dist/lib/lang/promise.js.map create mode 100644 node_modules/csv-writer/dist/lib/record.js create mode 100644 node_modules/csv-writer/dist/lib/record.js.map create mode 100644 node_modules/csv-writer/dist/test/csv-stringifiers/array.test.js create mode 100644 node_modules/csv-writer/dist/test/csv-stringifiers/array.test.js.map create mode 100644 node_modules/csv-writer/dist/test/csv-stringifiers/object.test.js create mode 100644 node_modules/csv-writer/dist/test/csv-stringifiers/object.test.js.map create mode 100644 node_modules/csv-writer/dist/test/field-stringifier.test.js create mode 100644 node_modules/csv-writer/dist/test/field-stringifier.test.js.map create mode 100644 node_modules/csv-writer/dist/test/helper.js create mode 100644 node_modules/csv-writer/dist/test/helper.js.map create mode 100644 node_modules/csv-writer/dist/test/helper/delimiter.js create mode 100644 node_modules/csv-writer/dist/test/helper/delimiter.js.map create mode 100644 node_modules/csv-writer/dist/test/lang/promise.test.js create mode 100644 node_modules/csv-writer/dist/test/lang/promise.test.js.map create mode 100644 node_modules/csv-writer/dist/test/write-array-records.test.js create mode 100644 node_modules/csv-writer/dist/test/write-array-records.test.js.map create mode 100644 node_modules/csv-writer/dist/test/write-object-records.test.js create mode 100644 node_modules/csv-writer/dist/test/write-object-records.test.js.map create mode 100644 node_modules/csv-writer/package.json create mode 100644 node_modules/csv-writer/src/index.ts create mode 100644 node_modules/csv-writer/src/lib/csv-stringifier-factory.ts create mode 100644 node_modules/csv-writer/src/lib/csv-stringifiers/abstract.ts create mode 100644 node_modules/csv-writer/src/lib/csv-stringifiers/array.ts create mode 100644 node_modules/csv-writer/src/lib/csv-stringifiers/object.ts create mode 100644 node_modules/csv-writer/src/lib/csv-writer-factory.ts create mode 100644 node_modules/csv-writer/src/lib/csv-writer.ts create mode 100644 node_modules/csv-writer/src/lib/field-stringifier.ts create mode 100644 node_modules/csv-writer/src/lib/file-writer.ts create mode 100644 node_modules/csv-writer/src/lib/lang/object.ts create mode 100644 node_modules/csv-writer/src/lib/lang/promise.ts create mode 100644 node_modules/csv-writer/src/lib/record.ts create mode 100644 node_modules/csv-writer/src/test/csv-stringifiers/array.test.ts create mode 100644 node_modules/csv-writer/src/test/csv-stringifiers/object.test.ts create mode 100644 node_modules/csv-writer/src/test/field-stringifier.test.ts create mode 100644 node_modules/csv-writer/src/test/helper.ts create mode 100644 node_modules/csv-writer/src/test/helper/delimiter.ts create mode 100644 node_modules/csv-writer/src/test/lang/promise.test.ts create mode 100644 node_modules/csv-writer/src/test/write-array-records.test.ts create mode 100644 node_modules/csv-writer/src/test/write-object-records.test.ts create mode 100644 node_modules/fs/README.md create mode 100644 node_modules/fs/package.json create mode 100644 node_modules/minimist/.eslintrc create mode 100644 node_modules/minimist/.github/FUNDING.yml create mode 100644 node_modules/minimist/.nycrc create mode 100644 node_modules/minimist/CHANGELOG.md create mode 100644 node_modules/minimist/LICENSE create mode 100644 node_modules/minimist/README.md create mode 100644 node_modules/minimist/example/parse.js create mode 100644 node_modules/minimist/index.js create mode 100644 node_modules/minimist/package.json create mode 100644 node_modules/minimist/test/all_bool.js create mode 100644 node_modules/minimist/test/bool.js create mode 100644 node_modules/minimist/test/dash.js create mode 100644 node_modules/minimist/test/default_bool.js create mode 100644 node_modules/minimist/test/dotted.js create mode 100644 node_modules/minimist/test/kv_short.js create mode 100644 node_modules/minimist/test/long.js create mode 100644 node_modules/minimist/test/num.js create mode 100644 node_modules/minimist/test/parse.js create mode 100644 node_modules/minimist/test/parse_modified.js create mode 100644 node_modules/minimist/test/proto.js create mode 100644 node_modules/minimist/test/short.js create mode 100644 node_modules/minimist/test/stop_early.js create mode 100644 node_modules/minimist/test/unknown.js create mode 100644 node_modules/minimist/test/whitespace.js create mode 100644 package-lock.json diff --git a/node_modules/.bin/csv-parser b/node_modules/.bin/csv-parser new file mode 120000 index 0000000..38d6336 --- /dev/null +++ b/node_modules/.bin/csv-parser @@ -0,0 +1 @@ +../csv-parser/bin/csv-parser \ No newline at end of file diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000..2376cbf --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,40 @@ +{ + "name": "edam-interview-test", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "node_modules/csv-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.0.0.tgz", + "integrity": "sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "csv-parser": "bin/csv-parser" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/csv-writer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/csv-writer/-/csv-writer-1.6.0.tgz", + "integrity": "sha512-NOx7YDFWEsM/fTRAJjRpPp8t+MKRVvniAg9wQlUKx20MFrPs73WLJhFf5iteqrxNYnsy924K3Iroh3yNHeYd2g==" + }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + } + } +} diff --git a/node_modules/csv-parser/LICENSE b/node_modules/csv-parser/LICENSE new file mode 100644 index 0000000..757562e --- /dev/null +++ b/node_modules/csv-parser/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Mathias Buus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/csv-parser/README.md b/node_modules/csv-parser/README.md new file mode 100644 index 0000000..bfd4b31 --- /dev/null +++ b/node_modules/csv-parser/README.md @@ -0,0 +1,358 @@ +[tests]: http://img.shields.io/travis/mafintosh/csv-parser.svg +[tests-url]: http://travis-ci.org/mafintosh/csv-parser + +[cover]: https://codecov.io/gh/mafintosh/csv-parser/branch/master/graph/badge.svg +[cover-url]: https://codecov.io/gh/mafintosh/csv-parser + +[size]: https://packagephobia.now.sh/badge?p=csv-parser +[size-url]: https://packagephobia.now.sh/result?p=csv-parser + +# csv-parser + +[![tests][tests]][tests-url] +[![cover][cover]][cover-url] +[![size][size]][size-url] + +Streaming CSV parser that aims for maximum speed as well as compatibility with +the [csv-spectrum](https://npmjs.org/csv-spectrum) CSV acid test suite. + +`csv-parser` can convert CSV into JSON at at rate of around 90,000 rows per +second. Performance varies with the data used; try `bin/bench.js ` +to benchmark your data. + +`csv-parser` can be used in the browser with [browserify](http://browserify.org/). + +[neat-csv](https://github.com/sindresorhus/neat-csv) can be used if a `Promise` +based interface to `csv-parser` is needed. + +_Note: This module requires Node v8.16.0 or higher._ + +## Benchmarks + +⚡️ `csv-parser` is greased-lightning fast + +```console +→ npm run bench + + Filename Rows Parsed Duration + backtick.csv 2 3.5ms + bad-data.csv 3 0.55ms + basic.csv 1 0.26ms + comma-in-quote.csv 1 0.29ms + comment.csv 2 0.40ms + empty-columns.csv 1 0.40ms + escape-quotes.csv 3 0.38ms + geojson.csv 3 0.46ms + large-dataset.csv 7268 73ms + newlines.csv 3 0.35ms + no-headers.csv 3 0.26ms + option-comment.csv 2 0.24ms + option-escape.csv 3 0.25ms + option-maxRowBytes.csv 4577 39ms + option-newline.csv 0 0.47ms + option-quote-escape.csv 3 0.33ms + option-quote-many.csv 3 0.38ms + option-quote.csv 2 0.22ms + quotes+newlines.csv 3 0.20ms + strict.csv 3 0.22ms + latin.csv 2 0.38ms + mac-newlines.csv 2 0.28ms + utf16-big.csv 2 0.33ms + utf16.csv 2 0.26ms + utf8.csv 2 0.24ms +``` + +## Install + +Using npm: + +```console +$ npm install csv-parser +``` + +Using yarn: + +```console +$ yarn add csv-parser +``` + +## Usage + +To use the module, create a readable stream to a desired CSV file, instantiate +`csv`, and pipe the stream to `csv`. + +Suppose you have a CSV file `data.csv` which contains the data: + +``` +NAME,AGE +Daffy Duck,24 +Bugs Bunny,22 +``` + +It could then be parsed, and results shown like so: + +``` js +const csv = require('csv-parser') +const fs = require('fs') +const results = []; + +fs.createReadStream('data.csv') + .pipe(csv()) + .on('data', (data) => results.push(data)) + .on('end', () => { + console.log(results); + // [ + // { NAME: 'Daffy Duck', AGE: '24' }, + // { NAME: 'Bugs Bunny', AGE: '22' } + // ] + }); +``` + +To specify options for `csv`, pass an object argument to the function. For +example: + +```js +csv({ separator: '\t' }); +``` + +## API + +### csv([options | headers]) + +Returns: `Array[Object]` + +#### options + +Type: `Object` + +As an alternative to passing an `options` object, you may pass an `Array[String]` +which specifies the headers to use. For example: + +```js +csv(['Name', 'Age']); +``` + +If you need to specify options _and_ headers, please use the the object notation +with the `headers` property as shown below. + +#### escape + +Type: `String`
+Default: `"` + +A single-character string used to specify the character used to escape strings +in a CSV row. + +#### headers + +Type: `Array[String] | Boolean` + +Specifies the headers to use. Headers define the property key for each value in +a CSV row. If no `headers` option is provided, `csv-parser` will use the first +line in a CSV file as the header specification. + +If `false`, specifies that the first row in a data file does _not_ contain +headers, and instructs the parser to use the column index as the key for each column. +Using `headers: false` with the same `data.csv` example from above would yield: + +``` js +[ + { '0': 'Daffy Duck', '1': 24 }, + { '0': 'Bugs Bunny', '1': 22 } +] +``` + +_Note: If using the `headers` for an operation on a file which contains headers on the first line, specify `skipLines: 1` to skip over the row, or the headers row will appear as normal row data. Alternatively, use the `mapHeaders` option to manipulate existing headers in that scenario._ + +#### mapHeaders + +Type: `Function` + +A function that can be used to modify the values of each header. Return a `String` to modify the header. Return `null` to remove the header, and it's column, from the results. + +```js +csv({ + mapHeaders: ({ header, index }) => header.toLowerCase() +}) +``` + +##### Parameters + +**header** _String_ The current column header.
+**index** _Number_ The current column index. + +#### mapValues + +Type: `Function` + +A function that can be used to modify the content of each column. The return value will replace the current column content. + +```js +csv({ + mapValues: ({ header, index, value }) => value.toLowerCase() +}) +``` + +##### Parameters + +**header** _String_ The current column header.
+**index** _Number_ The current column index.
+**value** _String_ The current column value (or content). + +##### newline + +Type: `String`
+Default: `\n` + +Specifies a single-character string to denote the end of a line in a CSV file. + +#### quote + +Type: `String`
+Default: `"` + +Specifies a single-character string to denote a quoted string. + +#### raw + +Type: `Boolean`
+ +If `true`, instructs the parser not to decode UTF-8 strings. + +#### separator + +Type: `String`
+Default: `,` + +Specifies a single-character string to use as the column separator for each row. + +#### skipComments + +Type: `Boolean | String`
+Default: `false` + +Instructs the parser to ignore lines which represent comments in a CSV file. Since there is no specification that dictates what a CSV comment looks like, comments should be considered non-standard. The "most common" character used to signify a comment in a CSV file is `"#"`. If this option is set to `true`, lines which begin with `#` will be skipped. If a custom character is needed to denote a commented line, this option may be set to a string which represents the leading character(s) signifying a comment line. + +#### skipLines + +Type: `Number`
+Default: `0` + +Specifies the number of lines at the beginning of a data file that the parser should +skip over, prior to parsing headers. + +#### maxRowBytes + +Type: `Number`
+Default: `Number.MAX_SAFE_INTEGER` + +Maximum number of bytes per row. An error is thrown if a line exeeds this value. The default value is on 8 peta byte. + +#### strict + +Type: `Boolean`
+Default: `false` + +If `true`, instructs the parser that the number of columns in each row must match +the number of `headers` specified or throws an exception. +if `false`: the headers are mapped to the column index + less columns: any missing column in the middle will result in a wrong property mapping! + more columns: the aditional columns will create a "_"+index properties - eg. "_10":"value" + +## Events + +The following events are emitted during parsing: + +### `data` + +Emitted for each row of data parsed with the notable exception of the header +row. Please see [Usage](#Usage) for an example. + +### `headers` + +Emitted after the header row is parsed. The first parameter of the event +callback is an `Array[String]` containing the header names. + +```js +fs.createReadStream('data.csv') + .pipe(csv()) + .on('headers', (headers) => { + console.log(`First header: ${headers[0]}`) + }) +``` + +### Readable Stream Events + +Events available on Node built-in +[Readable Streams](https://nodejs.org/api/stream.html#stream_class_stream_readable) +are also emitted. The `end` event should be used to detect the end of parsing. + +## CLI + +This module also provides a CLI which will convert CSV to +[newline-delimited](http://ndjson.org/) JSON. The following CLI flags can be +used to control how input is parsed: + +``` +Usage: csv-parser [filename?] [options] + + --escape,-e Set the escape character (defaults to quote value) + --headers,-h Explicitly specify csv headers as a comma separated list + --help Show this help + --output,-o Set output file. Defaults to stdout + --quote,-q Set the quote character ('"' by default) + --remove Remove columns from output by header name + --separator,-s Set the separator character ("," by default) + --skipComments,-c Skip CSV comments that begin with '#'. Set a value to change the comment character. + --skipLines,-l Set the number of lines to skip to before parsing headers + --strict Require column length match headers length + --version,-v Print out the installed version +``` + +For example; to parse a TSV file: + +``` +cat data.tsv | csv-parser -s $'\t' +``` + +## Encoding + +Users may encounter issues with the encoding of a CSV file. Transcoding the +source stream can be done neatly with a modules such as: +- [`iconv-lite`](https://www.npmjs.com/package/iconv-lite) +- [`iconv`](https://www.npmjs.com/package/iconv) + +Or native [`iconv`](http://man7.org/linux/man-pages/man1/iconv.1.html) if part +of a pipeline. + +## Byte Order Marks + +Some CSV files may be generated with, or contain a leading [Byte Order Mark](https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8). This may cause issues parsing headers and/or data from your file. From Wikipedia: + +>The Unicode Standard permits the BOM in UTF-8, but does not require nor recommend its use. Byte order has no meaning in UTF-8. + +To use this module with a file containing a BOM, please use a module like [strip-bom-stream](https://github.com/sindresorhus/strip-bom-stream) in your pipeline: + +```js +const fs = require('fs'); + +const csv = require('csv-parser'); +const stripBom = require('strip-bom-stream'); + +fs.createReadStream('data.csv') + .pipe(stripBom()) + .pipe(csv()) + ... +``` + +When using the CLI, the BOM can be removed by first running: + +```console +$ sed $'s/\xEF\xBB\xBF//g' data.csv +``` + +## Meta + +[CONTRIBUTING](./.github/CONTRIBUTING) + +[LICENSE (MIT)](./LICENSE) diff --git a/node_modules/csv-parser/bin/csv-parser b/node_modules/csv-parser/bin/csv-parser new file mode 100755 index 0000000..f895a8e --- /dev/null +++ b/node_modules/csv-parser/bin/csv-parser @@ -0,0 +1,94 @@ +#!/usr/bin/env node + +const { EOL } = require('os') +const minimist = require('minimist') +const { Transform } = require('stream'); +const fs = require('fs') +const csv = require('../') +const pkg = require('../package.json') + +const argv = minimist(process.argv, { + alias: { + c: 'skipComments', + e: 'escape', + h: 'headers', + o: 'output', + q: 'quote', + l: 'skipLines', + s: 'separator', + v: 'version' + }, + default: { + e: '"', + q: '"', + s: ',' + }, + boolean: ['version', 'help'] +}) + +const [,, filename] = argv._ + +if (argv.version) { + console.log(pkg.version) + process.exit(0) +} + +if (argv.help || (process.stdin.isTTY && !filename)) { + console.error(`Usage: csv-parser [filename?] [options] + --escape,-e Set the escape character (defaults to quote value) + --headers,-h Explicitly specify csv headers as a comma separated list + --help Show this help + --output,-o Set output file. Defaults to stdout + --quote,-q Set the quote character ('"' by default) + --remove Remove headers from output + --separator,-s Set the separator character ("," by default) + --skipComments,-c Skip CSV comments that begin with '#'. Set a value to change the comment character. + --skipLines,-l Set the number of lines to skip to before parsing headers + --strict Require column length match headers length + --version,-v Print out the installed version +`) + process.exit(1) +} + +let input +const output = (argv.output && argv.output !== '-') ? fs.createWriteStream(argv.output) : process.stdout +const options = { + separator: argv.separator, + strict: argv.strict, + skipComments: argv.skipComments, + skipLines: argv.skipLines +} + +if (argv.headers) { + options.headers = argv.headers.toString().split(argv.separator) +} + +if (argv.remove) { + const removeHeaders = argv.remove.split(',') + options.mapHeaders = (name, i) => { + return removeHeaders.indexOf(name) === -1 ? name : null + } +} + +if (filename === '-' || !filename) { + input = process.stdin +} else if (fs.existsSync(filename)) { + input = fs.createReadStream(filename) +} else { + console.error(`File: ${filename} does not exist`) + process.exit(2) +} + +const serialize = () => { + return new Transform({ + objectMode: true, + transform(obj, enc, cb) { + cb(null, JSON.stringify(obj) + EOL) + } + }); +} + +input + .pipe(csv(options)) + .pipe(serialize()) + .pipe(output) diff --git a/node_modules/csv-parser/index.d.ts b/node_modules/csv-parser/index.d.ts new file mode 100644 index 0000000..a6a400d --- /dev/null +++ b/node_modules/csv-parser/index.d.ts @@ -0,0 +1,146 @@ +/// +import { Transform } from 'stream'; + +declare namespace csvParser { + type CsvParser = Transform; + + interface Options { + /** + * A single-character string used to specify the character used to escape strings in a CSV row. + * + * @default '"' + */ + readonly escape?: string; + + /** + * Specifies the headers to use. Headers define the property key for each value in a CSV row. If no `headers` option is provided, `csv-parser` will use the first line in a CSV file as the header specification. + * + * If `false`, specifies that the first row in a data file does _not_ contain headers, and instructs the parser to use the row index as the key for each row. + * + * Suppose you have a CSV file `data.csv` which contains the data: + * + * ``` +NAME,AGE +Daffy Duck,24 +Bugs Bunny,22 +``` + * Using `headers: false` with the data from `data.csv` would yield: + * ``` +[ + { '0': 'Daffy Duck', '1': 24 }, + { '0': 'Bugs Bunny', '1': 22 } +] +``` + */ + readonly headers?: ReadonlyArray | boolean; + + /** + * A function that can be used to modify the values of each header. Return `null` to remove the header, and it's column, from the results. + * + * @example + * + * csv({ + * mapHeaders: ({ header, index }) => header.toLowerCase() + * }); + */ + readonly mapHeaders?: (args: { header: string; index: number }) => string | null; + + /** + * A function that can be used to modify the value of each column value. + * + * @example + * + * csv({ + * mapValues: ({ header, index, value }) => value.toLowerCase() + * }); + */ + readonly mapValues?: (args: { header: string; index: number; value: any }) => any; + + /** + * Specifies a single-character string to denote the end of a line in a CSV file. + * + * @default '\n' + */ + readonly newline?: string; + + /** + * Specifies a single-character string to denote a quoted string. + * + * @default '"' + */ + readonly quote?: string; + + /** + * If `true`, instructs the parser not to decode UTF-8 strings. + */ + readonly raw?: boolean; + + /** + * Specifies a single-character string to use as the column separator for each row. + * + * @default ',' + */ + readonly separator?: string; + + /** + * Instructs the parser to ignore lines which represent comments in a CSV file. Since there is no specification that dictates what a CSV comment looks like, comments should be considered non-standard. The "most common" character used to signify a comment in a CSV file is `"#"`. If this option is set to `true`, lines which begin with `#` will be skipped. If a custom character is needed to denote a commented line, this option may be set to a string which represents the leading character(s) signifying a comment line. + * + * @default false + */ + readonly skipComments?: boolean | string; + + /** + * Specifies the number of lines at the beginning of a data file that the parser should skip over, prior to parsing headers. + * + * @default 0 + */ + readonly skipLines?: number; + + /** + * Maximum number of bytes per row. An error is thrown if a line exeeds this value. The default value is on 8 peta byte. + * + * @default Number.MAX_SAFE_INTEGER + */ + readonly maxRowBytes?: number; + + /** + * If `true`, instructs the parser that the number of columns in each row must match the number of `headers` specified. + */ + readonly strict?: boolean; + } +} + +/** + * Streaming CSV parser that aims for maximum speed as well as compatibility with the [csv-spectrum](https://npmjs.org/csv-spectrum) CSV acid test suite. + * + * @param optionsOrHeaders - As an alternative to passing an `options` object, you may pass an `Array[String]` which specifies the headers to use. If you need to specify options _and_ headers, please use the the object notation with the `headers` property. + * + * @example + * + * // data.csv: + * // + * // NAME,AGE + * // Daffy Duck,24 + * // Bugs Bunny,22 + * + * import csv = require('csv-parser'); + * import * as fs from 'fs'; + * + * const results = []; + * + * fs.createReadStream('data.csv') + * .pipe(csv()) + * .on('data', (data) => results.push(data)) + * .on('end', () => { + * console.log(results); + * // [ + * // { NAME: 'Daffy Duck', AGE: '24' }, + * // { NAME: 'Bugs Bunny', AGE: '22' } + * // ] + * }); + */ +declare const csvParser: ( + optionsOrHeaders?: csvParser.Options | ReadonlyArray +) => csvParser.CsvParser; + +export = csvParser; diff --git a/node_modules/csv-parser/index.js b/node_modules/csv-parser/index.js new file mode 100644 index 0000000..2a6a2da --- /dev/null +++ b/node_modules/csv-parser/index.js @@ -0,0 +1,275 @@ +const { Transform } = require('stream') + +const [cr] = Buffer.from('\r') +const [nl] = Buffer.from('\n') +const defaults = { + escape: '"', + headers: null, + mapHeaders: ({ header }) => header, + mapValues: ({ value }) => value, + newline: '\n', + quote: '"', + raw: false, + separator: ',', + skipComments: false, + skipLines: null, + maxRowBytes: Number.MAX_SAFE_INTEGER, + strict: false +} + +class CsvParser extends Transform { + constructor (opts = {}) { + super({ objectMode: true, highWaterMark: 16 }) + + if (Array.isArray(opts)) opts = { headers: opts } + + const options = Object.assign({}, defaults, opts) + + options.customNewline = options.newline !== defaults.newline + + for (const key of ['newline', 'quote', 'separator']) { + if (typeof options[key] !== 'undefined') { + ([options[key]] = Buffer.from(options[key])) + } + } + + // if escape is not defined on the passed options, use the end value of quote + options.escape = (opts || {}).escape ? Buffer.from(options.escape)[0] : options.quote + + this.state = { + empty: options.raw ? Buffer.alloc(0) : '', + escaped: false, + first: true, + lineNumber: 0, + previousEnd: 0, + rowLength: 0, + quoted: false + } + + this._prev = null + + if (options.headers === false) { + // enforce, as the column length check will fail if headers:false + options.strict = false + } + + if (options.headers || options.headers === false) { + this.state.first = false + } + + this.options = options + this.headers = options.headers + } + + parseCell (buffer, start, end) { + const { escape, quote } = this.options + // remove quotes from quoted cells + if (buffer[start] === quote && buffer[end - 1] === quote) { + start++ + end-- + } + + let y = start + + for (let i = start; i < end; i++) { + // check for escape characters and skip them + if (buffer[i] === escape && i + 1 < end && buffer[i + 1] === quote) { + i++ + } + + if (y !== i) { + buffer[y] = buffer[i] + } + y++ + } + + return this.parseValue(buffer, start, y) + } + + parseLine (buffer, start, end) { + const { customNewline, escape, mapHeaders, mapValues, quote, separator, skipComments, skipLines } = this.options + + end-- // trim newline + if (!customNewline && buffer.length && buffer[end - 1] === cr) { + end-- + } + + const comma = separator + const cells = [] + let isQuoted = false + let offset = start + + if (skipComments) { + const char = typeof skipComments === 'string' ? skipComments : '#' + if (buffer[start] === Buffer.from(char)[0]) { + return + } + } + + const mapValue = (value) => { + if (this.state.first) { + return value + } + + const index = cells.length + const header = this.headers[index] + + return mapValues({ header, index, value }) + } + + for (let i = start; i < end; i++) { + const isStartingQuote = !isQuoted && buffer[i] === quote + const isEndingQuote = isQuoted && buffer[i] === quote && i + 1 <= end && buffer[i + 1] === comma + const isEscape = isQuoted && buffer[i] === escape && i + 1 < end && buffer[i + 1] === quote + + if (isStartingQuote || isEndingQuote) { + isQuoted = !isQuoted + continue + } else if (isEscape) { + i++ + continue + } + + if (buffer[i] === comma && !isQuoted) { + let value = this.parseCell(buffer, offset, i) + value = mapValue(value) + cells.push(value) + offset = i + 1 + } + } + + if (offset < end) { + let value = this.parseCell(buffer, offset, end) + value = mapValue(value) + cells.push(value) + } + + if (buffer[end - 1] === comma) { + cells.push(mapValue(this.state.empty)) + } + + const skip = skipLines && skipLines > this.state.lineNumber + this.state.lineNumber++ + + if (this.state.first && !skip) { + this.state.first = false + this.headers = cells.map((header, index) => mapHeaders({ header, index })) + + this.emit('headers', this.headers) + return + } + + if (!skip && this.options.strict && cells.length !== this.headers.length) { + const e = new RangeError('Row length does not match headers') + this.emit('error', e) + } else { + if (!skip) this.writeRow(cells) + } + } + + parseValue (buffer, start, end) { + if (this.options.raw) { + return buffer.slice(start, end) + } + + return buffer.toString('utf-8', start, end) + } + + writeRow (cells) { + const headers = (this.headers === false) ? cells.map((value, index) => index) : this.headers + + const row = cells.reduce((o, cell, index) => { + const header = headers[index] + if (header === null) return o // skip columns + if (header !== undefined) { + o[header] = cell + } else { + o[`_${index}`] = cell + } + return o + }, {}) + + this.push(row) + } + + _flush (cb) { + if (this.state.escaped || !this._prev) return cb() + this.parseLine(this._prev, this.state.previousEnd, this._prev.length + 1) // plus since online -1s + cb() + } + + _transform (data, enc, cb) { + if (typeof data === 'string') { + data = Buffer.from(data) + } + + const { escape, quote } = this.options + let start = 0 + let buffer = data + + if (this._prev) { + start = this._prev.length + buffer = Buffer.concat([this._prev, data]) + this._prev = null + } + + const bufferLength = buffer.length + + for (let i = start; i < bufferLength; i++) { + const chr = buffer[i] + const nextChr = i + 1 < bufferLength ? buffer[i + 1] : null + + this.state.rowLength++ + if (this.state.rowLength > this.options.maxRowBytes) { + return cb(new Error('Row exceeds the maximum size')) + } + + if (!this.state.escaped && chr === escape && nextChr === quote && i !== start) { + this.state.escaped = true + continue + } else if (chr === quote) { + if (this.state.escaped) { + this.state.escaped = false + // non-escaped quote (quoting the cell) + } else { + this.state.quoted = !this.state.quoted + } + continue + } + + if (!this.state.quoted) { + if (this.state.first && !this.options.customNewline) { + if (chr === nl) { + this.options.newline = nl + } else if (chr === cr) { + if (nextChr !== nl) { + this.options.newline = cr + } + } + } + + if (chr === this.options.newline) { + this.parseLine(buffer, this.state.previousEnd, i + 1) + this.state.previousEnd = i + 1 + this.state.rowLength = 0 + } + } + } + + if (this.state.previousEnd === bufferLength) { + this.state.previousEnd = 0 + return cb() + } + + if (bufferLength - this.state.previousEnd < data.length) { + this._prev = data + this.state.previousEnd -= (bufferLength - data.length) + return cb() + } + + this._prev = buffer + cb() + } +} + +module.exports = (opts) => new CsvParser(opts) diff --git a/node_modules/csv-parser/package.json b/node_modules/csv-parser/package.json new file mode 100644 index 0000000..7e22065 --- /dev/null +++ b/node_modules/csv-parser/package.json @@ -0,0 +1,92 @@ +{ + "name": "csv-parser", + "version": "3.0.0", + "description": "Streaming CSV parser that aims for maximum speed as well as compatibility with the csv-spectrum test suite", + "license": "MIT", + "repository": "mafintosh/csv-parser", + "author": "mafintosh", + "maintainers": [ + "Andrew Powell " + ], + "homepage": "https://github.com/mafintosh/csv-parser", + "bugs": "https://github.com/mafintosh/csv-parser/issues", + "bin": { + "csv-parser": "./bin/csv-parser" + }, + "main": "index.js", + "files": [ + "bin/csv-parser", + "index.js", + "index.d.ts" + ], + "engines": { + "node": ">= 10" + }, + "scripts": { + "bench": "bin/bench", + "commitlint": "commitlint", + "coverage": "nyc npm run test && nyc report --reporter=text-lcov > coverage.lcov", + "lint": "eslint .", + "lint-staged": "lint-staged", + "security": "npm audit", + "test": "ava && tsd" + }, + "dependencies": { + "minimist": "^1.2.0" + }, + "devDependencies": { + "@commitlint/cli": "^8.2.0", + "@commitlint/config-conventional": "^8.0.0", + "@types/node": "^12.0.0", + "ava": "^2.4.0", + "bops": "^1.0.0", + "chalk": "^2.4.2", + "concat-stream": "^2.0.0", + "csv-spectrum": "^1.0.0", + "eslint": "^6.4.0", + "eslint-config-standard": "^14.1.0", + "eslint-plugin-import": "^2.18.2", + "eslint-plugin-node": "^10.0.0", + "eslint-plugin-promise": "^4.1.1", + "eslint-plugin-standard": "^4.0.0", + "execa": "^2.1.0", + "globby": "^10.0.1", + "husky": "^3.0.0", + "lint-staged": "^9.0.2", + "loud-rejection": "^2.1.0", + "nyc": "^14.1.1", + "pre-commit": "^1.2.2", + "strip-ansi": "^5.2.0", + "text-table": "^0.2.0", + "time-span": "^3.1.0", + "tsd": "^0.8.0" + }, + "directories": { + "example": "examples", + "test": "test" + }, + "keywords": [ + "csv", + "parser", + "fast", + "json" + ], + "ava": { + "files": [ + "!**/fixtures/**", + "!**/helpers/**" + ] + }, + "husky": { + "hooks": { + "commit-msg": "commitlint -e $HUSKY_GIT_PARAMS" + } + }, + "lint-staged": { + "*.js": [ + "eslint --fix", + "git add" + ] + }, + "pre-commit": "lint-staged" +} diff --git a/node_modules/csv-writer/CHANGELOG.md b/node_modules/csv-writer/CHANGELOG.md new file mode 100644 index 0000000..08629d6 --- /dev/null +++ b/node_modules/csv-writer/CHANGELOG.md @@ -0,0 +1,58 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [1.6.0] - 2020-01-18 +### Added +- Support for specifying values in nested objects. [#34](https://github.com/ryu1kn/csv-writer/pull/34) + +## [1.5.0] - 2019-07-13 +### Added +- Added `alwaysQuote` flag to always double-quote all fields. [#21](https://github.com/ryu1kn/csv-writer/pull/21) + +## [1.4.0] - 2019-06-19 +### Added +- Allow CRLF as a record delimiter. [#27](https://github.com/ryu1kn/csv-writer/pull/27) + +## [1.3.0] - 2019-04-19 +### Changed +- Changed project language from JavaScript to TypeScript. + +### Added +- Made TypeScript type definitions accessible. Thanks to @coyotte508. + [PR #23](https://github.com/ryu1kn/csv-writer/pull/23) + +## [1.2.0] - 2018-08-22 +### Added +- CSV records are now not limited to an array but can be an iterable object. Thanks to @pineapplemachine. + [PR #11](https://github.com/ryu1kn/csv-writer/pull/11) + +## [1.1.0] - 2018-08-20 +### Added +- Allow semicolon as a field delimiter as it is commonly used in CSV in some regions. Thanks to @HKskn. + [PR #8](https://github.com/ryu1kn/csv-writer/pull/8), [#6](https://github.com/ryu1kn/csv-writer/pull/6) + +## [1.0.1] - 2018-08-09 +### Fixed +- Fixed the issue that coverage report badge on README shows question mark. + Use Coveralls instead of CodeClimate to get code coverage. + +## [1.0.0] - 2018-02-28 +### Added +- Support for adding CSV records to already existing files. Thanks to @jonmelcher. [PR #4](https://github.com/ryu1kn/csv-writer/pull/4) + +## [0.0.3] - 2016-11-09 +### Fixed +- Fixed the bug that fields were not always surrounded by double quotes +- Fixed the bug that white space characters on the edge of fields were trimmed + +## [0.0.2] - 2016-10-15 +### Fixed +- Fixed the bug that field values were not quoted when they have newline characters + +## [0.0.1] - 2016-09-09 +### Added +- Initial release of csv-writer diff --git a/node_modules/csv-writer/README.md b/node_modules/csv-writer/README.md new file mode 100644 index 0000000..6fc8580 --- /dev/null +++ b/node_modules/csv-writer/README.md @@ -0,0 +1,328 @@ +[![Build Status](https://travis-ci.org/ryu1kn/csv-writer.svg?branch=master)](https://travis-ci.org/ryu1kn/csv-writer) +[![Coverage Status](https://coveralls.io/repos/github/ryu1kn/csv-writer/badge.svg?branch=master)](https://coveralls.io/github/ryu1kn/csv-writer?branch=master) +[![Code Climate](https://codeclimate.com/github/ryu1kn/csv-writer/badges/gpa.svg)](https://codeclimate.com/github/ryu1kn/csv-writer) + +# CSV Writer + +Convert objects/arrays into a CSV string or write them into a file. +It respects [RFC 4180](https://tools.ietf.org/html/rfc4180) for the output CSV format. + +## Prerequisite + +* Node version 4 or above + +## Usage + +The example below shows how you can write records defined as the array of objects into a file. + +```js +const createCsvWriter = require('csv-writer').createObjectCsvWriter; +const csvWriter = createCsvWriter({ + path: 'path/to/file.csv', + header: [ + {id: 'name', title: 'NAME'}, + {id: 'lang', title: 'LANGUAGE'} + ] +}); + +const records = [ + {name: 'Bob', lang: 'French, English'}, + {name: 'Mary', lang: 'English'} +]; + +csvWriter.writeRecords(records) // returns a promise + .then(() => { + console.log('...Done'); + }); + +// This will produce a file path/to/file.csv with following contents: +// +// NAME,LANGUAGE +// Bob,"French, English" +// Mary,English +``` + +You can keep writing records into the same file by calling `writeRecords` multiple times +(but need to wait for the fulfillment of the `promise` of the previous `writeRecords` call). + +```js +// In an `async` function +await csvWriter.writeRecords(records1) +await csvWriter.writeRecords(records2) +... +``` + +However, if you need to keep writing large data to a certain file, you would want to create +node's transform stream and use `CsvStringifier`, which is explained later, inside it +, and pipe the stream into a file write stream. + +If you don't want to write a header line, don't give `title` to header elements and just give field IDs as a string. + +```js +const createCsvWriter = require('csv-writer').createObjectCsvWriter; +const csvWriter = createCsvWriter({ + path: 'path/to/file.csv', + header: ['name', 'lang'] +}); +``` + +If each record is defined as an array, use `createArrayCsvWriter` to get an `csvWriter`. + +```js +const createCsvWriter = require('csv-writer').createArrayCsvWriter; +const csvWriter = createCsvWriter({ + header: ['NAME', 'LANGUAGE'], + path: 'path/to/file.csv' +}); + +const records = [ + ['Bob', 'French, English'], + ['Mary', 'English'] +]; + +csvWriter.writeRecords(records) // returns a promise + .then(() => { + console.log('...Done'); + }); + +// This will produce a file path/to/file.csv with following contents: +// +// NAME,LANGUAGE +// Bob,"French, English" +// Mary,English +``` + +If you just want to get a CSV string but don't want to write into a file, +you can use `createObjectCsvStringifier` (or `createArrayCsvStringifier`) +to get an `csvStringifier`. + +```js +const createCsvStringifier = require('csv-writer').createObjectCsvStringifier; +const csvStringifier = createCsvStringifier({ + header: [ + {id: 'name', title: 'NAME'}, + {id: 'lang', title: 'LANGUAGE'} + ] +}); + +const records = [ + {name: 'Bob', lang: 'French, English'}, + {name: 'Mary', lang: 'English'} +]; + +console.log(csvStringifier.getHeaderString()); +// => 'NAME,LANGUAGE\n' + +console.log(csvStringifier.stringifyRecords(records)); +// => 'Bob,"French, English"\nMary,English\n' +``` + + +## API + +### createObjectCsvWriter(params) + +##### Parameters: + +* params `` + * path `` + + Path to a write file + + * header `>` + + Array of objects (`id` and `title` properties) or strings (field IDs). + A header line will be written to the file only if given as an array of objects. + + * fieldDelimiter `` (optional) + + Default: `,`. Only either comma `,` or semicolon `;` is allowed. + + * recordDelimiter `` (optional) + + Default: `\n`. Only either LF (`\n`) or CRLF (`\r\n`) is allowed. + + * headerIdDelimiter `` (optional) + + Default: `undefined`. Give this value to specify a path to a value in a nested object. + + * alwaysQuote `` (optional) + + Default: `false`. Set it to `true` to double-quote all fields regardless of their values. + + * encoding `` (optional) + + Default: `utf8`. + + * append `` (optional) + + Default: `false`. When `true`, it will append CSV records to the specified file. + If the file doesn't exist, it will create one. + + **NOTE:** A header line will not be written to the file if `true` is given. + +##### Returns: + +* `` + + +### createArrayCsvWriter(params) + +##### Parameters: + +* params `` + * path `` + + Path to a write file + + * header `>` (optional) + + Array of field titles + + * fieldDelimiter `` (optional) + + Default: `,`. Only either comma `,` or semicolon `;` is allowed. + + * recordDelimiter `` (optional) + + Default: `\n`. Only either LF (`\n`) or CRLF (`\r\n`) is allowed. + + * alwaysQuote `` (optional) + + Default: `false`. Set it to `true` to double-quote all fields regardless of their values. + + * encoding `` (optional) + + Default: `utf8`. + + * append `` (optional) + + Default: `false`. When `true`, it will append CSV records to the specified file. + If the file doesn't exist, it will create one. + + **NOTE:** A header line will not be written to the file if `true` is given. + +##### Returns: + +* `` + + +### CsvWriter#writeRecords(records) + +##### Parameters: + +* records `>` + + Depending on which function was used to create a `csvWriter` (i.e. `createObjectCsvWriter` or `createArrayCsvWriter`), + records will be either a collection of objects or arrays. As long as the collection is iterable, it doesn't need to be an array. + +##### Returns: + +* `` + + +### createObjectCsvStringifier(params) + +##### Parameters: + +* params `` + * header `>` + + Array of objects (`id` and `title` properties) or strings (field IDs) + + * fieldDelimiter `` (optional) + + Default: `,`. Only either comma `,` or semicolon `;` is allowed. + + * recordDelimiter `` (optional) + + Default: `\n`. Only either LF (`\n`) or CRLF (`\r\n`) is allowed. + + * headerIdDelimiter `` (optional) + + Default: `undefined`. Give this value to specify a path to a value in a nested object. + + * alwaysQuote `` (optional) + + Default: `false`. Set it to `true` to double-quote all fields regardless of their values. + +##### Returns: + +* `` + +### ObjectCsvStringifier#getHeaderString() + +##### Returns: + +* `` + +### ObjectCsvStringifier#stringifyRecords(records) + +##### Parameters: + +* records `>` + +##### Returns: + +* `` + +### createArrayCsvStringifier(params) + +##### Parameters: + +* params `` + * header `>` (optional) + + Array of field titles + + * fieldDelimiter `` (optional) + + Default: `,`. Only either comma `,` or semicolon `;` is allowed. + + * recordDelimiter `` (optional) + + Default: `\n`. Only either LF (`\n`) or CRLF (`\r\n`) is allowed. + + * alwaysQuote `` (optional) + + Default: `false`. Set it to `true` to double-quote all fields regardless of their values. + +##### Returns: + +* `` + +### ArrayCsvStringifier#getHeaderString() + +##### Returns: + +* `` + +### ArrayCsvStringifier#stringifyRecords(records) + +##### Parameters: + +* records `>>` + +##### Returns: + +* `` + + +## Request Features or Report Bugs + +Feature requests and bug reports are very welcome: https://github.com/ryu1kn/csv-writer/issues + +A couple of requests from me when you raise an issue on GitHub. + +* **Requesting a feature:** Please try to provide the context of why you want the feature. Such as, + in what situation the feature could help you and how, or how the lack of the feature is causing an inconvenience to you. + I can't start thinking of introducing it until I understand how it helps you 🙂 +* **Reporting a bug:** If you could provide a runnable code snippet that reproduces the bug, it would be very helpful! + + +## Development + +### Prerequisite + +* Node version 8 or above +* Docker diff --git a/node_modules/csv-writer/dist/index.js b/node_modules/csv-writer/dist/index.js new file mode 100644 index 0000000..2c877d1 --- /dev/null +++ b/node_modules/csv-writer/dist/index.js @@ -0,0 +1,19 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var csv_stringifier_factory_1 = require("./lib/csv-stringifier-factory"); +var csv_writer_factory_1 = require("./lib/csv-writer-factory"); +var csvStringifierFactory = new csv_stringifier_factory_1.CsvStringifierFactory(); +var csvWriterFactory = new csv_writer_factory_1.CsvWriterFactory(csvStringifierFactory); +exports.createArrayCsvStringifier = function (params) { + return csvStringifierFactory.createArrayCsvStringifier(params); +}; +exports.createObjectCsvStringifier = function (params) { + return csvStringifierFactory.createObjectCsvStringifier(params); +}; +exports.createArrayCsvWriter = function (params) { + return csvWriterFactory.createArrayCsvWriter(params); +}; +exports.createObjectCsvWriter = function (params) { + return csvWriterFactory.createObjectCsvWriter(params); +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/index.js.map b/node_modules/csv-writer/dist/index.js.map new file mode 100644 index 0000000..d14eb82 --- /dev/null +++ b/node_modules/csv-writer/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,yEAIuC;AACvC,+DAAuG;AAEvG,IAAM,qBAAqB,GAAG,IAAI,+CAAqB,EAAE,CAAC;AAC1D,IAAM,gBAAgB,GAAG,IAAI,qCAAgB,CAAC,qBAAqB,CAAC,CAAC;AAExD,QAAA,yBAAyB,GAAG,UAAC,MAAiC;IACnE,OAAA,qBAAqB,CAAC,yBAAyB,CAAC,MAAM,CAAC;AAAvD,CAAuD,CAAC;AAEnD,QAAA,0BAA0B,GAAG,UAAC,MAAkC;IACrE,OAAA,qBAAqB,CAAC,0BAA0B,CAAC,MAAM,CAAC;AAAxD,CAAwD,CAAC;AAEpD,QAAA,oBAAoB,GAAG,UAAC,MAA4B;IACzD,OAAA,gBAAgB,CAAC,oBAAoB,CAAC,MAAM,CAAC;AAA7C,CAA6C,CAAC;AAEzC,QAAA,qBAAqB,GAAG,UAAC,MAA6B;IAC3D,OAAA,gBAAgB,CAAC,qBAAqB,CAAC,MAAM,CAAC;AAA9C,CAA8C,CAAC"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/csv-stringifier-factory.js b/node_modules/csv-writer/dist/lib/csv-stringifier-factory.js new file mode 100644 index 0000000..20c2fc9 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/csv-stringifier-factory.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var array_1 = require("./csv-stringifiers/array"); +var field_stringifier_1 = require("./field-stringifier"); +var object_1 = require("./csv-stringifiers/object"); +var CsvStringifierFactory = /** @class */ (function () { + function CsvStringifierFactory() { + } + CsvStringifierFactory.prototype.createArrayCsvStringifier = function (params) { + var fieldStringifier = field_stringifier_1.createFieldStringifier(params.fieldDelimiter, params.alwaysQuote); + return new array_1.ArrayCsvStringifier(fieldStringifier, params.recordDelimiter, params.header); + }; + CsvStringifierFactory.prototype.createObjectCsvStringifier = function (params) { + var fieldStringifier = field_stringifier_1.createFieldStringifier(params.fieldDelimiter, params.alwaysQuote); + return new object_1.ObjectCsvStringifier(fieldStringifier, params.header, params.recordDelimiter, params.headerIdDelimiter); + }; + return CsvStringifierFactory; +}()); +exports.CsvStringifierFactory = CsvStringifierFactory; +//# sourceMappingURL=csv-stringifier-factory.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/csv-stringifier-factory.js.map b/node_modules/csv-writer/dist/lib/csv-stringifier-factory.js.map new file mode 100644 index 0000000..a8ca3f2 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/csv-stringifier-factory.js.map @@ -0,0 +1 @@ +{"version":3,"file":"csv-stringifier-factory.js","sourceRoot":"","sources":["../../src/lib/csv-stringifier-factory.ts"],"names":[],"mappings":";;AAAA,kDAA6D;AAC7D,yDAA2D;AAC3D,oDAA+D;AAkB/D;IAAA;IAYA,CAAC;IAVG,yDAAyB,GAAzB,UAA0B,MAAiC;QACvD,IAAM,gBAAgB,GAAG,0CAAsB,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAC3F,OAAO,IAAI,2BAAmB,CAAC,gBAAgB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5F,CAAC;IAED,0DAA0B,GAA1B,UAA2B,MAAkC;QACzD,IAAM,gBAAgB,GAAG,0CAAsB,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAC3F,OAAO,IAAI,6BAAoB,CAAC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACvH,CAAC;IAEL,4BAAC;AAAD,CAAC,AAZD,IAYC;AAZY,sDAAqB"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/csv-stringifiers/abstract.js b/node_modules/csv-writer/dist/lib/csv-stringifiers/abstract.js new file mode 100644 index 0000000..dcade06 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/csv-stringifiers/abstract.js @@ -0,0 +1,38 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var DEFAULT_RECORD_DELIMITER = '\n'; +var VALID_RECORD_DELIMITERS = [DEFAULT_RECORD_DELIMITER, '\r\n']; +var CsvStringifier = /** @class */ (function () { + function CsvStringifier(fieldStringifier, recordDelimiter) { + if (recordDelimiter === void 0) { recordDelimiter = DEFAULT_RECORD_DELIMITER; } + this.fieldStringifier = fieldStringifier; + this.recordDelimiter = recordDelimiter; + _validateRecordDelimiter(recordDelimiter); + } + CsvStringifier.prototype.getHeaderString = function () { + var headerRecord = this.getHeaderRecord(); + return headerRecord ? this.joinRecords([this.getCsvLine(headerRecord)]) : null; + }; + CsvStringifier.prototype.stringifyRecords = function (records) { + var _this = this; + var csvLines = Array.from(records, function (record) { return _this.getCsvLine(_this.getRecordAsArray(record)); }); + return this.joinRecords(csvLines); + }; + CsvStringifier.prototype.getCsvLine = function (record) { + var _this = this; + return record + .map(function (fieldValue) { return _this.fieldStringifier.stringify(fieldValue); }) + .join(this.fieldStringifier.fieldDelimiter); + }; + CsvStringifier.prototype.joinRecords = function (records) { + return records.join(this.recordDelimiter) + this.recordDelimiter; + }; + return CsvStringifier; +}()); +exports.CsvStringifier = CsvStringifier; +function _validateRecordDelimiter(delimiter) { + if (VALID_RECORD_DELIMITERS.indexOf(delimiter) === -1) { + throw new Error("Invalid record delimiter `" + delimiter + "` is specified"); + } +} +//# sourceMappingURL=abstract.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/csv-stringifiers/abstract.js.map b/node_modules/csv-writer/dist/lib/csv-stringifiers/abstract.js.map new file mode 100644 index 0000000..6e5151b --- /dev/null +++ b/node_modules/csv-writer/dist/lib/csv-stringifiers/abstract.js.map @@ -0,0 +1 @@ +{"version":3,"file":"abstract.js","sourceRoot":"","sources":["../../../src/lib/csv-stringifiers/abstract.ts"],"names":[],"mappings":";;AAGA,IAAM,wBAAwB,GAAG,IAAI,CAAC;AACtC,IAAM,uBAAuB,GAAG,CAAC,wBAAwB,EAAE,MAAM,CAAC,CAAC;AAEnE;IAEI,wBAA6B,gBAAkC,EAClC,eAA0C;QAA1C,gCAAA,EAAA,0CAA0C;QAD1C,qBAAgB,GAAhB,gBAAgB,CAAkB;QAClC,oBAAe,GAAf,eAAe,CAA2B;QACnE,wBAAwB,CAAC,eAAe,CAAC,CAAC;IAC9C,CAAC;IAED,wCAAe,GAAf;QACI,IAAM,YAAY,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QAC5C,OAAO,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACnF,CAAC;IAED,yCAAgB,GAAhB,UAAiB,OAAkC;QAAnD,iBAGC;QAFG,IAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,UAAA,MAAM,IAAI,OAAA,KAAI,CAAC,UAAU,CAAC,KAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,EAA9C,CAA8C,CAAC,CAAC;QAC/F,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;IAMO,mCAAU,GAAlB,UAAmB,MAAe;QAAlC,iBAIC;QAHG,OAAO,MAAM;aACR,GAAG,CAAC,UAAA,UAAU,IAAI,OAAA,KAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,UAAU,CAAC,EAA3C,CAA2C,CAAC;aAC9D,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;IACpD,CAAC;IAEO,oCAAW,GAAnB,UAAoB,OAAiB;QACjC,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC;IACrE,CAAC;IACL,qBAAC;AAAD,CAAC,AA9BD,IA8BC;AA9BqB,wCAAc;AAgCpC,SAAS,wBAAwB,CAAC,SAAiB;IAC/C,IAAI,uBAAuB,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE;QACnD,MAAM,IAAI,KAAK,CAAC,+BAA8B,SAAS,mBAAiB,CAAC,CAAC;KAC7E;AACL,CAAC"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/csv-stringifiers/array.js b/node_modules/csv-writer/dist/lib/csv-stringifiers/array.js new file mode 100644 index 0000000..5508a57 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/csv-stringifiers/array.js @@ -0,0 +1,33 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var abstract_1 = require("./abstract"); +var ArrayCsvStringifier = /** @class */ (function (_super) { + __extends(ArrayCsvStringifier, _super); + function ArrayCsvStringifier(fieldStringifier, recordDelimiter, header) { + var _this = _super.call(this, fieldStringifier, recordDelimiter) || this; + _this.header = header; + return _this; + } + ArrayCsvStringifier.prototype.getHeaderRecord = function () { + return this.header; + }; + ArrayCsvStringifier.prototype.getRecordAsArray = function (record) { + return record; + }; + return ArrayCsvStringifier; +}(abstract_1.CsvStringifier)); +exports.ArrayCsvStringifier = ArrayCsvStringifier; +//# sourceMappingURL=array.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/csv-stringifiers/array.js.map b/node_modules/csv-writer/dist/lib/csv-stringifiers/array.js.map new file mode 100644 index 0000000..36fcb18 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/csv-stringifiers/array.js.map @@ -0,0 +1 @@ +{"version":3,"file":"array.js","sourceRoot":"","sources":["../../../src/lib/csv-stringifiers/array.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,uCAA0C;AAI1C;IAAyC,uCAAuB;IAE5D,6BAAY,gBAAkC,EAClC,eAAwB,EACP,MAAiB;QAF9C,YAGI,kBAAM,gBAAgB,EAAE,eAAe,CAAC,SAC3C;QAF4B,YAAM,GAAN,MAAM,CAAW;;IAE9C,CAAC;IAES,6CAAe,GAAzB;QACI,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAES,8CAAgB,GAA1B,UAA2B,MAAe;QACtC,OAAO,MAAM,CAAC;IAClB,CAAC;IACL,0BAAC;AAAD,CAAC,AAfD,CAAyC,yBAAc,GAetD;AAfY,kDAAmB"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/csv-stringifiers/object.js b/node_modules/csv-writer/dist/lib/csv-stringifiers/object.js new file mode 100644 index 0000000..4d74e01 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/csv-stringifiers/object.js @@ -0,0 +1,57 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var abstract_1 = require("./abstract"); +var object_1 = require("../lang/object"); +var ObjectCsvStringifier = /** @class */ (function (_super) { + __extends(ObjectCsvStringifier, _super); + function ObjectCsvStringifier(fieldStringifier, header, recordDelimiter, headerIdDelimiter) { + var _this = _super.call(this, fieldStringifier, recordDelimiter) || this; + _this.header = header; + _this.headerIdDelimiter = headerIdDelimiter; + return _this; + } + ObjectCsvStringifier.prototype.getHeaderRecord = function () { + if (!this.isObjectHeader) + return null; + return this.header.map(function (field) { return field.title; }); + }; + ObjectCsvStringifier.prototype.getRecordAsArray = function (record) { + var _this = this; + return this.fieldIds.map(function (fieldId) { return _this.getNestedValue(record, fieldId); }); + }; + ObjectCsvStringifier.prototype.getNestedValue = function (obj, key) { + if (!this.headerIdDelimiter) + return obj[key]; + return key.split(this.headerIdDelimiter).reduce(function (subObj, keyPart) { return (subObj || {})[keyPart]; }, obj); + }; + Object.defineProperty(ObjectCsvStringifier.prototype, "fieldIds", { + get: function () { + return this.isObjectHeader ? this.header.map(function (column) { return column.id; }) : this.header; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ObjectCsvStringifier.prototype, "isObjectHeader", { + get: function () { + return object_1.isObject(this.header && this.header[0]); + }, + enumerable: true, + configurable: true + }); + return ObjectCsvStringifier; +}(abstract_1.CsvStringifier)); +exports.ObjectCsvStringifier = ObjectCsvStringifier; +//# sourceMappingURL=object.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/csv-stringifiers/object.js.map b/node_modules/csv-writer/dist/lib/csv-stringifiers/object.js.map new file mode 100644 index 0000000..3eff4c6 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/csv-stringifiers/object.js.map @@ -0,0 +1 @@ +{"version":3,"file":"object.js","sourceRoot":"","sources":["../../../src/lib/csv-stringifiers/object.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,uCAA0C;AAG1C,yCAAmD;AAEnD;IAA0C,wCAAgC;IAEtE,8BAAY,gBAAkC,EACjB,MAA+B,EAChD,eAAwB,EACP,iBAA0B;QAHvD,YAII,kBAAM,gBAAgB,EAAE,eAAe,CAAC,SAC3C;QAJ4B,YAAM,GAAN,MAAM,CAAyB;QAE/B,uBAAiB,GAAjB,iBAAiB,CAAS;;IAEvD,CAAC;IAES,8CAAe,GAAzB;QACI,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE,OAAO,IAAI,CAAC;QACtC,OAAQ,IAAI,CAAC,MAA6B,CAAC,GAAG,CAAC,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,KAAK,EAAX,CAAW,CAAC,CAAC;IACzE,CAAC;IAES,+CAAgB,GAA1B,UAA2B,MAAwB;QAAnD,iBAEC;QADG,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAA,OAAO,IAAI,OAAA,KAAI,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,EAApC,CAAoC,CAAC,CAAC;IAC9E,CAAC;IAEO,6CAAc,GAAtB,UAAuB,GAAqB,EAAE,GAAW;QACrD,IAAI,CAAC,IAAI,CAAC,iBAAiB;YAAE,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7C,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,UAAC,MAAM,EAAE,OAAO,IAAK,OAAA,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,EAAvB,CAAuB,EAAE,GAAG,CAAC,CAAC;IACvG,CAAC;IAED,sBAAY,0CAAQ;aAApB;YACI,OAAO,IAAI,CAAC,cAAc,CAAC,CAAC,CAAE,IAAI,CAAC,MAA6B,CAAC,GAAG,CAAC,UAAA,MAAM,IAAI,OAAA,MAAM,CAAC,EAAE,EAAT,CAAS,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,MAAmB,CAAC;QAC1H,CAAC;;;OAAA;IAED,sBAAY,gDAAc;aAA1B;YACI,OAAO,iBAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACnD,CAAC;;;OAAA;IACL,2BAAC;AAAD,CAAC,AA9BD,CAA0C,yBAAc,GA8BvD;AA9BY,oDAAoB"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/csv-writer-factory.js b/node_modules/csv-writer/dist/lib/csv-writer-factory.js new file mode 100644 index 0000000..6c0a091 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/csv-writer-factory.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var csv_writer_1 = require("./csv-writer"); +var CsvWriterFactory = /** @class */ (function () { + function CsvWriterFactory(csvStringifierFactory) { + this.csvStringifierFactory = csvStringifierFactory; + } + CsvWriterFactory.prototype.createArrayCsvWriter = function (params) { + var csvStringifier = this.csvStringifierFactory.createArrayCsvStringifier({ + header: params.header, + fieldDelimiter: params.fieldDelimiter, + recordDelimiter: params.recordDelimiter, + alwaysQuote: params.alwaysQuote + }); + return new csv_writer_1.CsvWriter(csvStringifier, params.path, params.encoding, params.append); + }; + CsvWriterFactory.prototype.createObjectCsvWriter = function (params) { + var csvStringifier = this.csvStringifierFactory.createObjectCsvStringifier({ + header: params.header, + fieldDelimiter: params.fieldDelimiter, + recordDelimiter: params.recordDelimiter, + headerIdDelimiter: params.headerIdDelimiter, + alwaysQuote: params.alwaysQuote + }); + return new csv_writer_1.CsvWriter(csvStringifier, params.path, params.encoding, params.append); + }; + return CsvWriterFactory; +}()); +exports.CsvWriterFactory = CsvWriterFactory; +//# sourceMappingURL=csv-writer-factory.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/csv-writer-factory.js.map b/node_modules/csv-writer/dist/lib/csv-writer-factory.js.map new file mode 100644 index 0000000..0851e62 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/csv-writer-factory.js.map @@ -0,0 +1 @@ +{"version":3,"file":"csv-writer-factory.js","sourceRoot":"","sources":["../../src/lib/csv-writer-factory.ts"],"names":[],"mappings":";;AAAA,2CAAuC;AAyBvC;IACI,0BAA6B,qBAA4C;QAA5C,0BAAqB,GAArB,qBAAqB,CAAuB;IAAG,CAAC;IAE7E,+CAAoB,GAApB,UAAqB,MAA4B;QAC7C,IAAM,cAAc,GAAG,IAAI,CAAC,qBAAqB,CAAC,yBAAyB,CAAC;YACxE,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,WAAW,EAAE,MAAM,CAAC,WAAW;SAClC,CAAC,CAAC;QACH,OAAO,IAAI,sBAAS,CAAC,cAAc,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACtF,CAAC;IAED,gDAAqB,GAArB,UAAsB,MAA6B;QAC/C,IAAM,cAAc,GAAG,IAAI,CAAC,qBAAqB,CAAC,0BAA0B,CAAC;YACzE,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;YAC3C,WAAW,EAAE,MAAM,CAAC,WAAW;SAClC,CAAC,CAAC;QACH,OAAO,IAAI,sBAAS,CAAC,cAAc,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACtF,CAAC;IACL,uBAAC;AAAD,CAAC,AAvBD,IAuBC;AAvBY,4CAAgB"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/csv-writer.js b/node_modules/csv-writer/dist/lib/csv-writer.js new file mode 100644 index 0000000..51d7425 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/csv-writer.js @@ -0,0 +1,76 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var file_writer_1 = require("./file-writer"); +var DEFAULT_INITIAL_APPEND_FLAG = false; +var CsvWriter = /** @class */ (function () { + function CsvWriter(csvStringifier, path, encoding, append) { + if (append === void 0) { append = DEFAULT_INITIAL_APPEND_FLAG; } + this.csvStringifier = csvStringifier; + this.append = append; + this.fileWriter = new file_writer_1.FileWriter(path, this.append, encoding); + } + CsvWriter.prototype.writeRecords = function (records) { + return __awaiter(this, void 0, void 0, function () { + var recordsString, writeString; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + recordsString = this.csvStringifier.stringifyRecords(records); + writeString = this.headerString + recordsString; + return [4 /*yield*/, this.fileWriter.write(writeString)]; + case 1: + _a.sent(); + this.append = true; + return [2 /*return*/]; + } + }); + }); + }; + Object.defineProperty(CsvWriter.prototype, "headerString", { + get: function () { + var headerString = !this.append && this.csvStringifier.getHeaderString(); + return headerString || ''; + }, + enumerable: true, + configurable: true + }); + return CsvWriter; +}()); +exports.CsvWriter = CsvWriter; +//# sourceMappingURL=csv-writer.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/csv-writer.js.map b/node_modules/csv-writer/dist/lib/csv-writer.js.map new file mode 100644 index 0000000..b134506 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/csv-writer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"csv-writer.js","sourceRoot":"","sources":["../../src/lib/csv-writer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,6CAAyC;AAEzC,IAAM,2BAA2B,GAAG,KAAK,CAAC;AAE1C;IAGI,mBAA6B,cAAiC,EAClD,IAAY,EACZ,QAAiB,EACT,MAAoC;QAApC,uBAAA,EAAA,oCAAoC;QAH3B,mBAAc,GAAd,cAAc,CAAmB;QAG1C,WAAM,GAAN,MAAM,CAA8B;QACpD,IAAI,CAAC,UAAU,GAAG,IAAI,wBAAU,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClE,CAAC;IAEK,gCAAY,GAAlB,UAAmB,OAAY;;;;;;wBACrB,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;wBAC9D,WAAW,GAAG,IAAI,CAAC,YAAY,GAAG,aAAa,CAAC;wBACtD,qBAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,EAAA;;wBAAxC,SAAwC,CAAC;wBACzC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;;;;;KACtB;IAED,sBAAY,mCAAY;aAAxB;YACI,IAAM,YAAY,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC;YAC3E,OAAO,YAAY,IAAI,EAAE,CAAC;QAC9B,CAAC;;;OAAA;IACL,gBAAC;AAAD,CAAC,AArBD,IAqBC;AArBY,8BAAS"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/field-stringifier.js b/node_modules/csv-writer/dist/lib/field-stringifier.js new file mode 100644 index 0000000..3b22942 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/field-stringifier.js @@ -0,0 +1,69 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var DEFAULT_FIELD_DELIMITER = ','; +var VALID_FIELD_DELIMITERS = [DEFAULT_FIELD_DELIMITER, ';']; +var FieldStringifier = /** @class */ (function () { + function FieldStringifier(fieldDelimiter) { + this.fieldDelimiter = fieldDelimiter; + } + FieldStringifier.prototype.isEmpty = function (value) { + return typeof value === 'undefined' || value === null || value === ''; + }; + FieldStringifier.prototype.quoteField = function (field) { + return "\"" + field.replace(/"/g, '""') + "\""; + }; + return FieldStringifier; +}()); +exports.FieldStringifier = FieldStringifier; +var DefaultFieldStringifier = /** @class */ (function (_super) { + __extends(DefaultFieldStringifier, _super); + function DefaultFieldStringifier() { + return _super !== null && _super.apply(this, arguments) || this; + } + DefaultFieldStringifier.prototype.stringify = function (value) { + if (this.isEmpty(value)) + return ''; + var str = String(value); + return this.needsQuote(str) ? this.quoteField(str) : str; + }; + DefaultFieldStringifier.prototype.needsQuote = function (str) { + return str.includes(this.fieldDelimiter) || str.includes('\n') || str.includes('"'); + }; + return DefaultFieldStringifier; +}(FieldStringifier)); +var ForceQuoteFieldStringifier = /** @class */ (function (_super) { + __extends(ForceQuoteFieldStringifier, _super); + function ForceQuoteFieldStringifier() { + return _super !== null && _super.apply(this, arguments) || this; + } + ForceQuoteFieldStringifier.prototype.stringify = function (value) { + return this.isEmpty(value) ? '' : this.quoteField(String(value)); + }; + return ForceQuoteFieldStringifier; +}(FieldStringifier)); +function createFieldStringifier(fieldDelimiter, alwaysQuote) { + if (fieldDelimiter === void 0) { fieldDelimiter = DEFAULT_FIELD_DELIMITER; } + if (alwaysQuote === void 0) { alwaysQuote = false; } + _validateFieldDelimiter(fieldDelimiter); + return alwaysQuote ? new ForceQuoteFieldStringifier(fieldDelimiter) : new DefaultFieldStringifier(fieldDelimiter); +} +exports.createFieldStringifier = createFieldStringifier; +function _validateFieldDelimiter(delimiter) { + if (VALID_FIELD_DELIMITERS.indexOf(delimiter) === -1) { + throw new Error("Invalid field delimiter `" + delimiter + "` is specified"); + } +} +//# sourceMappingURL=field-stringifier.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/field-stringifier.js.map b/node_modules/csv-writer/dist/lib/field-stringifier.js.map new file mode 100644 index 0000000..5a1e391 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/field-stringifier.js.map @@ -0,0 +1 @@ +{"version":3,"file":"field-stringifier.js","sourceRoot":"","sources":["../../src/lib/field-stringifier.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAEA,IAAM,uBAAuB,GAAG,GAAG,CAAC;AACpC,IAAM,sBAAsB,GAAG,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;AAE9D;IACI,0BAA4B,cAAsB;QAAtB,mBAAc,GAAd,cAAc,CAAQ;IAAG,CAAC;IAI5C,kCAAO,GAAjB,UAAkB,KAAa;QAC3B,OAAO,OAAO,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;IAC1E,CAAC;IAES,qCAAU,GAApB,UAAqB,KAAa;QAC9B,OAAO,OAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAG,CAAC;IAC5C,CAAC;IACL,uBAAC;AAAD,CAAC,AAZD,IAYC;AAZqB,4CAAgB;AActC;IAAsC,2CAAgB;IAAtD;;IAUA,CAAC;IATG,2CAAS,GAAT,UAAU,KAAa;QACnB,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACnC,IAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC7D,CAAC;IAEO,4CAAU,GAAlB,UAAmB,GAAW;QAC1B,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACxF,CAAC;IACL,8BAAC;AAAD,CAAC,AAVD,CAAsC,gBAAgB,GAUrD;AAED;IAAyC,8CAAgB;IAAzD;;IAIA,CAAC;IAHG,8CAAS,GAAT,UAAU,KAAa;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACrE,CAAC;IACL,iCAAC;AAAD,CAAC,AAJD,CAAyC,gBAAgB,GAIxD;AAED,SAAgB,sBAAsB,CAAC,cAAgD,EAAE,WAAmB;IAArE,+BAAA,EAAA,wCAAgD;IAAE,4BAAA,EAAA,mBAAmB;IACxG,uBAAuB,CAAC,cAAc,CAAC,CAAC;IACxC,OAAO,WAAW,CAAC,CAAC,CAAC,IAAI,0BAA0B,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,uBAAuB,CAAC,cAAc,CAAC,CAAC;AACtH,CAAC;AAHD,wDAGC;AAED,SAAS,uBAAuB,CAAC,SAAiB;IAC9C,IAAI,sBAAsB,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE;QAClD,MAAM,IAAI,KAAK,CAAC,8BAA6B,SAAS,mBAAiB,CAAC,CAAC;KAC5E;AACL,CAAC"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/file-writer.js b/node_modules/csv-writer/dist/lib/file-writer.js new file mode 100644 index 0000000..855955c --- /dev/null +++ b/node_modules/csv-writer/dist/lib/file-writer.js @@ -0,0 +1,72 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var promise_1 = require("./lang/promise"); +var fs_1 = require("fs"); +var writeFilePromise = promise_1.promisify(fs_1.writeFile); +var DEFAULT_ENCODING = 'utf8'; +var FileWriter = /** @class */ (function () { + function FileWriter(path, append, encoding) { + if (encoding === void 0) { encoding = DEFAULT_ENCODING; } + this.path = path; + this.append = append; + this.encoding = encoding; + } + FileWriter.prototype.write = function (string) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writeFilePromise(this.path, string, this.getWriteOption())]; + case 1: + _a.sent(); + this.append = true; + return [2 /*return*/]; + } + }); + }); + }; + FileWriter.prototype.getWriteOption = function () { + return { + encoding: this.encoding, + flag: this.append ? 'a' : 'w' + }; + }; + return FileWriter; +}()); +exports.FileWriter = FileWriter; +//# sourceMappingURL=file-writer.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/file-writer.js.map b/node_modules/csv-writer/dist/lib/file-writer.js.map new file mode 100644 index 0000000..c0ecbfd --- /dev/null +++ b/node_modules/csv-writer/dist/lib/file-writer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"file-writer.js","sourceRoot":"","sources":["../../src/lib/file-writer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,0CAAyC;AACzC,yBAA6B;AAE7B,IAAM,gBAAgB,GAAG,mBAAS,CAAC,cAAS,CAAC,CAAC;AAE9C,IAAM,gBAAgB,GAAG,MAAM,CAAC;AAEhC;IAEI,oBAA6B,IAAY,EACrB,MAAe,EACN,QAA2B;QAA3B,yBAAA,EAAA,2BAA2B;QAF3B,SAAI,GAAJ,IAAI,CAAQ;QACrB,WAAM,GAAN,MAAM,CAAS;QACN,aAAQ,GAAR,QAAQ,CAAmB;IACxD,CAAC;IAEK,0BAAK,GAAX,UAAY,MAAc;;;;4BACtB,qBAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,EAAA;;wBAAhE,SAAgE,CAAC;wBACjE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;;;;;KACtB;IAEO,mCAAc,GAAtB;QACI,OAAO;YACH,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;SAChC,CAAC;IACN,CAAC;IACL,iBAAC;AAAD,CAAC,AAlBD,IAkBC;AAlBY,gCAAU"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/lang/object.js b/node_modules/csv-writer/dist/lib/lang/object.js new file mode 100644 index 0000000..5d12434 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/lang/object.js @@ -0,0 +1,6 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isObject = function (value) { + return Object.prototype.toString.call(value) === '[object Object]'; +}; +//# sourceMappingURL=object.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/lang/object.js.map b/node_modules/csv-writer/dist/lib/lang/object.js.map new file mode 100644 index 0000000..ac17a38 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/lang/object.js.map @@ -0,0 +1 @@ +{"version":3,"file":"object.js","sourceRoot":"","sources":["../../../src/lib/lang/object.ts"],"names":[],"mappings":";;AAAa,QAAA,QAAQ,GAAG,UAAC,KAAU;IAC/B,OAAA,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,iBAAiB;AAA3D,CAA2D,CAAC"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/lang/promise.js b/node_modules/csv-writer/dist/lib/lang/promise.js new file mode 100644 index 0000000..1ee4696 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/lang/promise.js @@ -0,0 +1,28 @@ +"use strict"; +var __spreadArrays = (this && this.__spreadArrays) || function () { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +function promisify(fn) { + return function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + return new Promise(function (resolve, reject) { + var nodeCallback = function (err, result) { + if (err) + reject(err); + else + resolve(result); + }; + fn.apply(null, __spreadArrays(args, [nodeCallback])); + }); + }; +} +exports.promisify = promisify; +//# sourceMappingURL=promise.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/lang/promise.js.map b/node_modules/csv-writer/dist/lib/lang/promise.js.map new file mode 100644 index 0000000..c8d2da6 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/lang/promise.js.map @@ -0,0 +1 @@ +{"version":3,"file":"promise.js","sourceRoot":"","sources":["../../../src/lib/lang/promise.ts"],"names":[],"mappings":";;;;;;;;;AAGA,SAAgB,SAAS,CAAC,EAA4B;IAClD,OAAO;QAAC,cAAc;aAAd,UAAc,EAAd,qBAAc,EAAd,IAAc;YAAd,yBAAc;;QAClB,OAAO,IAAI,OAAO,CAAC,UAAC,OAAO,EAAE,MAAM;YAC/B,IAAM,YAAY,GAAG,UAAC,GAAkB,EAAE,MAAW;gBACjD,IAAI,GAAG;oBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;;oBAChB,OAAO,CAAC,MAAM,CAAC,CAAC;YACzB,CAAC,CAAC;YACF,EAAE,CAAC,KAAK,CAAC,IAAI,iBAAM,IAAI,GAAE,YAAY,GAAE,CAAC;QAC5C,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;AACN,CAAC;AAVD,8BAUC"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/record.js b/node_modules/csv-writer/dist/lib/record.js new file mode 100644 index 0000000..1f82ca9 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/record.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=record.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/lib/record.js.map b/node_modules/csv-writer/dist/lib/record.js.map new file mode 100644 index 0000000..d9c2928 --- /dev/null +++ b/node_modules/csv-writer/dist/lib/record.js.map @@ -0,0 +1 @@ +{"version":3,"file":"record.js","sourceRoot":"","sources":["../../src/lib/record.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/csv-stringifiers/array.test.js b/node_modules/csv-writer/dist/test/csv-stringifiers/array.test.js new file mode 100644 index 0000000..5fc4090 --- /dev/null +++ b/node_modules/csv-writer/dist/test/csv-stringifiers/array.test.js @@ -0,0 +1,114 @@ +"use strict"; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var delimiter_1 = require("../helper/delimiter"); +var index_1 = require("../../index"); +var assert_1 = require("assert"); +describe('ArrayCsvStringifier', function () { + var records = [ + ['FIELD_A1', 'FIELD_B1'], + ['FIELD_A2', 'FIELD_B2'] + ]; + describe('When field delimiter is comma', generateTestCases()); + describe('When field delimiter is semicolon', generateTestCases(';')); + describe('When field delimiter is neither comma nor semicolon', function () { + it('throws an exception', function () { + assert_1.throws(function () { + index_1.createArrayCsvStringifier({ fieldDelimiter: '/' }); + }); + }); + }); + describe('When record delimiter is neither LF nor CR+LF', function () { + it('throws an exception', function () { + assert_1.throws(function () { + index_1.createArrayCsvStringifier({ recordDelimiter: '\r' }); + }); + }); + }); + describe('When records input is an iterable other than an array', function () { + var stringifier = index_1.createArrayCsvStringifier({ + header: ['TITLE_A', 'TITLE_B'] + }); + function recordGenerator() { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, records[0]]; + case 1: + _a.sent(); + return [4 /*yield*/, records[1]]; + case 2: + _a.sent(); + return [2 /*return*/]; + } + }); + } + it('converts the records into CSV', function () { + assert_1.strictEqual(stringifier.stringifyRecords(recordGenerator()), 'FIELD_A1,FIELD_B1\nFIELD_A2,FIELD_B2\n'); + }); + }); + describe('When `alwaysQuote` flag is set', function () { + var stringifier = index_1.createArrayCsvStringifier({ + header: ['TITLE_A', 'TITLE_B'], + alwaysQuote: true + }); + it('quotes all header fields', function () { + assert_1.strictEqual(stringifier.getHeaderString(), '"TITLE_A","TITLE_B"\n'); + }); + it('quotes all data fields', function () { + assert_1.strictEqual(stringifier.stringifyRecords(records), '"FIELD_A1","FIELD_B1"\n"FIELD_A2","FIELD_B2"\n'); + }); + }); + function generateTestCases(fieldDelimiter) { + var delim = delimiter_1.resolveDelimiterChar(fieldDelimiter); + return function () { + describe('header is specified as a list of column titles', function () { + var stringifier = index_1.createArrayCsvStringifier({ + header: ['TITLE_A', 'TITLE_B'], + fieldDelimiter: fieldDelimiter + }); + it("returns a header line with field separated by \"" + delim + "\"", function () { + assert_1.strictEqual(stringifier.getHeaderString(), "TITLE_A" + delim + "TITLE_B\n"); + }); + it("converts given data records into CSV lines with field separated by \"" + delim + "\"", function () { + assert_1.strictEqual(stringifier.stringifyRecords(records), "FIELD_A1" + delim + "FIELD_B1\nFIELD_A2" + delim + "FIELD_B2\n"); + }); + }); + describe('header is not specified', function () { + var stringifier = index_1.createArrayCsvStringifier({ fieldDelimiter: fieldDelimiter }); + it('returns null for header line', function () { + assert_1.strictEqual(stringifier.getHeaderString(), null); + }); + it("converts given data records into CSV lines with field separated by \"" + delim + "\"", function () { + assert_1.strictEqual(stringifier.stringifyRecords(records), "FIELD_A1" + delim + "FIELD_B1\nFIELD_A2" + delim + "FIELD_B2\n"); + }); + }); + }; + } +}); +//# sourceMappingURL=array.test.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/csv-stringifiers/array.test.js.map b/node_modules/csv-writer/dist/test/csv-stringifiers/array.test.js.map new file mode 100644 index 0000000..888b01c --- /dev/null +++ b/node_modules/csv-writer/dist/test/csv-stringifiers/array.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"array.test.js","sourceRoot":"","sources":["../../../src/test/csv-stringifiers/array.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iDAAyD;AACzD,qCAAsD;AACtD,iCAA2C;AAE3C,QAAQ,CAAC,qBAAqB,EAAE;IAC5B,IAAM,OAAO,GAAG;QACZ,CAAC,UAAU,EAAE,UAAU,CAAC;QACxB,CAAC,UAAU,EAAE,UAAU,CAAC;KAC3B,CAAC;IAEF,QAAQ,CAAC,+BAA+B,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAE/D,QAAQ,CAAC,mCAAmC,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;IAEtE,QAAQ,CAAC,qDAAqD,EAAE;QAC5D,EAAE,CAAC,qBAAqB,EAAE;YACtB,eAAM,CAAC;gBACH,iCAAyB,CAAC,EAAC,cAAc,EAAE,GAAG,EAAC,CAAC,CAAC;YACrD,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,+CAA+C,EAAE;QACtD,EAAE,CAAC,qBAAqB,EAAE;YACtB,eAAM,CAAC;gBACH,iCAAyB,CAAC,EAAC,eAAe,EAAE,IAAI,EAAC,CAAC,CAAC;YACvD,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,uDAAuD,EAAE;QAC9D,IAAM,WAAW,GAAG,iCAAyB,CAAC;YAC1C,MAAM,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;SACjC,CAAC,CAAC;QACH,SAAW,eAAe;;;4BACtB,qBAAM,OAAO,CAAC,CAAC,CAAC,EAAA;;wBAAhB,SAAgB,CAAC;wBACjB,qBAAM,OAAO,CAAC,CAAC,CAAC,EAAA;;wBAAhB,SAAgB,CAAC;;;;SACpB;QAED,EAAE,CAAC,+BAA+B,EAAE;YAChC,oBAAW,CACP,WAAW,CAAC,gBAAgB,CAAC,eAAe,EAAE,CAAC,EAC/C,wCAAwC,CAC3C,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gCAAgC,EAAE;QACvC,IAAM,WAAW,GAAG,iCAAyB,CAAC;YAC1C,MAAM,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;YAC9B,WAAW,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,EAAE,CAAC,0BAA0B,EAAE;YAC3B,oBAAW,CAAC,WAAW,CAAC,eAAe,EAAE,EAAE,uBAAuB,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wBAAwB,EAAE;YACzB,oBAAW,CAAC,WAAW,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,gDAAgD,CAAC,CAAC;QACzG,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,SAAS,iBAAiB,CAAC,cAAuB;QAC9C,IAAM,KAAK,GAAG,gCAAoB,CAAC,cAAc,CAAC,CAAC;QACnD,OAAO;YACH,QAAQ,CAAC,gDAAgD,EAAE;gBACvD,IAAM,WAAW,GAAG,iCAAyB,CAAC;oBAC1C,MAAM,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;oBAC9B,cAAc,gBAAA;iBACjB,CAAC,CAAC;gBAEH,EAAE,CAAC,qDAAkD,KAAK,OAAG,EAAE;oBAC3D,oBAAW,CAAC,WAAW,CAAC,eAAe,EAAE,EAAE,YAAU,KAAK,cAAW,CAAC,CAAC;gBAC3E,CAAC,CAAC,CAAC;gBAEH,EAAE,CAAC,0EAAuE,KAAK,OAAG,EAAE;oBAChF,oBAAW,CACP,WAAW,CAAC,gBAAgB,CAAC,OAAO,CAAC,EACrC,aAAW,KAAK,0BAAqB,KAAK,eAAY,CACzD,CAAC;gBACN,CAAC,CAAC,CAAC;YACP,CAAC,CAAC,CAAC;YAEH,QAAQ,CAAC,yBAAyB,EAAE;gBAChC,IAAM,WAAW,GAAG,iCAAyB,CAAC,EAAC,cAAc,gBAAA,EAAC,CAAC,CAAC;gBAEhE,EAAE,CAAC,8BAA8B,EAAE;oBAC/B,oBAAW,CAAC,WAAW,CAAC,eAAe,EAAE,EAAE,IAAI,CAAC,CAAC;gBACrD,CAAC,CAAC,CAAC;gBAEH,EAAE,CAAC,0EAAuE,KAAK,OAAG,EAAE;oBAChF,oBAAW,CACP,WAAW,CAAC,gBAAgB,CAAC,OAAO,CAAC,EACrC,aAAW,KAAK,0BAAqB,KAAK,eAAY,CACzD,CAAC;gBACN,CAAC,CAAC,CAAC;YACP,CAAC,CAAC,CAAC;QACP,CAAC,CAAC;IACN,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/csv-stringifiers/object.test.js b/node_modules/csv-writer/dist/test/csv-stringifiers/object.test.js new file mode 100644 index 0000000..3b3ace1 --- /dev/null +++ b/node_modules/csv-writer/dist/test/csv-stringifiers/object.test.js @@ -0,0 +1,156 @@ +"use strict"; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var delimiter_1 = require("../helper/delimiter"); +var index_1 = require("../../index"); +var assert_1 = require("assert"); +describe('ObjectCsvStringifier', function () { + var records = [ + { FIELD_A: 'VALUE_A1', FIELD_B: 'VALUE_B1' }, + { FIELD_A: 'VALUE_A2', FIELD_B: 'VALUE_B2', OTHERS: { FIELD_C: 'VALUE_C2' } } + ]; + describe('When field delimiter is comma', generateTestCases()); + describe('When field delimiter is semicolon', generateTestCases(';')); + describe('When field delimiter is neither comma nor semicolon', function () { + it('throws an exception', function () { + assert_1.throws(function () { + index_1.createObjectCsvStringifier({ + header: ['FIELD_A', 'FIELD_B'], + fieldDelimiter: '/' + }); + }); + }); + }); + describe('When record delimiter is neither LF nor CR+LF', function () { + it('throws an exception', function () { + assert_1.throws(function () { + index_1.createObjectCsvStringifier({ + header: ['FIELD_A', 'FIELD_B'], + recordDelimiter: '\r' + }); + }); + }); + }); + describe('When records input is an iterable other than an array', function () { + var stringifier = index_1.createObjectCsvStringifier({ + header: ['FIELD_A', 'FIELD_B'] + }); + function recordGenerator() { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, records[0]]; + case 1: + _a.sent(); + return [4 /*yield*/, records[1]]; + case 2: + _a.sent(); + return [2 /*return*/]; + } + }); + } + it('converts the records into CSV', function () { + assert_1.strictEqual(stringifier.stringifyRecords(recordGenerator()), 'VALUE_A1,VALUE_B1\nVALUE_A2,VALUE_B2\n'); + }); + }); + describe('When `alwaysQuote` flag is set', function () { + var stringifier = index_1.createObjectCsvStringifier({ + header: [ + { id: 'FIELD_A', title: 'TITLE_A' }, + { id: 'FIELD_B', title: 'TITLE_B' } + ], + alwaysQuote: true + }); + it('quotes all header fields', function () { + assert_1.strictEqual(stringifier.getHeaderString(), '"TITLE_A","TITLE_B"\n'); + }); + it('quotes all data fields', function () { + assert_1.strictEqual(stringifier.stringifyRecords(records), '"VALUE_A1","VALUE_B1"\n"VALUE_A2","VALUE_B2"\n'); + }); + }); + describe('When `headerIdDelimiter` is set', function () { + var stringifier = index_1.createObjectCsvStringifier({ + header: [ + { id: 'FIELD_A', title: 'TITLE_A' }, + { id: 'OTHERS/FIELD_C', title: 'TITLE_C' } + ], + headerIdDelimiter: '/' + }); + it('uses the title as is', function () { + assert_1.strictEqual(stringifier.getHeaderString(), 'TITLE_A,TITLE_C\n'); + }); + it('picks up a value in nested objects', function () { + assert_1.strictEqual(stringifier.stringifyRecords(records), 'VALUE_A1,\nVALUE_A2,VALUE_C2\n'); + }); + }); + function generateTestCases(fieldDelimiter) { + var delim = delimiter_1.resolveDelimiterChar(fieldDelimiter); + return function () { + describe('header is specified with title', function () { + var stringifier = index_1.createObjectCsvStringifier({ + header: [ + { id: 'FIELD_A', title: 'TITLE_A' }, + { id: 'FIELD_B', title: 'TITLE_B' } + ], + fieldDelimiter: fieldDelimiter + }); + it("returns a header line with field separated by \"" + delim + "\"", function () { + assert_1.strictEqual(stringifier.getHeaderString(), "TITLE_A" + delim + "TITLE_B\n"); + }); + it("converts given data records into CSV lines with field separated by \"" + delim + "\"", function () { + assert_1.strictEqual(stringifier.stringifyRecords(records), "VALUE_A1" + delim + "VALUE_B1\nVALUE_A2" + delim + "VALUE_B2\n"); + }); + }); + describe('header is specified without title', function () { + var stringifier = index_1.createObjectCsvStringifier({ + header: ['FIELD_A', 'FIELD_B'], + fieldDelimiter: fieldDelimiter + }); + it('returns null for header line', function () { + assert_1.strictEqual(stringifier.getHeaderString(), null); + }); + it("converts given data records into CSV lines with field separated by \"" + delim + "\"", function () { + assert_1.strictEqual(stringifier.stringifyRecords(records), "VALUE_A1" + delim + "VALUE_B1\nVALUE_A2" + delim + "VALUE_B2\n"); + }); + }); + describe('header columns are given with reverse order', function () { + var stringifier = index_1.createObjectCsvStringifier({ + header: [ + { id: 'FIELD_B', title: 'TITLE_B' }, + { id: 'FIELD_A', title: 'TITLE_A' } + ], + fieldDelimiter: fieldDelimiter + }); + it("layouts fields with the order of headers given with field separated by \"" + delim + "\"", function () { + assert_1.strictEqual(stringifier.stringifyRecords(records), "VALUE_B1" + delim + "VALUE_A1\nVALUE_B2" + delim + "VALUE_A2\n"); + }); + }); + }; + } +}); +//# sourceMappingURL=object.test.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/csv-stringifiers/object.test.js.map b/node_modules/csv-writer/dist/test/csv-stringifiers/object.test.js.map new file mode 100644 index 0000000..bdcdd9d --- /dev/null +++ b/node_modules/csv-writer/dist/test/csv-stringifiers/object.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"object.test.js","sourceRoot":"","sources":["../../../src/test/csv-stringifiers/object.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/field-stringifier.test.js b/node_modules/csv-writer/dist/test/field-stringifier.test.js new file mode 100644 index 0000000..72eb70f --- /dev/null +++ b/node_modules/csv-writer/dist/test/field-stringifier.test.js @@ -0,0 +1,79 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var delimiter_1 = require("./helper/delimiter"); +var field_stringifier_1 = require("../lib/field-stringifier"); +var assert_1 = require("assert"); +describe('DefaultFieldStringifier', function () { + describe('When field delimiter is comma', generateTestCases(',')); + describe('When field delimiter is semicolon', generateTestCases(';')); + describe('When all fields needs to be quoted', function () { + var stringifier = field_stringifier_1.createFieldStringifier(',', true); + it('quotes a field', function () { + assert_1.strictEqual(stringifier.stringify('VALUE'), '"VALUE"'); + }); + it('does not quote a field of value undefined', function () { + assert_1.strictEqual(stringifier.stringify(), ''); + }); + it('does not quote a field of value null', function () { + assert_1.strictEqual(stringifier.stringify(null), ''); + }); + it('does not quote a field of value empty string', function () { + assert_1.strictEqual(stringifier.stringify(''), ''); + }); + }); + function generateTestCases(fieldDelimiter) { + var delim = delimiter_1.resolveDelimiterChar(fieldDelimiter); + return function () { + var stringifier = field_stringifier_1.createFieldStringifier(fieldDelimiter); + it('returns the same string', function () { + assert_1.strictEqual(stringifier.stringify('VALUE'), 'VALUE'); + }); + it('preserves the whitespace characters', function () { + assert_1.strictEqual(stringifier.stringify(' VALUE\tA '), ' VALUE\tA '); + }); + it("wraps a field value with double quotes if the field contains \"" + delim + "\"", function () { + assert_1.strictEqual(stringifier.stringify("VALUE" + delim + "A"), "\"VALUE" + delim + "A\""); + }); + it('wraps a field value with double quotes if the field contains newline', function () { + assert_1.strictEqual(stringifier.stringify('VALUE\nA'), '"VALUE\nA"'); + }); + it('wraps a field value with double quotes and escape the double quotes if they are used in the field', function () { + assert_1.strictEqual(stringifier.stringify('VALUE"A'), '"VALUE""A"'); + }); + it('escapes double quotes even if double quotes are only on the both edges of the field', function () { + assert_1.strictEqual(stringifier.stringify('"VALUE"'), '"""VALUE"""'); + }); + it('converts a number into a string', function () { + assert_1.strictEqual(stringifier.stringify(1), '1'); + }); + it('converts undefined into an empty string', function () { + assert_1.strictEqual(stringifier.stringify(), ''); + }); + it('converts null into an empty string', function () { + assert_1.strictEqual(stringifier.stringify(null), ''); + }); + it('converts an object into toString-ed value', function () { + var obj = { + name: 'OBJECT_NAME', + toString: function () { return "Name: " + this.name; } + }; + assert_1.strictEqual(stringifier.stringify(obj), 'Name: OBJECT_NAME'); + }); + it("wraps a toString-ed field value with double quote if the value contains \"" + delim + "\"", function () { + var obj = { + name: "OBJECT" + delim + "NAME", + toString: function () { return "Name: " + this.name; } + }; + assert_1.strictEqual(stringifier.stringify(obj), "\"Name: OBJECT" + delim + "NAME\""); + }); + it('escapes double quotes in a toString-ed field value if the value has double quotes', function () { + var obj = { + name: 'OBJECT_NAME"', + toString: function () { return "Name: " + this.name; } + }; + assert_1.strictEqual(stringifier.stringify(obj), '"Name: OBJECT_NAME"""'); + }); + }; + } +}); +//# sourceMappingURL=field-stringifier.test.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/field-stringifier.test.js.map b/node_modules/csv-writer/dist/test/field-stringifier.test.js.map new file mode 100644 index 0000000..9a606db --- /dev/null +++ b/node_modules/csv-writer/dist/test/field-stringifier.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"field-stringifier.test.js","sourceRoot":"","sources":["../../src/test/field-stringifier.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/helper.js b/node_modules/csv-writer/dist/test/helper.js new file mode 100644 index 0000000..bdc23bb --- /dev/null +++ b/node_modules/csv-writer/dist/test/helper.js @@ -0,0 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var assert_1 = require("assert"); +var fs_1 = require("fs"); +exports.testFilePath = function (id) { return "./test-tmp/" + id + ".csv"; }; +exports.assertFile = function (path, expectedContents, encoding) { + var actualContents = fs_1.readFileSync(path, encoding || 'utf8'); + assert_1.strictEqual(actualContents, expectedContents); +}; +exports.assertRejected = function (p, message) { + return p.then(function () { return new Error('Should not have been called'); }, function (e) { assert_1.strictEqual(e.message, message); }); +}; +//# sourceMappingURL=helper.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/helper.js.map b/node_modules/csv-writer/dist/test/helper.js.map new file mode 100644 index 0000000..a30ab8b --- /dev/null +++ b/node_modules/csv-writer/dist/test/helper.js.map @@ -0,0 +1 @@ +{"version":3,"file":"helper.js","sourceRoot":"","sources":["../../src/test/helper.ts"],"names":[],"mappings":";;AAAA,iCAAmC;AACnC,yBAAgC;AAEnB,QAAA,YAAY,GAAG,UAAC,EAAU,IAAK,OAAA,gBAAc,EAAE,SAAM,EAAtB,CAAsB,CAAC;AAEtD,QAAA,UAAU,GAAG,UAAC,IAAY,EAAE,gBAAwB,EAAE,QAAiB;IAChF,IAAM,cAAc,GAAG,iBAAY,CAAC,IAAI,EAAE,QAAQ,IAAI,MAAM,CAAC,CAAC;IAC9D,oBAAW,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;AAClD,CAAC,CAAC;AAEW,QAAA,cAAc,GAAG,UAAC,CAAe,EAAE,OAAe;IAC3D,OAAO,CAAC,CAAC,IAAI,CACT,cAAM,OAAA,IAAI,KAAK,CAAC,6BAA6B,CAAC,EAAxC,CAAwC,EAC9C,UAAC,CAAQ,IAAO,oBAAW,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CACrD,CAAC;AACN,CAAC,CAAC"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/helper/delimiter.js b/node_modules/csv-writer/dist/test/helper/delimiter.js new file mode 100644 index 0000000..6b17c8b --- /dev/null +++ b/node_modules/csv-writer/dist/test/helper/delimiter.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.resolveDelimiterChar = function (char) { + if (char === ',' || char === ';') + return char; + if (typeof char === 'undefined') + return ','; + throw new Error('Invalid field delimiter'); +}; +//# sourceMappingURL=delimiter.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/helper/delimiter.js.map b/node_modules/csv-writer/dist/test/helper/delimiter.js.map new file mode 100644 index 0000000..a0c18d9 --- /dev/null +++ b/node_modules/csv-writer/dist/test/helper/delimiter.js.map @@ -0,0 +1 @@ +{"version":3,"file":"delimiter.js","sourceRoot":"","sources":["../../../src/test/helper/delimiter.ts"],"names":[],"mappings":";;AACa,QAAA,oBAAoB,GAAG,UAAC,IAAa;IAC9C,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,OAAO,IAAI,KAAK,WAAW;QAAE,OAAO,GAAG,CAAC;IAC5C,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;AAC/C,CAAC,CAAC"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/lang/promise.test.js b/node_modules/csv-writer/dist/test/lang/promise.test.js new file mode 100644 index 0000000..046541d --- /dev/null +++ b/node_modules/csv-writer/dist/test/lang/promise.test.js @@ -0,0 +1,76 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var promise_1 = require("../../lib/lang/promise"); +var assert_1 = require("assert"); +var helper_1 = require("../helper"); +describe('Promise', function () { + var greetAsync = function (name, callback) { + setTimeout(function () { + if (name === 'foo') + callback(null, "Hello, " + name + "!"); + else + callback(new Error("We don't know " + name)); + }, 0); + }; + var promisifiedFn = promise_1.promisify(greetAsync); + it('promisify node style callback', function () { return __awaiter(void 0, void 0, void 0, function () { + var _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _a = assert_1.strictEqual; + return [4 /*yield*/, promisifiedFn('foo')]; + case 1: + _a.apply(void 0, [_b.sent(), 'Hello, foo!']); + return [2 /*return*/]; + } + }); + }); }); + it('raise an error for error', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, helper_1.assertRejected(promisifiedFn('bar'), "We don't know bar")]; + case 1: + _a.sent(); + return [2 /*return*/]; + } + }); + }); }); +}); +//# sourceMappingURL=promise.test.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/lang/promise.test.js.map b/node_modules/csv-writer/dist/test/lang/promise.test.js.map new file mode 100644 index 0000000..820bb3c --- /dev/null +++ b/node_modules/csv-writer/dist/test/lang/promise.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"promise.test.js","sourceRoot":"","sources":["../../../src/test/lang/promise.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kDAAiD;AACjD,iCAAmC;AACnC,oCAAyC;AAEzC,QAAQ,CAAC,SAAS,EAAE;IAChB,IAAM,UAAU,GAAG,UAAC,IAAY,EAAE,QAAsD;QACpF,UAAU,CAAC;YACP,IAAI,IAAI,KAAK,KAAK;gBAAE,QAAQ,CAAC,IAAI,EAAE,YAAU,IAAI,MAAG,CAAC,CAAC;;gBACjD,QAAQ,CAAC,IAAI,KAAK,CAAC,mBAAiB,IAAM,CAAC,CAAC,CAAC;QACtD,CAAC,EAAE,CAAC,CAAC,CAAC;IACV,CAAC,CAAC;IACF,IAAM,aAAa,GAAG,mBAAS,CAAC,UAAU,CAAC,CAAC;IAE5C,EAAE,CAAC,+BAA+B,EAAE;;;;;oBAChC,KAAA,oBAAW,CAAA;oBAAC,qBAAM,aAAa,CAAC,KAAK,CAAC,EAAA;;oBAAtC,kBAAY,SAA0B,EAAE,aAAa,EAAC,CAAC;;;;SAC1D,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE;;;wBAC3B,qBAAM,uBAAc,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,mBAAmB,CAAC,EAAA;;oBAA/D,SAA+D,CAAC;;;;SACnE,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/write-array-records.test.js b/node_modules/csv-writer/dist/test/write-array-records.test.js new file mode 100644 index 0000000..6b9d88f --- /dev/null +++ b/node_modules/csv-writer/dist/test/write-array-records.test.js @@ -0,0 +1,209 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var helper_1 = require("./helper"); +var fs_1 = require("fs"); +var index_1 = require("../index"); +describe('Write array records into CSV', function () { + var makeFilePath = function (id) { return helper_1.testFilePath("array-" + id); }; + var records = [ + ['Bob', 'French'], + ['Mary', 'English'] + ]; + describe('When only path is specified', function () { + var filePath = makeFilePath('minimum'); + var writer; + beforeEach(function () { + writer = index_1.createArrayCsvWriter({ path: filePath }); + }); + it('writes records to a new file', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords(records)]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, 'Bob,French\nMary,English\n'); + return [2 /*return*/]; + } + }); + }); }); + it('appends records when requested to write to the same file', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords([records[0]])]; + case 1: + _a.sent(); + return [4 /*yield*/, writer.writeRecords([records[1]])]; + case 2: + _a.sent(); + helper_1.assertFile(filePath, 'Bob,French\nMary,English\n'); + return [2 /*return*/]; + } + }); + }); }); + }); + describe('When field header is given', function () { + var filePath = makeFilePath('header'); + var writer; + beforeEach(function () { + writer = index_1.createArrayCsvWriter({ + path: filePath, + header: ['NAME', 'LANGUAGE'] + }); + }); + it('writes a header', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords(records)]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, 'NAME,LANGUAGE\nBob,French\nMary,English\n'); + return [2 /*return*/]; + } + }); + }); }); + it('appends records without headers', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords([records[0]])]; + case 1: + _a.sent(); + return [4 /*yield*/, writer.writeRecords([records[1]])]; + case 2: + _a.sent(); + helper_1.assertFile(filePath, 'NAME,LANGUAGE\nBob,French\nMary,English\n'); + return [2 /*return*/]; + } + }); + }); }); + }); + describe('When `append` flag is specified', function () { + var filePath = makeFilePath('append'); + fs_1.writeFileSync(filePath, 'Mike,German\n', 'utf8'); + var writer = index_1.createArrayCsvWriter({ + path: filePath, + append: true + }); + it('do not overwrite the existing contents and appends records to them', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords([records[1]])]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, 'Mike,German\nMary,English\n'); + return [2 /*return*/]; + } + }); + }); }); + }); + describe('When encoding is specified', function () { + var filePath = makeFilePath('encoding'); + var writer = index_1.createArrayCsvWriter({ + path: filePath, + encoding: 'utf16le' + }); + it('writes to a file with the specified encoding', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords(records)]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, 'Bob,French\nMary,English\n', 'utf16le'); + return [2 /*return*/]; + } + }); + }); }); + }); + describe('When semicolon is specified as a field delimiter', function () { + var filePath = makeFilePath('field-delimiter'); + var writer = index_1.createArrayCsvWriter({ + path: filePath, + header: ['NAME', 'LANGUAGE'], + fieldDelimiter: ';' + }); + it('uses semicolon instead of comma to separate fields', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords(records)]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, 'NAME;LANGUAGE\nBob;French\nMary;English\n'); + return [2 /*return*/]; + } + }); + }); }); + }); + describe('When newline is specified', function () { + var filePath = makeFilePath('newline'); + var writer = index_1.createArrayCsvWriter({ + path: filePath, + recordDelimiter: '\r\n' + }); + it('writes to a file with the specified newline character', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords(records)]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, 'Bob,French\r\nMary,English\r\n'); + return [2 /*return*/]; + } + }); + }); }); + }); + describe('When `alwaysQuote` flag is set', function () { + var filePath = makeFilePath('always-quote'); + var writer = index_1.createArrayCsvWriter({ + path: filePath, + header: ['NAME', 'LANGUAGE'], + alwaysQuote: true + }); + it('quotes all fields', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords(records)]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, '"NAME","LANGUAGE"\n"Bob","French"\n"Mary","English"\n'); + return [2 /*return*/]; + } + }); + }); }); + }); +}); +//# sourceMappingURL=write-array-records.test.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/write-array-records.test.js.map b/node_modules/csv-writer/dist/test/write-array-records.test.js.map new file mode 100644 index 0000000..566e090 --- /dev/null +++ b/node_modules/csv-writer/dist/test/write-array-records.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"write-array-records.test.js","sourceRoot":"","sources":["../../src/test/write-array-records.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/write-object-records.test.js b/node_modules/csv-writer/dist/test/write-object-records.test.js new file mode 100644 index 0000000..459eeb5 --- /dev/null +++ b/node_modules/csv-writer/dist/test/write-object-records.test.js @@ -0,0 +1,252 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var helper_1 = require("./helper"); +var fs_1 = require("fs"); +var index_1 = require("../index"); +describe('Write object records into CSV', function () { + var makeFilePath = function (id) { return helper_1.testFilePath("object-" + id); }; + var records = [ + { name: 'Bob', lang: 'French', address: { country: 'France' } }, + { name: 'Mary', lang: 'English' } + ]; + describe('When only path and header ids are given', function () { + var filePath = makeFilePath('minimum'); + var writer; + beforeEach(function () { + writer = index_1.createObjectCsvWriter({ + path: filePath, + header: ['name', 'lang'] + }); + }); + it('writes records to a new file', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords(records)]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, 'Bob,French\nMary,English\n'); + return [2 /*return*/]; + } + }); + }); }); + it('appends records when requested to write to the same file', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords([records[0]])]; + case 1: + _a.sent(); + return [4 /*yield*/, writer.writeRecords([records[1]])]; + case 2: + _a.sent(); + helper_1.assertFile(filePath, 'Bob,French\nMary,English\n'); + return [2 /*return*/]; + } + }); + }); }); + }); + describe('When header ids are given with reverse order', function () { + var filePath = makeFilePath('column-order'); + var writer = index_1.createObjectCsvWriter({ + path: filePath, + header: ['lang', 'name'] + }); + it('also writes columns with reverse order', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords(records)]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, 'French,Bob\nEnglish,Mary\n'); + return [2 /*return*/]; + } + }); + }); }); + }); + describe('When field header is given with titles', function () { + var filePath = makeFilePath('header'); + var writer; + beforeEach(function () { + writer = index_1.createObjectCsvWriter({ + path: filePath, + header: [{ id: 'name', title: 'NAME' }, { id: 'lang', title: 'LANGUAGE' }] + }); + }); + it('writes a header', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords(records)]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, 'NAME,LANGUAGE\nBob,French\nMary,English\n'); + return [2 /*return*/]; + } + }); + }); }); + it('appends records without headers', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords([records[0]])]; + case 1: + _a.sent(); + return [4 /*yield*/, writer.writeRecords([records[1]])]; + case 2: + _a.sent(); + helper_1.assertFile(filePath, 'NAME,LANGUAGE\nBob,French\nMary,English\n'); + return [2 /*return*/]; + } + }); + }); }); + }); + describe('When `append` flag is specified', function () { + var filePath = makeFilePath('append'); + fs_1.writeFileSync(filePath, 'Mike,German\n', 'utf8'); + var writer = index_1.createObjectCsvWriter({ + path: filePath, + header: ['name', 'lang'], + append: true + }); + it('do not overwrite the existing contents and appends records to them', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords([records[1]])]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, 'Mike,German\nMary,English\n'); + return [2 /*return*/]; + } + }); + }); }); + }); + describe('When encoding is specified', function () { + var filePath = makeFilePath('encoding'); + var writer = index_1.createObjectCsvWriter({ + path: filePath, + header: ['name', 'lang'], + encoding: 'utf16le' + }); + it('writes to a file with the specified encoding', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords(records)]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, 'Bob,French\nMary,English\n', 'utf16le'); + return [2 /*return*/]; + } + }); + }); }); + }); + describe('When semicolon is specified as a field delimiter', function () { + var filePath = makeFilePath('field-delimiter'); + var writer = index_1.createObjectCsvWriter({ + path: filePath, + header: [{ id: 'name', title: 'NAME' }, { id: 'lang', title: 'LANGUAGE' }], + fieldDelimiter: ';' + }); + it('uses semicolon instead of comma to separate fields', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords(records)]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, 'NAME;LANGUAGE\nBob;French\nMary;English\n'); + return [2 /*return*/]; + } + }); + }); }); + }); + describe('When newline is specified', function () { + var filePath = makeFilePath('newline'); + var writer = index_1.createObjectCsvWriter({ + path: filePath, + header: ['name', 'lang'], + recordDelimiter: '\r\n' + }); + it('writes to a file with the specified newline character', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords(records)]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, 'Bob,French\r\nMary,English\r\n'); + return [2 /*return*/]; + } + }); + }); }); + }); + describe('When `alwaysQuote` flag is set', function () { + var filePath = makeFilePath('always-quote'); + var writer = index_1.createObjectCsvWriter({ + path: filePath, + header: [{ id: 'name', title: 'NAME' }, { id: 'lang', title: 'LANGUAGE' }], + alwaysQuote: true + }); + it('quotes all fields', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords(records)]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, '"NAME","LANGUAGE"\n"Bob","French"\n"Mary","English"\n'); + return [2 /*return*/]; + } + }); + }); }); + }); + describe('When `headerIdDelimiter` flag is set', function () { + var filePath = makeFilePath('nested'); + var writer = index_1.createObjectCsvWriter({ + path: filePath, + header: [{ id: 'name', title: 'NAME' }, { id: 'address.country', title: 'COUNTRY' }], + headerIdDelimiter: '.' + }); + it('breaks keys into key paths', function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, writer.writeRecords(records)]; + case 1: + _a.sent(); + helper_1.assertFile(filePath, 'NAME,COUNTRY\nBob,France\nMary,\n'); + return [2 /*return*/]; + } + }); + }); }); + }); +}); +//# sourceMappingURL=write-object-records.test.js.map \ No newline at end of file diff --git a/node_modules/csv-writer/dist/test/write-object-records.test.js.map b/node_modules/csv-writer/dist/test/write-object-records.test.js.map new file mode 100644 index 0000000..aed39fc --- /dev/null +++ b/node_modules/csv-writer/dist/test/write-object-records.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"write-object-records.test.js","sourceRoot":"","sources":["../../src/test/write-object-records.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/csv-writer/package.json b/node_modules/csv-writer/package.json new file mode 100644 index 0000000..28b2f5b --- /dev/null +++ b/node_modules/csv-writer/package.json @@ -0,0 +1,43 @@ +{ + "name": "csv-writer", + "version": "1.6.0", + "description": "Convert objects/arrays into a CSV string or write them into a CSV file", + "main": "dist/index.js", + "types": "src/index.ts", + "scripts": { + "compile": "tsc -p ./", + "test": "npm run test:unit && npm run test:it", + "pretest:unit": "rm -rf test-tmp && mkdir test-tmp", + "test:unit": "mocha --require ts-node/register --recursive 'src/test/**/*.ts'", + "test:it": "test-integration/test.sh", + "coverage": "nyc npm run test:unit", + "lint": "tslint -p .", + "prepare": "npm run compile" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ryu1kn/csv-writer.git" + }, + "keywords": [ + "csv", + "writer", + "stringify" + ], + "author": "Ryuichi Inagaki", + "license": "MIT", + "bugs": { + "url": "https://github.com/ryu1kn/csv-writer/issues" + }, + "homepage": "https://github.com/ryu1kn/csv-writer#readme", + "devDependencies": { + "@types/mocha": "^5.2.7", + "@types/node": "^12.12.25", + "codeclimate-test-reporter": "^0.5.1", + "coveralls": "^3.0.9", + "mocha": "^7.0.0", + "nyc": "^15.0.0", + "ts-node": "^8.6.2", + "tslint": "^5.20.1", + "typescript": "^3.7.5" + } +} diff --git a/node_modules/csv-writer/src/index.ts b/node_modules/csv-writer/src/index.ts new file mode 100644 index 0000000..17d713f --- /dev/null +++ b/node_modules/csv-writer/src/index.ts @@ -0,0 +1,21 @@ +import { + ArrayCsvStringifierParams, + CsvStringifierFactory, + ObjectCsvStringifierParams +} from './lib/csv-stringifier-factory'; +import {ArrayCsvWriterParams, CsvWriterFactory, ObjectCsvWriterParams} from './lib/csv-writer-factory'; + +const csvStringifierFactory = new CsvStringifierFactory(); +const csvWriterFactory = new CsvWriterFactory(csvStringifierFactory); + +export const createArrayCsvStringifier = (params: ArrayCsvStringifierParams) => + csvStringifierFactory.createArrayCsvStringifier(params); + +export const createObjectCsvStringifier = (params: ObjectCsvStringifierParams) => + csvStringifierFactory.createObjectCsvStringifier(params); + +export const createArrayCsvWriter = (params: ArrayCsvWriterParams) => + csvWriterFactory.createArrayCsvWriter(params); + +export const createObjectCsvWriter = (params: ObjectCsvWriterParams) => + csvWriterFactory.createObjectCsvWriter(params); diff --git a/node_modules/csv-writer/src/lib/csv-stringifier-factory.ts b/node_modules/csv-writer/src/lib/csv-stringifier-factory.ts new file mode 100644 index 0000000..698e92f --- /dev/null +++ b/node_modules/csv-writer/src/lib/csv-stringifier-factory.ts @@ -0,0 +1,33 @@ +import {ArrayCsvStringifier} from './csv-stringifiers/array'; +import {createFieldStringifier} from './field-stringifier'; +import {ObjectCsvStringifier} from './csv-stringifiers/object'; +import {ObjectStringifierHeader} from './record'; + +export interface ArrayCsvStringifierParams { + header?: string[]; + fieldDelimiter?: string; + recordDelimiter?: string; + alwaysQuote?: boolean; +} + +export interface ObjectCsvStringifierParams { + header: ObjectStringifierHeader; + fieldDelimiter?: string; + recordDelimiter?: string; + headerIdDelimiter?: string; + alwaysQuote?: boolean; +} + +export class CsvStringifierFactory { + + createArrayCsvStringifier(params: ArrayCsvStringifierParams) { + const fieldStringifier = createFieldStringifier(params.fieldDelimiter, params.alwaysQuote); + return new ArrayCsvStringifier(fieldStringifier, params.recordDelimiter, params.header); + } + + createObjectCsvStringifier(params: ObjectCsvStringifierParams) { + const fieldStringifier = createFieldStringifier(params.fieldDelimiter, params.alwaysQuote); + return new ObjectCsvStringifier(fieldStringifier, params.header, params.recordDelimiter, params.headerIdDelimiter); + } + +} diff --git a/node_modules/csv-writer/src/lib/csv-stringifiers/abstract.ts b/node_modules/csv-writer/src/lib/csv-stringifiers/abstract.ts new file mode 100644 index 0000000..5fa27ca --- /dev/null +++ b/node_modules/csv-writer/src/lib/csv-stringifiers/abstract.ts @@ -0,0 +1,43 @@ +import {FieldStringifier} from '../field-stringifier'; +import {Field} from '../record'; + +const DEFAULT_RECORD_DELIMITER = '\n'; +const VALID_RECORD_DELIMITERS = [DEFAULT_RECORD_DELIMITER, '\r\n']; + +export abstract class CsvStringifier { + + constructor(private readonly fieldStringifier: FieldStringifier, + private readonly recordDelimiter = DEFAULT_RECORD_DELIMITER) { + _validateRecordDelimiter(recordDelimiter); + } + + getHeaderString(): string | null { + const headerRecord = this.getHeaderRecord(); + return headerRecord ? this.joinRecords([this.getCsvLine(headerRecord)]) : null; + } + + stringifyRecords(records: IterableIterator | T[]): string { + const csvLines = Array.from(records, record => this.getCsvLine(this.getRecordAsArray(record))); + return this.joinRecords(csvLines); + } + + protected abstract getRecordAsArray(_record: T): Field[]; + + protected abstract getHeaderRecord(): string[] | null | undefined; + + private getCsvLine(record: Field[]): string { + return record + .map(fieldValue => this.fieldStringifier.stringify(fieldValue)) + .join(this.fieldStringifier.fieldDelimiter); + } + + private joinRecords(records: string[]) { + return records.join(this.recordDelimiter) + this.recordDelimiter; + } +} + +function _validateRecordDelimiter(delimiter: string): void { + if (VALID_RECORD_DELIMITERS.indexOf(delimiter) === -1) { + throw new Error(`Invalid record delimiter \`${delimiter}\` is specified`); + } +} diff --git a/node_modules/csv-writer/src/lib/csv-stringifiers/array.ts b/node_modules/csv-writer/src/lib/csv-stringifiers/array.ts new file mode 100644 index 0000000..6ba0f16 --- /dev/null +++ b/node_modules/csv-writer/src/lib/csv-stringifiers/array.ts @@ -0,0 +1,20 @@ +import {CsvStringifier} from './abstract'; +import {FieldStringifier} from '../field-stringifier'; +import {Field} from '../record'; + +export class ArrayCsvStringifier extends CsvStringifier { + + constructor(fieldStringifier: FieldStringifier, + recordDelimiter?: string, + private readonly header?: string[]) { + super(fieldStringifier, recordDelimiter); + } + + protected getHeaderRecord() { + return this.header; + } + + protected getRecordAsArray(record: Field[]): Field[] { + return record; + } +} diff --git a/node_modules/csv-writer/src/lib/csv-stringifiers/object.ts b/node_modules/csv-writer/src/lib/csv-stringifiers/object.ts new file mode 100644 index 0000000..45b54b7 --- /dev/null +++ b/node_modules/csv-writer/src/lib/csv-stringifiers/object.ts @@ -0,0 +1,36 @@ +import {CsvStringifier} from './abstract'; +import {FieldStringifier} from '../field-stringifier'; +import {Field, ObjectHeaderItem, ObjectStringifierHeader} from '../record'; +import {isObject, ObjectMap} from '../lang/object'; + +export class ObjectCsvStringifier extends CsvStringifier> { + + constructor(fieldStringifier: FieldStringifier, + private readonly header: ObjectStringifierHeader, + recordDelimiter?: string, + private readonly headerIdDelimiter?: string) { + super(fieldStringifier, recordDelimiter); + } + + protected getHeaderRecord(): string[] | null { + if (!this.isObjectHeader) return null; + return (this.header as ObjectHeaderItem[]).map(field => field.title); + } + + protected getRecordAsArray(record: ObjectMap): Field[] { + return this.fieldIds.map(fieldId => this.getNestedValue(record, fieldId)); + } + + private getNestedValue(obj: ObjectMap, key: string) { + if (!this.headerIdDelimiter) return obj[key]; + return key.split(this.headerIdDelimiter).reduce((subObj, keyPart) => (subObj || {})[keyPart], obj); + } + + private get fieldIds(): string[] { + return this.isObjectHeader ? (this.header as ObjectHeaderItem[]).map(column => column.id) : (this.header as string[]); + } + + private get isObjectHeader(): boolean { + return isObject(this.header && this.header[0]); + } +} diff --git a/node_modules/csv-writer/src/lib/csv-writer-factory.ts b/node_modules/csv-writer/src/lib/csv-writer-factory.ts new file mode 100644 index 0000000..070dd0b --- /dev/null +++ b/node_modules/csv-writer/src/lib/csv-writer-factory.ts @@ -0,0 +1,49 @@ +import {CsvWriter} from './csv-writer'; +import {CsvStringifierFactory} from './csv-stringifier-factory'; +import {ObjectStringifierHeader} from './record'; + +export interface ArrayCsvWriterParams { + path: string; + header?: string[]; + fieldDelimiter?: string; + recordDelimiter?: string; + alwaysQuote?: boolean; + encoding?: string; + append?: boolean; +} + +export interface ObjectCsvWriterParams { + path: string; + header: ObjectStringifierHeader; + fieldDelimiter?: string; + recordDelimiter?: string; + headerIdDelimiter?: string; + alwaysQuote?: boolean; + encoding?: string; + append?: boolean; +} + +export class CsvWriterFactory { + constructor(private readonly csvStringifierFactory: CsvStringifierFactory) {} + + createArrayCsvWriter(params: ArrayCsvWriterParams) { + const csvStringifier = this.csvStringifierFactory.createArrayCsvStringifier({ + header: params.header, + fieldDelimiter: params.fieldDelimiter, + recordDelimiter: params.recordDelimiter, + alwaysQuote: params.alwaysQuote + }); + return new CsvWriter(csvStringifier, params.path, params.encoding, params.append); + } + + createObjectCsvWriter(params: ObjectCsvWriterParams) { + const csvStringifier = this.csvStringifierFactory.createObjectCsvStringifier({ + header: params.header, + fieldDelimiter: params.fieldDelimiter, + recordDelimiter: params.recordDelimiter, + headerIdDelimiter: params.headerIdDelimiter, + alwaysQuote: params.alwaysQuote + }); + return new CsvWriter(csvStringifier, params.path, params.encoding, params.append); + } +} diff --git a/node_modules/csv-writer/src/lib/csv-writer.ts b/node_modules/csv-writer/src/lib/csv-writer.ts new file mode 100644 index 0000000..6fc2047 --- /dev/null +++ b/node_modules/csv-writer/src/lib/csv-writer.ts @@ -0,0 +1,27 @@ +import {CsvStringifier} from './csv-stringifiers/abstract'; +import {FileWriter} from './file-writer'; + +const DEFAULT_INITIAL_APPEND_FLAG = false; + +export class CsvWriter { + private readonly fileWriter: FileWriter; + + constructor(private readonly csvStringifier: CsvStringifier, + path: string, + encoding?: string, + private append = DEFAULT_INITIAL_APPEND_FLAG) { + this.fileWriter = new FileWriter(path, this.append, encoding); + } + + async writeRecords(records: T[]): Promise { + const recordsString = this.csvStringifier.stringifyRecords(records); + const writeString = this.headerString + recordsString; + await this.fileWriter.write(writeString); + this.append = true; + } + + private get headerString(): string { + const headerString = !this.append && this.csvStringifier.getHeaderString(); + return headerString || ''; + } +} diff --git a/node_modules/csv-writer/src/lib/field-stringifier.ts b/node_modules/csv-writer/src/lib/field-stringifier.ts new file mode 100644 index 0000000..019057a --- /dev/null +++ b/node_modules/csv-writer/src/lib/field-stringifier.ts @@ -0,0 +1,47 @@ +import {Field} from './record'; + +const DEFAULT_FIELD_DELIMITER = ','; +const VALID_FIELD_DELIMITERS = [DEFAULT_FIELD_DELIMITER, ';']; + +export abstract class FieldStringifier { + constructor(public readonly fieldDelimiter: string) {} + + abstract stringify(value?: Field): string; + + protected isEmpty(value?: Field): boolean { + return typeof value === 'undefined' || value === null || value === ''; + } + + protected quoteField(field: string): string { + return `"${field.replace(/"/g, '""')}"`; + } +} + +class DefaultFieldStringifier extends FieldStringifier { + stringify(value?: Field): string { + if (this.isEmpty(value)) return ''; + const str = String(value); + return this.needsQuote(str) ? this.quoteField(str) : str; + } + + private needsQuote(str: string): boolean { + return str.includes(this.fieldDelimiter) || str.includes('\n') || str.includes('"'); + } +} + +class ForceQuoteFieldStringifier extends FieldStringifier { + stringify(value?: Field): string { + return this.isEmpty(value) ? '' : this.quoteField(String(value)); + } +} + +export function createFieldStringifier(fieldDelimiter: string = DEFAULT_FIELD_DELIMITER, alwaysQuote = false) { + _validateFieldDelimiter(fieldDelimiter); + return alwaysQuote ? new ForceQuoteFieldStringifier(fieldDelimiter) : new DefaultFieldStringifier(fieldDelimiter); +} + +function _validateFieldDelimiter(delimiter: string): void { + if (VALID_FIELD_DELIMITERS.indexOf(delimiter) === -1) { + throw new Error(`Invalid field delimiter \`${delimiter}\` is specified`); + } +} diff --git a/node_modules/csv-writer/src/lib/file-writer.ts b/node_modules/csv-writer/src/lib/file-writer.ts new file mode 100644 index 0000000..30ce9dd --- /dev/null +++ b/node_modules/csv-writer/src/lib/file-writer.ts @@ -0,0 +1,26 @@ +import {promisify} from './lang/promise'; +import {writeFile} from 'fs'; + +const writeFilePromise = promisify(writeFile); + +const DEFAULT_ENCODING = 'utf8'; + +export class FileWriter { + + constructor(private readonly path: string, + private append: boolean, + private readonly encoding = DEFAULT_ENCODING) { + } + + async write(string: string): Promise { + await writeFilePromise(this.path, string, this.getWriteOption()); + this.append = true; + } + + private getWriteOption() { + return { + encoding: this.encoding, + flag: this.append ? 'a' : 'w' + }; + } +} diff --git a/node_modules/csv-writer/src/lib/lang/object.ts b/node_modules/csv-writer/src/lib/lang/object.ts new file mode 100644 index 0000000..0f0f76f --- /dev/null +++ b/node_modules/csv-writer/src/lib/lang/object.ts @@ -0,0 +1,6 @@ +export const isObject = (value: any) => + Object.prototype.toString.call(value) === '[object Object]'; + +export interface ObjectMap { + [k: string]: T; +} diff --git a/node_modules/csv-writer/src/lib/lang/promise.ts b/node_modules/csv-writer/src/lib/lang/promise.ts new file mode 100644 index 0000000..6b53b15 --- /dev/null +++ b/node_modules/csv-writer/src/lib/lang/promise.ts @@ -0,0 +1,14 @@ + +type NullableError = Error | null; + +export function promisify(fn: (...args: any[]) => void): (...args: any[]) => any { + return (...args: any[]) => { + return new Promise((resolve, reject) => { + const nodeCallback = (err: NullableError, result: any) => { + if (err) reject(err); + else resolve(result); + }; + fn.apply(null, [...args, nodeCallback]); + }); + }; +} diff --git a/node_modules/csv-writer/src/lib/record.ts b/node_modules/csv-writer/src/lib/record.ts new file mode 100644 index 0000000..e757a96 --- /dev/null +++ b/node_modules/csv-writer/src/lib/record.ts @@ -0,0 +1,5 @@ + +export type Field = any; + +export type ObjectHeaderItem = { id: string; title: string }; +export type ObjectStringifierHeader = ObjectHeaderItem[] | string[]; diff --git a/node_modules/csv-writer/src/test/csv-stringifiers/array.test.ts b/node_modules/csv-writer/src/test/csv-stringifiers/array.test.ts new file mode 100644 index 0000000..49e4ed2 --- /dev/null +++ b/node_modules/csv-writer/src/test/csv-stringifiers/array.test.ts @@ -0,0 +1,100 @@ +import {resolveDelimiterChar} from '../helper/delimiter'; +import {createArrayCsvStringifier} from '../../index'; +import {strictEqual, throws} from 'assert'; + +describe('ArrayCsvStringifier', () => { + const records = [ + ['FIELD_A1', 'FIELD_B1'], + ['FIELD_A2', 'FIELD_B2'] + ]; + + describe('When field delimiter is comma', generateTestCases()); + + describe('When field delimiter is semicolon', generateTestCases(';')); + + describe('When field delimiter is neither comma nor semicolon', () => { + it('throws an exception', () => { + throws(() => { + createArrayCsvStringifier({fieldDelimiter: '/'}); + }); + }); + }); + + describe('When record delimiter is neither LF nor CR+LF', () => { + it('throws an exception', () => { + throws(() => { + createArrayCsvStringifier({recordDelimiter: '\r'}); + }); + }); + }); + + describe('When records input is an iterable other than an array', () => { + const stringifier = createArrayCsvStringifier({ + header: ['TITLE_A', 'TITLE_B'] + }); + function * recordGenerator() { + yield records[0]; + yield records[1]; + } + + it('converts the records into CSV', () => { + strictEqual( + stringifier.stringifyRecords(recordGenerator()), + 'FIELD_A1,FIELD_B1\nFIELD_A2,FIELD_B2\n' + ); + }); + }); + + describe('When `alwaysQuote` flag is set', () => { + const stringifier = createArrayCsvStringifier({ + header: ['TITLE_A', 'TITLE_B'], + alwaysQuote: true + }); + + it('quotes all header fields', () => { + strictEqual(stringifier.getHeaderString(), '"TITLE_A","TITLE_B"\n'); + }); + + it('quotes all data fields', () => { + strictEqual(stringifier.stringifyRecords(records), '"FIELD_A1","FIELD_B1"\n"FIELD_A2","FIELD_B2"\n'); + }); + }); + + function generateTestCases(fieldDelimiter?: string) { + const delim = resolveDelimiterChar(fieldDelimiter); + return () => { + describe('header is specified as a list of column titles', () => { + const stringifier = createArrayCsvStringifier({ + header: ['TITLE_A', 'TITLE_B'], + fieldDelimiter + }); + + it(`returns a header line with field separated by "${delim}"`, () => { + strictEqual(stringifier.getHeaderString(), `TITLE_A${delim}TITLE_B\n`); + }); + + it(`converts given data records into CSV lines with field separated by "${delim}"`, () => { + strictEqual( + stringifier.stringifyRecords(records), + `FIELD_A1${delim}FIELD_B1\nFIELD_A2${delim}FIELD_B2\n` + ); + }); + }); + + describe('header is not specified', () => { + const stringifier = createArrayCsvStringifier({fieldDelimiter}); + + it('returns null for header line', () => { + strictEqual(stringifier.getHeaderString(), null); + }); + + it(`converts given data records into CSV lines with field separated by "${delim}"`, () => { + strictEqual( + stringifier.stringifyRecords(records), + `FIELD_A1${delim}FIELD_B1\nFIELD_A2${delim}FIELD_B2\n` + ); + }); + }); + }; + } +}); diff --git a/node_modules/csv-writer/src/test/csv-stringifiers/object.test.ts b/node_modules/csv-writer/src/test/csv-stringifiers/object.test.ts new file mode 100644 index 0000000..fc88f28 --- /dev/null +++ b/node_modules/csv-writer/src/test/csv-stringifiers/object.test.ts @@ -0,0 +1,150 @@ +import {resolveDelimiterChar} from '../helper/delimiter'; +import {createObjectCsvStringifier} from '../../index'; +import {strictEqual, throws} from 'assert'; + +describe('ObjectCsvStringifier', () => { + const records = [ + {FIELD_A: 'VALUE_A1', FIELD_B: 'VALUE_B1'}, + {FIELD_A: 'VALUE_A2', FIELD_B: 'VALUE_B2', OTHERS: {FIELD_C: 'VALUE_C2'}} + ]; + + describe('When field delimiter is comma', generateTestCases()); + + describe('When field delimiter is semicolon', generateTestCases(';')); + + describe('When field delimiter is neither comma nor semicolon', () => { + it('throws an exception', () => { + throws(() => { + createObjectCsvStringifier({ + header: ['FIELD_A', 'FIELD_B'], + fieldDelimiter: '/' + }); + }); + }); + }); + + describe('When record delimiter is neither LF nor CR+LF', () => { + it('throws an exception', () => { + throws(() => { + createObjectCsvStringifier({ + header: ['FIELD_A', 'FIELD_B'], + recordDelimiter: '\r' + }); + }); + }); + }); + + describe('When records input is an iterable other than an array', () => { + const stringifier = createObjectCsvStringifier({ + header: ['FIELD_A', 'FIELD_B'] + }); + function * recordGenerator() { + yield records[0]; + yield records[1]; + } + + it('converts the records into CSV', () => { + strictEqual( + stringifier.stringifyRecords(recordGenerator()), + 'VALUE_A1,VALUE_B1\nVALUE_A2,VALUE_B2\n' + ); + }); + }); + + describe('When `alwaysQuote` flag is set', () => { + const stringifier = createObjectCsvStringifier({ + header: [ + {id: 'FIELD_A', title: 'TITLE_A'}, + {id: 'FIELD_B', title: 'TITLE_B'} + ], + alwaysQuote: true + }); + + it('quotes all header fields', () => { + strictEqual(stringifier.getHeaderString(), '"TITLE_A","TITLE_B"\n'); + }); + + it('quotes all data fields', () => { + strictEqual(stringifier.stringifyRecords(records), '"VALUE_A1","VALUE_B1"\n"VALUE_A2","VALUE_B2"\n'); + }); + }); + + describe('When `headerIdDelimiter` is set', () => { + const stringifier = createObjectCsvStringifier({ + header: [ + {id: 'FIELD_A', title: 'TITLE_A'}, + {id: 'OTHERS/FIELD_C', title: 'TITLE_C'} + ], + headerIdDelimiter: '/' + }); + + it('uses the title as is', () => { + strictEqual(stringifier.getHeaderString(), 'TITLE_A,TITLE_C\n'); + }); + + it('picks up a value in nested objects', () => { + strictEqual(stringifier.stringifyRecords(records), 'VALUE_A1,\nVALUE_A2,VALUE_C2\n'); + }); + }); + + function generateTestCases(fieldDelimiter?: string) { + const delim = resolveDelimiterChar(fieldDelimiter); + return () => { + describe('header is specified with title', () => { + const stringifier = createObjectCsvStringifier({ + header: [ + {id: 'FIELD_A', title: 'TITLE_A'}, + {id: 'FIELD_B', title: 'TITLE_B'} + ], + fieldDelimiter + }); + + it(`returns a header line with field separated by "${delim}"`, () => { + strictEqual(stringifier.getHeaderString(), `TITLE_A${delim}TITLE_B\n`); + }); + + it(`converts given data records into CSV lines with field separated by "${delim}"`, () => { + strictEqual( + stringifier.stringifyRecords(records), + `VALUE_A1${delim}VALUE_B1\nVALUE_A2${delim}VALUE_B2\n` + ); + }); + }); + + describe('header is specified without title', () => { + const stringifier = createObjectCsvStringifier({ + header: ['FIELD_A', 'FIELD_B'], + fieldDelimiter + }); + + it('returns null for header line', () => { + strictEqual(stringifier.getHeaderString(), null); + }); + + it(`converts given data records into CSV lines with field separated by "${delim}"`, () => { + strictEqual( + stringifier.stringifyRecords(records), + `VALUE_A1${delim}VALUE_B1\nVALUE_A2${delim}VALUE_B2\n` + ); + }); + }); + + describe('header columns are given with reverse order', () => { + const stringifier = createObjectCsvStringifier({ + header: [ + {id: 'FIELD_B', title: 'TITLE_B'}, + {id: 'FIELD_A', title: 'TITLE_A'} + ], + fieldDelimiter + }); + + it(`layouts fields with the order of headers given with field separated by "${delim}"`, () => { + strictEqual( + stringifier.stringifyRecords(records), + `VALUE_B1${delim}VALUE_A1\nVALUE_B2${delim}VALUE_A2\n` + ); + }); + }); + }; + } +}); diff --git a/node_modules/csv-writer/src/test/field-stringifier.test.ts b/node_modules/csv-writer/src/test/field-stringifier.test.ts new file mode 100644 index 0000000..93dbbea --- /dev/null +++ b/node_modules/csv-writer/src/test/field-stringifier.test.ts @@ -0,0 +1,97 @@ +import {resolveDelimiterChar} from './helper/delimiter'; +import {createFieldStringifier} from '../lib/field-stringifier'; +import {strictEqual} from 'assert'; + +describe('DefaultFieldStringifier', () => { + + describe('When field delimiter is comma', generateTestCases(',')); + + describe('When field delimiter is semicolon', generateTestCases(';')); + + describe('When all fields needs to be quoted', () => { + const stringifier = createFieldStringifier(',', true); + + it('quotes a field', () => { + strictEqual(stringifier.stringify('VALUE'), '"VALUE"'); + }); + + it('does not quote a field of value undefined', () => { + strictEqual(stringifier.stringify(), ''); + }); + + it('does not quote a field of value null', () => { + strictEqual(stringifier.stringify(null), ''); + }); + + it('does not quote a field of value empty string', () => { + strictEqual(stringifier.stringify(''), ''); + }); + }); + + function generateTestCases(fieldDelimiter: string) { + const delim = resolveDelimiterChar(fieldDelimiter); + return () => { + const stringifier = createFieldStringifier(fieldDelimiter); + + it('returns the same string', () => { + strictEqual(stringifier.stringify('VALUE'), 'VALUE'); + }); + + it('preserves the whitespace characters', () => { + strictEqual(stringifier.stringify(' VALUE\tA '), ' VALUE\tA '); + }); + + it(`wraps a field value with double quotes if the field contains "${delim}"`, () => { + strictEqual(stringifier.stringify(`VALUE${delim}A`), `"VALUE${delim}A"`); + }); + + it('wraps a field value with double quotes if the field contains newline', () => { + strictEqual(stringifier.stringify('VALUE\nA'), '"VALUE\nA"'); + }); + + it('wraps a field value with double quotes and escape the double quotes if they are used in the field', () => { + strictEqual(stringifier.stringify('VALUE"A'), '"VALUE""A"'); + }); + + it('escapes double quotes even if double quotes are only on the both edges of the field', () => { + strictEqual(stringifier.stringify('"VALUE"'), '"""VALUE"""'); + }); + + it('converts a number into a string', () => { + strictEqual(stringifier.stringify(1), '1'); + }); + + it('converts undefined into an empty string', () => { + strictEqual(stringifier.stringify(), ''); + }); + + it('converts null into an empty string', () => { + strictEqual(stringifier.stringify(null), ''); + }); + + it('converts an object into toString-ed value', () => { + const obj = { + name: 'OBJECT_NAME', + toString: function () { return `Name: ${this.name}`; } + }; + strictEqual(stringifier.stringify(obj), 'Name: OBJECT_NAME'); + }); + + it(`wraps a toString-ed field value with double quote if the value contains "${delim}"`, () => { + const obj = { + name: `OBJECT${delim}NAME`, + toString: function () { return `Name: ${this.name}`; } + }; + strictEqual(stringifier.stringify(obj), `"Name: OBJECT${delim}NAME"`); + }); + + it('escapes double quotes in a toString-ed field value if the value has double quotes', () => { + const obj = { + name: 'OBJECT_NAME"', + toString: function () { return `Name: ${this.name}`; } + }; + strictEqual(stringifier.stringify(obj), '"Name: OBJECT_NAME"""'); + }); + }; + } +}); diff --git a/node_modules/csv-writer/src/test/helper.ts b/node_modules/csv-writer/src/test/helper.ts new file mode 100644 index 0000000..e08c4b7 --- /dev/null +++ b/node_modules/csv-writer/src/test/helper.ts @@ -0,0 +1,16 @@ +import {strictEqual} from 'assert'; +import {readFileSync} from 'fs'; + +export const testFilePath = (id: string) => `./test-tmp/${id}.csv`; + +export const assertFile = (path: string, expectedContents: string, encoding?: string) => { + const actualContents = readFileSync(path, encoding || 'utf8'); + strictEqual(actualContents, expectedContents); +}; + +export const assertRejected = (p: Promise, message: string) => { + return p.then( + () => new Error('Should not have been called'), + (e: Error) => { strictEqual(e.message, message); } + ); +}; diff --git a/node_modules/csv-writer/src/test/helper/delimiter.ts b/node_modules/csv-writer/src/test/helper/delimiter.ts new file mode 100644 index 0000000..75ca063 --- /dev/null +++ b/node_modules/csv-writer/src/test/helper/delimiter.ts @@ -0,0 +1,6 @@ + +export const resolveDelimiterChar = (char?: string) => { + if (char === ',' || char === ';') return char; + if (typeof char === 'undefined') return ','; + throw new Error('Invalid field delimiter'); +}; diff --git a/node_modules/csv-writer/src/test/lang/promise.test.ts b/node_modules/csv-writer/src/test/lang/promise.test.ts new file mode 100644 index 0000000..6782f1b --- /dev/null +++ b/node_modules/csv-writer/src/test/lang/promise.test.ts @@ -0,0 +1,21 @@ +import {promisify} from '../../lib/lang/promise'; +import {strictEqual} from 'assert'; +import {assertRejected} from '../helper'; + +describe('Promise', () => { + const greetAsync = (name: string, callback: (err: Error | null, result?: string) => void) => { + setTimeout(() => { + if (name === 'foo') callback(null, `Hello, ${name}!`); + else callback(new Error(`We don't know ${name}`)); + }, 0); + }; + const promisifiedFn = promisify(greetAsync); + + it('promisify node style callback', async () => { + strictEqual(await promisifiedFn('foo'), 'Hello, foo!'); + }); + + it('raise an error for error', async () => { + await assertRejected(promisifiedFn('bar'), "We don't know bar"); + }); +}); diff --git a/node_modules/csv-writer/src/test/write-array-records.test.ts b/node_modules/csv-writer/src/test/write-array-records.test.ts new file mode 100644 index 0000000..9ae0a75 --- /dev/null +++ b/node_modules/csv-writer/src/test/write-array-records.test.ts @@ -0,0 +1,124 @@ +import {assertFile, testFilePath} from './helper'; +import {CsvWriter} from '../lib/csv-writer'; +import {writeFileSync} from 'fs'; +import {createArrayCsvWriter} from '../index'; + +describe('Write array records into CSV', () => { + + const makeFilePath = (id: string) => testFilePath(`array-${id}`); + const records = [ + ['Bob', 'French'], + ['Mary', 'English'] + ]; + + describe('When only path is specified', () => { + const filePath = makeFilePath('minimum'); + let writer: CsvWriter; + + beforeEach(() => { + writer = createArrayCsvWriter({path: filePath}); + }); + + it('writes records to a new file', async () => { + await writer.writeRecords(records); + assertFile(filePath, 'Bob,French\nMary,English\n'); + }); + + it('appends records when requested to write to the same file', async () => { + await writer.writeRecords([records[0]]); + await writer.writeRecords([records[1]]); + assertFile(filePath, 'Bob,French\nMary,English\n'); + }); + }); + + describe('When field header is given', () => { + const filePath = makeFilePath('header'); + let writer: CsvWriter; + + beforeEach(() => { + writer = createArrayCsvWriter({ + path: filePath, + header: ['NAME', 'LANGUAGE'] + }); + }); + + it('writes a header', async () => { + await writer.writeRecords(records); + assertFile(filePath, 'NAME,LANGUAGE\nBob,French\nMary,English\n'); + }); + + it('appends records without headers', async () => { + await writer.writeRecords([records[0]]); + await writer.writeRecords([records[1]]); + assertFile(filePath, 'NAME,LANGUAGE\nBob,French\nMary,English\n'); + }); + }); + + describe('When `append` flag is specified', () => { + const filePath = makeFilePath('append'); + writeFileSync(filePath, 'Mike,German\n', 'utf8'); + const writer = createArrayCsvWriter({ + path: filePath, + append: true + }); + + it('do not overwrite the existing contents and appends records to them', async () => { + await writer.writeRecords([records[1]]); + assertFile(filePath, 'Mike,German\nMary,English\n'); + }); + }); + + describe('When encoding is specified', () => { + const filePath = makeFilePath('encoding'); + const writer = createArrayCsvWriter({ + path: filePath, + encoding: 'utf16le' + }); + + it('writes to a file with the specified encoding', async () => { + await writer.writeRecords(records); + assertFile(filePath, 'Bob,French\nMary,English\n', 'utf16le'); + }); + }); + + describe('When semicolon is specified as a field delimiter', () => { + const filePath = makeFilePath('field-delimiter'); + const writer = createArrayCsvWriter({ + path: filePath, + header: ['NAME', 'LANGUAGE'], + fieldDelimiter: ';' + }); + + it('uses semicolon instead of comma to separate fields', async () => { + await writer.writeRecords(records); + assertFile(filePath, 'NAME;LANGUAGE\nBob;French\nMary;English\n'); + }); + }); + + describe('When newline is specified', () => { + const filePath = makeFilePath('newline'); + const writer = createArrayCsvWriter({ + path: filePath, + recordDelimiter: '\r\n' + }); + + it('writes to a file with the specified newline character', async () => { + await writer.writeRecords(records); + assertFile(filePath, 'Bob,French\r\nMary,English\r\n'); + }); + }); + + describe('When `alwaysQuote` flag is set', () => { + const filePath = makeFilePath('always-quote'); + const writer = createArrayCsvWriter({ + path: filePath, + header: ['NAME', 'LANGUAGE'], + alwaysQuote: true + }); + + it('quotes all fields', async () => { + await writer.writeRecords(records); + assertFile(filePath, '"NAME","LANGUAGE"\n"Bob","French"\n"Mary","English"\n'); + }); + }); +}); diff --git a/node_modules/csv-writer/src/test/write-object-records.test.ts b/node_modules/csv-writer/src/test/write-object-records.test.ts new file mode 100644 index 0000000..f94f02f --- /dev/null +++ b/node_modules/csv-writer/src/test/write-object-records.test.ts @@ -0,0 +1,158 @@ +import {assertFile, testFilePath} from './helper'; +import {CsvWriter} from '../lib/csv-writer'; +import {writeFileSync} from 'fs'; +import {createObjectCsvWriter} from '../index'; +import {ObjectMap} from '../lib/lang/object'; + +describe('Write object records into CSV', () => { + + const makeFilePath = (id: string) => testFilePath(`object-${id}`); + const records = [ + {name: 'Bob', lang: 'French', address: {country: 'France'}}, + {name: 'Mary', lang: 'English'} + ]; + + describe('When only path and header ids are given', () => { + const filePath = makeFilePath('minimum'); + let writer: CsvWriter>; + + beforeEach(() => { + writer = createObjectCsvWriter({ + path: filePath, + header: ['name', 'lang'] + }); + }); + + it('writes records to a new file', async () => { + await writer.writeRecords(records); + assertFile(filePath, 'Bob,French\nMary,English\n'); + }); + + it('appends records when requested to write to the same file', async () => { + await writer.writeRecords([records[0]]); + await writer.writeRecords([records[1]]); + assertFile(filePath, 'Bob,French\nMary,English\n'); + }); + }); + + describe('When header ids are given with reverse order', () => { + const filePath = makeFilePath('column-order'); + const writer = createObjectCsvWriter({ + path: filePath, + header: ['lang', 'name'] + }); + + it('also writes columns with reverse order', async () => { + await writer.writeRecords(records); + assertFile(filePath, 'French,Bob\nEnglish,Mary\n'); + }); + }); + + describe('When field header is given with titles', () => { + const filePath = makeFilePath('header'); + let writer: CsvWriter>; + + beforeEach(() => { + writer = createObjectCsvWriter({ + path: filePath, + header: [{id: 'name', title: 'NAME'}, {id: 'lang', title: 'LANGUAGE'}] + }); + }); + + it('writes a header', async () => { + await writer.writeRecords(records); + assertFile(filePath, 'NAME,LANGUAGE\nBob,French\nMary,English\n'); + }); + + it('appends records without headers', async () => { + await writer.writeRecords([records[0]]); + await writer.writeRecords([records[1]]); + assertFile(filePath, 'NAME,LANGUAGE\nBob,French\nMary,English\n'); + }); + }); + + describe('When `append` flag is specified', () => { + const filePath = makeFilePath('append'); + writeFileSync(filePath, 'Mike,German\n', 'utf8'); + const writer = createObjectCsvWriter({ + path: filePath, + header: ['name', 'lang'], + append: true + }); + + it('do not overwrite the existing contents and appends records to them', async () => { + await writer.writeRecords([records[1]]); + assertFile(filePath, 'Mike,German\nMary,English\n'); + }); + }); + + describe('When encoding is specified', () => { + const filePath = makeFilePath('encoding'); + const writer = createObjectCsvWriter({ + path: filePath, + header: ['name', 'lang'], + encoding: 'utf16le' + }); + + it('writes to a file with the specified encoding', async () => { + await writer.writeRecords(records); + assertFile(filePath, 'Bob,French\nMary,English\n', 'utf16le'); + }); + }); + + describe('When semicolon is specified as a field delimiter', () => { + const filePath = makeFilePath('field-delimiter'); + const writer = createObjectCsvWriter({ + path: filePath, + header: [{id: 'name', title: 'NAME'}, {id: 'lang', title: 'LANGUAGE'}], + fieldDelimiter: ';' + }); + + it('uses semicolon instead of comma to separate fields', async () => { + await writer.writeRecords(records); + assertFile(filePath, 'NAME;LANGUAGE\nBob;French\nMary;English\n'); + }); + }); + + describe('When newline is specified', () => { + const filePath = makeFilePath('newline'); + const writer = createObjectCsvWriter({ + path: filePath, + header: ['name', 'lang'], + recordDelimiter: '\r\n' + }); + + it('writes to a file with the specified newline character', async () => { + await writer.writeRecords(records); + assertFile(filePath, 'Bob,French\r\nMary,English\r\n'); + }); + }); + + describe('When `alwaysQuote` flag is set', () => { + const filePath = makeFilePath('always-quote'); + const writer = createObjectCsvWriter({ + path: filePath, + header: [{id: 'name', title: 'NAME'}, {id: 'lang', title: 'LANGUAGE'}], + alwaysQuote: true + }); + + it('quotes all fields', async () => { + await writer.writeRecords(records); + assertFile(filePath, '"NAME","LANGUAGE"\n"Bob","French"\n"Mary","English"\n'); + }); + }); + + describe('When `headerIdDelimiter` flag is set', () => { + const filePath = makeFilePath('nested'); + const writer = createObjectCsvWriter({ + path: filePath, + header: [{id: 'name', title: 'NAME'}, {id: 'address.country', title: 'COUNTRY'}], + headerIdDelimiter: '.' + }); + + it('breaks keys into key paths', async () => { + await writer.writeRecords(records); + assertFile(filePath, 'NAME,COUNTRY\nBob,France\nMary,\n'); + }); + }); +}); diff --git a/node_modules/fs/README.md b/node_modules/fs/README.md new file mode 100644 index 0000000..5e9a74c --- /dev/null +++ b/node_modules/fs/README.md @@ -0,0 +1,9 @@ +# Security holding package + +This package name is not currently in use, but was formerly occupied +by another package. To avoid malicious use, npm is hanging on to the +package name, but loosely, and we'll probably give it to you if you +want it. + +You may adopt this package by contacting support@npmjs.com and +requesting the name. diff --git a/node_modules/fs/package.json b/node_modules/fs/package.json new file mode 100644 index 0000000..11661b0 --- /dev/null +++ b/node_modules/fs/package.json @@ -0,0 +1,20 @@ +{ + "name": "fs", + "version": "0.0.1-security", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/npm/security-holder.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/npm/security-holder/issues" + }, + "homepage": "https://github.com/npm/security-holder#readme" +} diff --git a/node_modules/minimist/.eslintrc b/node_modules/minimist/.eslintrc new file mode 100644 index 0000000..bd1a5e0 --- /dev/null +++ b/node_modules/minimist/.eslintrc @@ -0,0 +1,29 @@ +{ + "root": true, + + "extends": "@ljharb/eslint-config/node/0.4", + + "rules": { + "array-element-newline": 0, + "complexity": 0, + "func-style": [2, "declaration"], + "max-lines-per-function": 0, + "max-nested-callbacks": 1, + "max-statements-per-line": 1, + "max-statements": 0, + "multiline-comment-style": 0, + "no-continue": 1, + "no-param-reassign": 1, + "no-restricted-syntax": 1, + "object-curly-newline": 0, + }, + + "overrides": [ + { + "files": "test/**", + "rules": { + "camelcase": 0, + }, + }, + ] +} diff --git a/node_modules/minimist/.github/FUNDING.yml b/node_modules/minimist/.github/FUNDING.yml new file mode 100644 index 0000000..a936622 --- /dev/null +++ b/node_modules/minimist/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [ljharb] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: npm/minimist +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/node_modules/minimist/.nycrc b/node_modules/minimist/.nycrc new file mode 100644 index 0000000..55c3d29 --- /dev/null +++ b/node_modules/minimist/.nycrc @@ -0,0 +1,14 @@ +{ + "all": true, + "check-coverage": false, + "reporter": ["text-summary", "text", "html", "json"], + "lines": 86, + "statements": 85.93, + "functions": 82.43, + "branches": 76.06, + "exclude": [ + "coverage", + "example", + "test" + ] +} diff --git a/node_modules/minimist/CHANGELOG.md b/node_modules/minimist/CHANGELOG.md new file mode 100644 index 0000000..c9a1e15 --- /dev/null +++ b/node_modules/minimist/CHANGELOG.md @@ -0,0 +1,298 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [v1.2.8](https://github.com/minimistjs/minimist/compare/v1.2.7...v1.2.8) - 2023-02-09 + +### Merged + +- [Fix] Fix long option followed by single dash [`#17`](https://github.com/minimistjs/minimist/pull/17) +- [Tests] Remove duplicate test [`#12`](https://github.com/minimistjs/minimist/pull/12) +- [Fix] opt.string works with multiple aliases [`#10`](https://github.com/minimistjs/minimist/pull/10) + +### Fixed + +- [Fix] Fix long option followed by single dash (#17) [`#15`](https://github.com/minimistjs/minimist/issues/15) +- [Tests] Remove duplicate test (#12) [`#8`](https://github.com/minimistjs/minimist/issues/8) +- [Fix] Fix long option followed by single dash [`#15`](https://github.com/minimistjs/minimist/issues/15) +- [Fix] opt.string works with multiple aliases (#10) [`#9`](https://github.com/minimistjs/minimist/issues/9) +- [Fix] Fix handling of short option with non-trivial equals [`#5`](https://github.com/minimistjs/minimist/issues/5) +- [Tests] Remove duplicate test [`#8`](https://github.com/minimistjs/minimist/issues/8) +- [Fix] opt.string works with multiple aliases [`#9`](https://github.com/minimistjs/minimist/issues/9) + +### Commits + +- Merge tag 'v0.2.3' [`a026794`](https://github.com/minimistjs/minimist/commit/a0267947c7870fc5847cf2d437fbe33f392767da) +- [eslint] fix indentation and whitespace [`5368ca4`](https://github.com/minimistjs/minimist/commit/5368ca4147e974138a54cc0dc4cea8f756546b70) +- [eslint] fix indentation and whitespace [`e5f5067`](https://github.com/minimistjs/minimist/commit/e5f5067259ceeaf0b098d14bec910f87e58708c7) +- [eslint] more cleanup [`62fde7d`](https://github.com/minimistjs/minimist/commit/62fde7d935f83417fb046741531a9e2346a36976) +- [eslint] more cleanup [`36ac5d0`](https://github.com/minimistjs/minimist/commit/36ac5d0d95e4947d074e5737d94814034ca335d1) +- [meta] add `auto-changelog` [`73923d2`](https://github.com/minimistjs/minimist/commit/73923d223553fca08b1ba77e3fbc2a492862ae4c) +- [actions] add reusable workflows [`d80727d`](https://github.com/minimistjs/minimist/commit/d80727df77bfa9e631044d7f16368d8f09242c91) +- [eslint] add eslint; rules to enable later are warnings [`48bc06a`](https://github.com/minimistjs/minimist/commit/48bc06a1b41f00e9cdf183db34f7a51ba70e98d4) +- [eslint] fix indentation [`34b0f1c`](https://github.com/minimistjs/minimist/commit/34b0f1ccaa45183c3c4f06a91f9b405180a6f982) +- [readme] rename and add badges [`5df0fe4`](https://github.com/minimistjs/minimist/commit/5df0fe49211bd09a3636f8686a7cb3012c3e98f0) +- [Dev Deps] switch from `covert` to `nyc` [`a48b128`](https://github.com/minimistjs/minimist/commit/a48b128fdb8d427dfb20a15273f83e38d97bef07) +- [Dev Deps] update `covert`, `tape`; remove unnecessary `tap` [`f0fb958`](https://github.com/minimistjs/minimist/commit/f0fb958e9a1fe980cdffc436a211b0bda58f621b) +- [meta] create FUNDING.yml; add `funding` in package.json [`3639e0c`](https://github.com/minimistjs/minimist/commit/3639e0c819359a366387e425ab6eabf4c78d3caa) +- [meta] use `npmignore` to autogenerate an npmignore file [`be2e038`](https://github.com/minimistjs/minimist/commit/be2e038c342d8333b32f0fde67a0026b79c8150e) +- Only apps should have lockfiles [`282b570`](https://github.com/minimistjs/minimist/commit/282b570e7489d01b03f2d6d3dabf79cd3e5f84cf) +- isConstructorOrProto adapted from PR [`ef9153f`](https://github.com/minimistjs/minimist/commit/ef9153fc52b6cea0744b2239921c5dcae4697f11) +- [Dev Deps] update `@ljharb/eslint-config`, `aud` [`098873c`](https://github.com/minimistjs/minimist/commit/098873c213cdb7c92e55ae1ef5aa1af3a8192a79) +- [Dev Deps] update `@ljharb/eslint-config`, `aud` [`3124ed3`](https://github.com/minimistjs/minimist/commit/3124ed3e46306301ebb3c834874ce0241555c2c4) +- [meta] add `safe-publish-latest` [`4b927de`](https://github.com/minimistjs/minimist/commit/4b927de696d561c636b4f43bf49d4597cb36d6d6) +- [Tests] add `aud` in `posttest` [`b32d9bd`](https://github.com/minimistjs/minimist/commit/b32d9bd0ab340f4e9f8c3a97ff2a4424f25fab8c) +- [meta] update repo URLs [`f9fdfc0`](https://github.com/minimistjs/minimist/commit/f9fdfc032c54884d9a9996a390c63cd0719bbe1a) +- [actions] Avoid 0.6 tests due to build failures [`ba92fe6`](https://github.com/minimistjs/minimist/commit/ba92fe6ebbdc0431cca9a2ea8f27beb492f5e4ec) +- [Dev Deps] update `tape` [`950eaa7`](https://github.com/minimistjs/minimist/commit/950eaa74f112e04d23e9c606c67472c46739b473) +- [Dev Deps] add missing `npmignore` dev dep [`3226afa`](https://github.com/minimistjs/minimist/commit/3226afaf09e9d127ca369742437fe6e88f752d6b) +- Merge tag 'v0.2.2' [`980d7ac`](https://github.com/minimistjs/minimist/commit/980d7ac61a0b4bd552711251ac107d506b23e41f) + +## [v1.2.7](https://github.com/minimistjs/minimist/compare/v1.2.6...v1.2.7) - 2022-10-10 + +### Commits + +- [meta] add `auto-changelog` [`0ebf4eb`](https://github.com/minimistjs/minimist/commit/0ebf4ebcd5f7787a5524d31a849ef41316b83c3c) +- [actions] add reusable workflows [`e115b63`](https://github.com/minimistjs/minimist/commit/e115b63fa9d3909f33b00a2db647ff79068388de) +- [eslint] add eslint; rules to enable later are warnings [`f58745b`](https://github.com/minimistjs/minimist/commit/f58745b9bb84348e1be72af7dbba5840c7c13013) +- [Dev Deps] switch from `covert` to `nyc` [`ab03356`](https://github.com/minimistjs/minimist/commit/ab033567b9c8b31117cb026dc7f1e592ce455c65) +- [readme] rename and add badges [`236f4a0`](https://github.com/minimistjs/minimist/commit/236f4a07e4ebe5ee44f1496ec6974991ab293ffd) +- [meta] create FUNDING.yml; add `funding` in package.json [`783a49b`](https://github.com/minimistjs/minimist/commit/783a49bfd47e8335d3098a8cac75662cf71eb32a) +- [meta] use `npmignore` to autogenerate an npmignore file [`f81ece6`](https://github.com/minimistjs/minimist/commit/f81ece6aaec2fa14e69ff4f1e0407a8c4e2635a2) +- Only apps should have lockfiles [`56cad44`](https://github.com/minimistjs/minimist/commit/56cad44c7f879b9bb5ec18fcc349308024a89bfc) +- [Dev Deps] update `covert`, `tape`; remove unnecessary `tap` [`49c5f9f`](https://github.com/minimistjs/minimist/commit/49c5f9fb7e6a92db9eb340cc679de92fb3aacded) +- [Tests] add `aud` in `posttest` [`228ae93`](https://github.com/minimistjs/minimist/commit/228ae938f3cd9db9dfd8bd7458b076a7b2aef280) +- [meta] add `safe-publish-latest` [`01fc23f`](https://github.com/minimistjs/minimist/commit/01fc23f5104f85c75059972e01dd33796ab529ff) +- [meta] update repo URLs [`6b164c7`](https://github.com/minimistjs/minimist/commit/6b164c7d68e0b6bf32f894699effdfb7c63041dd) + +## [v1.2.6](https://github.com/minimistjs/minimist/compare/v1.2.5...v1.2.6) - 2022-03-21 + +### Commits + +- test from prototype pollution PR [`bc8ecee`](https://github.com/minimistjs/minimist/commit/bc8ecee43875261f4f17eb20b1243d3ed15e70eb) +- isConstructorOrProto adapted from PR [`c2b9819`](https://github.com/minimistjs/minimist/commit/c2b981977fa834b223b408cfb860f933c9811e4d) +- security notice for additional prototype pollution issue [`ef88b93`](https://github.com/minimistjs/minimist/commit/ef88b9325f77b5ee643ccfc97e2ebda577e4c4e2) + +## [v1.2.5](https://github.com/minimistjs/minimist/compare/v1.2.4...v1.2.5) - 2020-03-12 + +## [v1.2.4](https://github.com/minimistjs/minimist/compare/v1.2.3...v1.2.4) - 2020-03-11 + +### Commits + +- security notice [`4cf1354`](https://github.com/minimistjs/minimist/commit/4cf1354839cb972e38496d35e12f806eea92c11f) +- additional test for constructor prototype pollution [`1043d21`](https://github.com/minimistjs/minimist/commit/1043d212c3caaf871966e710f52cfdf02f9eea4b) + +## [v1.2.3](https://github.com/minimistjs/minimist/compare/v1.2.2...v1.2.3) - 2020-03-10 + +### Commits + +- more failing proto pollution tests [`13c01a5`](https://github.com/minimistjs/minimist/commit/13c01a5327736903704984b7f65616b8476850cc) +- even more aggressive checks for protocol pollution [`38a4d1c`](https://github.com/minimistjs/minimist/commit/38a4d1caead72ef99e824bb420a2528eec03d9ab) + +## [v1.2.2](https://github.com/minimistjs/minimist/compare/v1.2.1...v1.2.2) - 2020-03-10 + +### Commits + +- failing test for protocol pollution [`0efed03`](https://github.com/minimistjs/minimist/commit/0efed0340ec8433638758f7ca0c77cb20a0bfbab) +- cleanup [`67d3722`](https://github.com/minimistjs/minimist/commit/67d3722413448d00a62963d2d30c34656a92d7e2) +- console.dir -> console.log [`47acf72`](https://github.com/minimistjs/minimist/commit/47acf72c715a630bf9ea013867f47f1dd69dfc54) +- don't assign onto __proto__ [`63e7ed0`](https://github.com/minimistjs/minimist/commit/63e7ed05aa4b1889ec2f3b196426db4500cbda94) + +## [v1.2.1](https://github.com/minimistjs/minimist/compare/v1.2.0...v1.2.1) - 2020-03-10 + +### Merged + +- move the `opts['--']` example back where it belongs [`#63`](https://github.com/minimistjs/minimist/pull/63) + +### Commits + +- add test [`6be5dae`](https://github.com/minimistjs/minimist/commit/6be5dae35a32a987bcf4137fcd6c19c5200ee909) +- fix bad boolean regexp [`ac3fc79`](https://github.com/minimistjs/minimist/commit/ac3fc796e63b95128fdbdf67ea7fad71bd59aa76) + +## [v1.2.0](https://github.com/minimistjs/minimist/compare/v1.1.3...v1.2.0) - 2015-08-24 + +### Commits + +- failing -k=v short test [`63416b8`](https://github.com/minimistjs/minimist/commit/63416b8cd1d0d70e4714564cce465a36e4dd26d7) +- kv short fix [`6bbe145`](https://github.com/minimistjs/minimist/commit/6bbe14529166245e86424f220a2321442fe88dc3) +- failing kv short test [`f72ab7f`](https://github.com/minimistjs/minimist/commit/f72ab7f4572adc52902c9b6873cc969192f01b10) +- fixed kv test [`f5a48c3`](https://github.com/minimistjs/minimist/commit/f5a48c3e50e40ca54f00c8e84de4b4d6e9897fa8) +- enforce space between arg key and value [`86b321a`](https://github.com/minimistjs/minimist/commit/86b321affe648a8e016c095a4f0efa9d9074f502) + +## [v1.1.3](https://github.com/minimistjs/minimist/compare/v1.1.2...v1.1.3) - 2015-08-06 + +### Commits + +- add failing test - boolean alias array [`0fa3c5b`](https://github.com/minimistjs/minimist/commit/0fa3c5b3dd98551ddecf5392831b4c21211743fc) +- fix boolean values with multiple aliases [`9c0a6e7`](https://github.com/minimistjs/minimist/commit/9c0a6e7de25a273b11bbf9a7464f0bd833779795) + +## [v1.1.2](https://github.com/minimistjs/minimist/compare/v1.1.1...v1.1.2) - 2015-07-22 + +### Commits + +- Convert boolean arguments to boolean values [`8f3dc27`](https://github.com/minimistjs/minimist/commit/8f3dc27cf833f1d54671b6d0bcb55c2fe19672a9) +- use non-ancient npm, node 0.12 and iojs [`61ed1d0`](https://github.com/minimistjs/minimist/commit/61ed1d034b9ec7282764ce76f3992b1a0b4906ae) +- an older npm for 0.8 [`25cf778`](https://github.com/minimistjs/minimist/commit/25cf778b1220e7838a526832ad6972f75244054f) + +## [v1.1.1](https://github.com/minimistjs/minimist/compare/v1.1.0...v1.1.1) - 2015-03-10 + +### Commits + +- check that they type of a value is a boolean, not just that it is currently set to a boolean [`6863198`](https://github.com/minimistjs/minimist/commit/6863198e36139830ff1f20ffdceaddd93f2c1db9) +- upgrade tape, fix type issues from old tape version [`806712d`](https://github.com/minimistjs/minimist/commit/806712df91604ed02b8e39aa372b84aea659ee34) +- test for setting a boolean to a null default [`8c444fe`](https://github.com/minimistjs/minimist/commit/8c444fe89384ded7d441c120915ea60620b01dd3) +- if the previous value was a boolean, without an default (or with an alias) don't make an array either [`e5f419a`](https://github.com/minimistjs/minimist/commit/e5f419a3b5b3bc3f9e5ac71b7040621af70ed2dd) + +## [v1.1.0](https://github.com/minimistjs/minimist/compare/v1.0.0...v1.1.0) - 2014-08-10 + +### Commits + +- add support for handling "unknown" options not registered with the parser. [`6f3cc5d`](https://github.com/minimistjs/minimist/commit/6f3cc5d4e84524932a6ef2ce3592acc67cdd4383) +- reformat package.json [`02ed371`](https://github.com/minimistjs/minimist/commit/02ed37115194d3697ff358e8e25e5e66bab1d9f8) +- coverage script [`e5531ba`](https://github.com/minimistjs/minimist/commit/e5531ba0479da3b8138d3d8cac545d84ccb1c8df) +- extra fn to get 100% coverage again [`a6972da`](https://github.com/minimistjs/minimist/commit/a6972da89e56bf77642f8ec05a13b6558db93498) + +## [v1.0.0](https://github.com/minimistjs/minimist/compare/v0.2.3...v1.0.0) - 2014-08-10 + +### Commits + +- added stopEarly option [`471c7e4`](https://github.com/minimistjs/minimist/commit/471c7e4a7e910fc7ad8f9df850a186daf32c64e9) +- fix list [`fef6ae7`](https://github.com/minimistjs/minimist/commit/fef6ae79c38b9dc1c49569abb7cd04eb965eac5e) + +## [v0.2.3](https://github.com/minimistjs/minimist/compare/v0.2.2...v0.2.3) - 2023-02-09 + +### Merged + +- [Fix] Fix long option followed by single dash [`#17`](https://github.com/minimistjs/minimist/pull/17) +- [Tests] Remove duplicate test [`#12`](https://github.com/minimistjs/minimist/pull/12) +- [Fix] opt.string works with multiple aliases [`#10`](https://github.com/minimistjs/minimist/pull/10) + +### Fixed + +- [Fix] Fix long option followed by single dash (#17) [`#15`](https://github.com/minimistjs/minimist/issues/15) +- [Tests] Remove duplicate test (#12) [`#8`](https://github.com/minimistjs/minimist/issues/8) +- [Fix] opt.string works with multiple aliases (#10) [`#9`](https://github.com/minimistjs/minimist/issues/9) + +### Commits + +- [eslint] fix indentation and whitespace [`e5f5067`](https://github.com/minimistjs/minimist/commit/e5f5067259ceeaf0b098d14bec910f87e58708c7) +- [eslint] more cleanup [`36ac5d0`](https://github.com/minimistjs/minimist/commit/36ac5d0d95e4947d074e5737d94814034ca335d1) +- [eslint] fix indentation [`34b0f1c`](https://github.com/minimistjs/minimist/commit/34b0f1ccaa45183c3c4f06a91f9b405180a6f982) +- isConstructorOrProto adapted from PR [`ef9153f`](https://github.com/minimistjs/minimist/commit/ef9153fc52b6cea0744b2239921c5dcae4697f11) +- [Dev Deps] update `@ljharb/eslint-config`, `aud` [`098873c`](https://github.com/minimistjs/minimist/commit/098873c213cdb7c92e55ae1ef5aa1af3a8192a79) +- [Dev Deps] add missing `npmignore` dev dep [`3226afa`](https://github.com/minimistjs/minimist/commit/3226afaf09e9d127ca369742437fe6e88f752d6b) + +## [v0.2.2](https://github.com/minimistjs/minimist/compare/v0.2.1...v0.2.2) - 2022-10-10 + +### Commits + +- [meta] add `auto-changelog` [`73923d2`](https://github.com/minimistjs/minimist/commit/73923d223553fca08b1ba77e3fbc2a492862ae4c) +- [actions] add reusable workflows [`d80727d`](https://github.com/minimistjs/minimist/commit/d80727df77bfa9e631044d7f16368d8f09242c91) +- [eslint] add eslint; rules to enable later are warnings [`48bc06a`](https://github.com/minimistjs/minimist/commit/48bc06a1b41f00e9cdf183db34f7a51ba70e98d4) +- [readme] rename and add badges [`5df0fe4`](https://github.com/minimistjs/minimist/commit/5df0fe49211bd09a3636f8686a7cb3012c3e98f0) +- [Dev Deps] switch from `covert` to `nyc` [`a48b128`](https://github.com/minimistjs/minimist/commit/a48b128fdb8d427dfb20a15273f83e38d97bef07) +- [Dev Deps] update `covert`, `tape`; remove unnecessary `tap` [`f0fb958`](https://github.com/minimistjs/minimist/commit/f0fb958e9a1fe980cdffc436a211b0bda58f621b) +- [meta] create FUNDING.yml; add `funding` in package.json [`3639e0c`](https://github.com/minimistjs/minimist/commit/3639e0c819359a366387e425ab6eabf4c78d3caa) +- [meta] use `npmignore` to autogenerate an npmignore file [`be2e038`](https://github.com/minimistjs/minimist/commit/be2e038c342d8333b32f0fde67a0026b79c8150e) +- Only apps should have lockfiles [`282b570`](https://github.com/minimistjs/minimist/commit/282b570e7489d01b03f2d6d3dabf79cd3e5f84cf) +- [meta] add `safe-publish-latest` [`4b927de`](https://github.com/minimistjs/minimist/commit/4b927de696d561c636b4f43bf49d4597cb36d6d6) +- [Tests] add `aud` in `posttest` [`b32d9bd`](https://github.com/minimistjs/minimist/commit/b32d9bd0ab340f4e9f8c3a97ff2a4424f25fab8c) +- [meta] update repo URLs [`f9fdfc0`](https://github.com/minimistjs/minimist/commit/f9fdfc032c54884d9a9996a390c63cd0719bbe1a) + +## [v0.2.1](https://github.com/minimistjs/minimist/compare/v0.2.0...v0.2.1) - 2020-03-12 + +## [v0.2.0](https://github.com/minimistjs/minimist/compare/v0.1.0...v0.2.0) - 2014-06-19 + +### Commits + +- support all-boolean mode [`450a97f`](https://github.com/minimistjs/minimist/commit/450a97f6e2bc85c7a4a13185c19a818d9a5ebe69) + +## [v0.1.0](https://github.com/minimistjs/minimist/compare/v0.0.10...v0.1.0) - 2014-05-12 + +### Commits + +- Provide a mechanism to segregate -- arguments [`ce4a1e6`](https://github.com/minimistjs/minimist/commit/ce4a1e63a7e8d5ab88d2a3768adefa6af98a445a) +- documented argv['--'] [`14db0e6`](https://github.com/minimistjs/minimist/commit/14db0e6dbc6d2b9e472adaa54dad7004b364634f) +- Adding a test-case for notFlags segregation [`715c1e3`](https://github.com/minimistjs/minimist/commit/715c1e3714be223f998f6c537af6b505f0236c16) + +## [v0.0.10](https://github.com/minimistjs/minimist/compare/v0.0.9...v0.0.10) - 2014-05-11 + +### Commits + +- dedicated boolean test [`46e448f`](https://github.com/minimistjs/minimist/commit/46e448f9f513cfeb2bcc8b688b9b47ba1e515c2b) +- dedicated num test [`9bf2d36`](https://github.com/minimistjs/minimist/commit/9bf2d36f1d3b8795be90b8f7de0a937f098aa394) +- aliased values treated as strings [`1ab743b`](https://github.com/minimistjs/minimist/commit/1ab743bad4484d69f1259bed42f9531de01119de) +- cover the case of already numbers, at 100% coverage [`b2bb044`](https://github.com/minimistjs/minimist/commit/b2bb04436599d77a2ce029e8e555e25b3aa55d13) +- another test for higher coverage [`3662624`](https://github.com/minimistjs/minimist/commit/3662624be976d5489d486a856849c048d13be903) + +## [v0.0.9](https://github.com/minimistjs/minimist/compare/v0.0.8...v0.0.9) - 2014-05-08 + +### Commits + +- Eliminate `longest` fn. [`824f642`](https://github.com/minimistjs/minimist/commit/824f642038d1b02ede68b6261d1d65163390929a) + +## [v0.0.8](https://github.com/minimistjs/minimist/compare/v0.0.7...v0.0.8) - 2014-02-20 + +### Commits + +- return '' if flag is string and empty [`fa63ed4`](https://github.com/minimistjs/minimist/commit/fa63ed4651a4ef4eefddce34188e0d98d745a263) +- handle joined single letters [`66c248f`](https://github.com/minimistjs/minimist/commit/66c248f0241d4d421d193b022e9e365f11178534) + +## [v0.0.7](https://github.com/minimistjs/minimist/compare/v0.0.6...v0.0.7) - 2014-02-08 + +### Commits + +- another swap of .test for .match [`d1da408`](https://github.com/minimistjs/minimist/commit/d1da40819acbe846d89a5c02721211e3c1260dde) + +## [v0.0.6](https://github.com/minimistjs/minimist/compare/v0.0.5...v0.0.6) - 2014-02-08 + +### Commits + +- use .test() instead of .match() to not crash on non-string values in the arguments array [`7e0d1ad`](https://github.com/minimistjs/minimist/commit/7e0d1add8c9e5b9b20a4d3d0f9a94d824c578da1) + +## [v0.0.5](https://github.com/minimistjs/minimist/compare/v0.0.4...v0.0.5) - 2013-09-18 + +### Commits + +- Improve '--' handling. [`b11822c`](https://github.com/minimistjs/minimist/commit/b11822c09cc9d2460f30384d12afc0b953c037a4) + +## [v0.0.4](https://github.com/minimistjs/minimist/compare/v0.0.3...v0.0.4) - 2013-09-17 + +## [v0.0.3](https://github.com/minimistjs/minimist/compare/v0.0.2...v0.0.3) - 2013-09-12 + +### Commits + +- failing test for single dash preceeding a double dash [`b465514`](https://github.com/minimistjs/minimist/commit/b465514b82c9ae28972d714facd951deb2ad762b) +- fix for the dot test [`6a095f1`](https://github.com/minimistjs/minimist/commit/6a095f1d364c8fab2d6753d2291a0649315d297a) + +## [v0.0.2](https://github.com/minimistjs/minimist/compare/v0.0.1...v0.0.2) - 2013-08-28 + +### Commits + +- allow dotted aliases & defaults [`321c33e`](https://github.com/minimistjs/minimist/commit/321c33e755485faaeb44eeb1c05d33b2e0a5a7c4) +- use a better version of ff [`e40f611`](https://github.com/minimistjs/minimist/commit/e40f61114cf7be6f7947f7b3eed345853a67dbbb) + +## [v0.0.1](https://github.com/minimistjs/minimist/compare/v0.0.0...v0.0.1) - 2013-06-25 + +### Commits + +- remove trailing commas [`6ff0fa0`](https://github.com/minimistjs/minimist/commit/6ff0fa055064f15dbe06d50b89d5173a6796e1db) + +## v0.0.0 - 2013-06-25 + +### Commits + +- half of the parse test ported [`3079326`](https://github.com/minimistjs/minimist/commit/307932601325087de6cf94188eb798ffc4f3088a) +- stripped down code and a passing test from optimist [`7cced88`](https://github.com/minimistjs/minimist/commit/7cced88d82e399d1a03ed23eb667f04d3f320d10) +- ported parse tests completely over [`9448754`](https://github.com/minimistjs/minimist/commit/944875452e0820df6830b1408c26a0f7d3e1db04) +- docs, package.json [`a5bf46a`](https://github.com/minimistjs/minimist/commit/a5bf46ac9bb3bd114a9c340276c62c1091e538d5) +- move more short tests into short.js [`503edb5`](https://github.com/minimistjs/minimist/commit/503edb5c41d89c0d40831ee517154fc13b0f18b9) +- default bool test was wrong, not the code [`1b9f5db`](https://github.com/minimistjs/minimist/commit/1b9f5db4741b49962846081b68518de824992097) +- passing long tests ripped out of parse.js [`7972c4a`](https://github.com/minimistjs/minimist/commit/7972c4aff1f4803079e1668006658e2a761a0428) +- badges [`84c0370`](https://github.com/minimistjs/minimist/commit/84c037063664d42878aace715fe6572ce01b6f3b) +- all the tests now ported, some failures [`64239ed`](https://github.com/minimistjs/minimist/commit/64239edfe92c711c4eb0da254fcdfad2a5fdb605) +- failing short test [`f8a5341`](https://github.com/minimistjs/minimist/commit/f8a534112dd1138d2fad722def56a848480c446f) +- fixed the numeric test [`6b034f3`](https://github.com/minimistjs/minimist/commit/6b034f37c79342c60083ed97fd222e16928aac51) diff --git a/node_modules/minimist/LICENSE b/node_modules/minimist/LICENSE new file mode 100644 index 0000000..ee27ba4 --- /dev/null +++ b/node_modules/minimist/LICENSE @@ -0,0 +1,18 @@ +This software is released under the MIT license: + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/minimist/README.md b/node_modules/minimist/README.md new file mode 100644 index 0000000..74da323 --- /dev/null +++ b/node_modules/minimist/README.md @@ -0,0 +1,121 @@ +# minimist [![Version Badge][npm-version-svg]][package-url] + +[![github actions][actions-image]][actions-url] +[![coverage][codecov-image]][codecov-url] +[![License][license-image]][license-url] +[![Downloads][downloads-image]][downloads-url] + +[![npm badge][npm-badge-png]][package-url] + +parse argument options + +This module is the guts of optimist's argument parser without all the +fanciful decoration. + +# example + +``` js +var argv = require('minimist')(process.argv.slice(2)); +console.log(argv); +``` + +``` +$ node example/parse.js -a beep -b boop +{ _: [], a: 'beep', b: 'boop' } +``` + +``` +$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz +{ + _: ['foo', 'bar', 'baz'], + x: 3, + y: 4, + n: 5, + a: true, + b: true, + c: true, + beep: 'boop' +} +``` + +# security + +Previous versions had a prototype pollution bug that could cause privilege +escalation in some circumstances when handling untrusted user input. + +Please use version 1.2.6 or later: + +* https://security.snyk.io/vuln/SNYK-JS-MINIMIST-2429795 (version <=1.2.5) +* https://snyk.io/vuln/SNYK-JS-MINIMIST-559764 (version <=1.2.3) + +# methods + +``` js +var parseArgs = require('minimist') +``` + +## var argv = parseArgs(args, opts={}) + +Return an argument object `argv` populated with the array arguments from `args`. + +`argv._` contains all the arguments that didn't have an option associated with +them. + +Numeric-looking arguments will be returned as numbers unless `opts.string` or +`opts.boolean` is set for that argument name. + +Any arguments after `'--'` will not be parsed and will end up in `argv._`. + +options can be: + +* `opts.string` - a string or array of strings argument names to always treat as +strings +* `opts.boolean` - a boolean, string or array of strings to always treat as +booleans. if `true` will treat all double hyphenated arguments without equal signs +as boolean (e.g. affects `--foo`, not `-f` or `--foo=bar`) +* `opts.alias` - an object mapping string names to strings or arrays of string +argument names to use as aliases +* `opts.default` - an object mapping string argument names to default values +* `opts.stopEarly` - when true, populate `argv._` with everything after the +first non-option +* `opts['--']` - when true, populate `argv._` with everything before the `--` +and `argv['--']` with everything after the `--`. Here's an example: + + ``` + > require('./')('one two three -- four five --six'.split(' '), { '--': true }) + { + _: ['one', 'two', 'three'], + '--': ['four', 'five', '--six'] + } + ``` + + Note that with `opts['--']` set, parsing for arguments still stops after the + `--`. + +* `opts.unknown` - a function which is invoked with a command line parameter not +defined in the `opts` configuration object. If the function returns `false`, the +unknown option is not added to `argv`. + +# install + +With [npm](https://npmjs.org) do: + +``` +npm install minimist +``` + +# license + +MIT + +[package-url]: https://npmjs.org/package/minimist +[npm-version-svg]: https://versionbadg.es/minimistjs/minimist.svg +[npm-badge-png]: https://nodei.co/npm/minimist.png?downloads=true&stars=true +[license-image]: https://img.shields.io/npm/l/minimist.svg +[license-url]: LICENSE +[downloads-image]: https://img.shields.io/npm/dm/minimist.svg +[downloads-url]: https://npm-stat.com/charts.html?package=minimist +[codecov-image]: https://codecov.io/gh/minimistjs/minimist/branch/main/graphs/badge.svg +[codecov-url]: https://app.codecov.io/gh/minimistjs/minimist/ +[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/minimistjs/minimist +[actions-url]: https://github.com/minimistjs/minimist/actions diff --git a/node_modules/minimist/example/parse.js b/node_modules/minimist/example/parse.js new file mode 100644 index 0000000..9d90ffb --- /dev/null +++ b/node_modules/minimist/example/parse.js @@ -0,0 +1,4 @@ +'use strict'; + +var argv = require('../')(process.argv.slice(2)); +console.log(argv); diff --git a/node_modules/minimist/index.js b/node_modules/minimist/index.js new file mode 100644 index 0000000..f020f39 --- /dev/null +++ b/node_modules/minimist/index.js @@ -0,0 +1,263 @@ +'use strict'; + +function hasKey(obj, keys) { + var o = obj; + keys.slice(0, -1).forEach(function (key) { + o = o[key] || {}; + }); + + var key = keys[keys.length - 1]; + return key in o; +} + +function isNumber(x) { + if (typeof x === 'number') { return true; } + if ((/^0x[0-9a-f]+$/i).test(x)) { return true; } + return (/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/).test(x); +} + +function isConstructorOrProto(obj, key) { + return (key === 'constructor' && typeof obj[key] === 'function') || key === '__proto__'; +} + +module.exports = function (args, opts) { + if (!opts) { opts = {}; } + + var flags = { + bools: {}, + strings: {}, + unknownFn: null, + }; + + if (typeof opts.unknown === 'function') { + flags.unknownFn = opts.unknown; + } + + if (typeof opts.boolean === 'boolean' && opts.boolean) { + flags.allBools = true; + } else { + [].concat(opts.boolean).filter(Boolean).forEach(function (key) { + flags.bools[key] = true; + }); + } + + var aliases = {}; + + function aliasIsBoolean(key) { + return aliases[key].some(function (x) { + return flags.bools[x]; + }); + } + + Object.keys(opts.alias || {}).forEach(function (key) { + aliases[key] = [].concat(opts.alias[key]); + aliases[key].forEach(function (x) { + aliases[x] = [key].concat(aliases[key].filter(function (y) { + return x !== y; + })); + }); + }); + + [].concat(opts.string).filter(Boolean).forEach(function (key) { + flags.strings[key] = true; + if (aliases[key]) { + [].concat(aliases[key]).forEach(function (k) { + flags.strings[k] = true; + }); + } + }); + + var defaults = opts.default || {}; + + var argv = { _: [] }; + + function argDefined(key, arg) { + return (flags.allBools && (/^--[^=]+$/).test(arg)) + || flags.strings[key] + || flags.bools[key] + || aliases[key]; + } + + function setKey(obj, keys, value) { + var o = obj; + for (var i = 0; i < keys.length - 1; i++) { + var key = keys[i]; + if (isConstructorOrProto(o, key)) { return; } + if (o[key] === undefined) { o[key] = {}; } + if ( + o[key] === Object.prototype + || o[key] === Number.prototype + || o[key] === String.prototype + ) { + o[key] = {}; + } + if (o[key] === Array.prototype) { o[key] = []; } + o = o[key]; + } + + var lastKey = keys[keys.length - 1]; + if (isConstructorOrProto(o, lastKey)) { return; } + if ( + o === Object.prototype + || o === Number.prototype + || o === String.prototype + ) { + o = {}; + } + if (o === Array.prototype) { o = []; } + if (o[lastKey] === undefined || flags.bools[lastKey] || typeof o[lastKey] === 'boolean') { + o[lastKey] = value; + } else if (Array.isArray(o[lastKey])) { + o[lastKey].push(value); + } else { + o[lastKey] = [o[lastKey], value]; + } + } + + function setArg(key, val, arg) { + if (arg && flags.unknownFn && !argDefined(key, arg)) { + if (flags.unknownFn(arg) === false) { return; } + } + + var value = !flags.strings[key] && isNumber(val) + ? Number(val) + : val; + setKey(argv, key.split('.'), value); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), value); + }); + } + + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] === undefined ? false : defaults[key]); + }); + + var notFlags = []; + + if (args.indexOf('--') !== -1) { + notFlags = args.slice(args.indexOf('--') + 1); + args = args.slice(0, args.indexOf('--')); + } + + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + var key; + var next; + + if ((/^--.+=/).test(arg)) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + var m = arg.match(/^--([^=]+)=([\s\S]*)$/); + key = m[1]; + var value = m[2]; + if (flags.bools[key]) { + value = value !== 'false'; + } + setArg(key, value, arg); + } else if ((/^--no-.+/).test(arg)) { + key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false, arg); + } else if ((/^--.+/).test(arg)) { + key = arg.match(/^--(.+)/)[1]; + next = args[i + 1]; + if ( + next !== undefined + && !(/^(-|--)[^-]/).test(next) + && !flags.bools[key] + && !flags.allBools + && (aliases[key] ? !aliasIsBoolean(key) : true) + ) { + setArg(key, next, arg); + i += 1; + } else if ((/^(true|false)$/).test(next)) { + setArg(key, next === 'true', arg); + i += 1; + } else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } else if ((/^-[^-]+/).test(arg)) { + var letters = arg.slice(1, -1).split(''); + + var broken = false; + for (var j = 0; j < letters.length; j++) { + next = arg.slice(j + 2); + + if (next === '-') { + setArg(letters[j], next, arg); + continue; + } + + if ((/[A-Za-z]/).test(letters[j]) && next[0] === '=') { + setArg(letters[j], next.slice(1), arg); + broken = true; + break; + } + + if ( + (/[A-Za-z]/).test(letters[j]) + && (/-?\d+(\.\d*)?(e-?\d+)?$/).test(next) + ) { + setArg(letters[j], next, arg); + broken = true; + break; + } + + if (letters[j + 1] && letters[j + 1].match(/\W/)) { + setArg(letters[j], arg.slice(j + 2), arg); + broken = true; + break; + } else { + setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg); + } + } + + key = arg.slice(-1)[0]; + if (!broken && key !== '-') { + if ( + args[i + 1] + && !(/^(-|--)[^-]/).test(args[i + 1]) + && !flags.bools[key] + && (aliases[key] ? !aliasIsBoolean(key) : true) + ) { + setArg(key, args[i + 1], arg); + i += 1; + } else if (args[i + 1] && (/^(true|false)$/).test(args[i + 1])) { + setArg(key, args[i + 1] === 'true', arg); + i += 1; + } else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + } else { + if (!flags.unknownFn || flags.unknownFn(arg) !== false) { + argv._.push(flags.strings._ || !isNumber(arg) ? arg : Number(arg)); + } + if (opts.stopEarly) { + argv._.push.apply(argv._, args.slice(i + 1)); + break; + } + } + } + + Object.keys(defaults).forEach(function (k) { + if (!hasKey(argv, k.split('.'))) { + setKey(argv, k.split('.'), defaults[k]); + + (aliases[k] || []).forEach(function (x) { + setKey(argv, x.split('.'), defaults[k]); + }); + } + }); + + if (opts['--']) { + argv['--'] = notFlags.slice(); + } else { + notFlags.forEach(function (k) { + argv._.push(k); + }); + } + + return argv; +}; diff --git a/node_modules/minimist/package.json b/node_modules/minimist/package.json new file mode 100644 index 0000000..c10a334 --- /dev/null +++ b/node_modules/minimist/package.json @@ -0,0 +1,75 @@ +{ + "name": "minimist", + "version": "1.2.8", + "description": "parse argument options", + "main": "index.js", + "devDependencies": { + "@ljharb/eslint-config": "^21.0.1", + "aud": "^2.0.2", + "auto-changelog": "^2.4.0", + "eslint": "=8.8.0", + "in-publish": "^2.0.1", + "npmignore": "^0.3.0", + "nyc": "^10.3.2", + "safe-publish-latest": "^2.0.0", + "tape": "^5.6.3" + }, + "scripts": { + "prepack": "npmignore --auto --commentLines=auto", + "prepublishOnly": "safe-publish-latest", + "prepublish": "not-in-publish || npm run prepublishOnly", + "lint": "eslint --ext=js,mjs .", + "pretest": "npm run lint", + "tests-only": "nyc tape 'test/**/*.js'", + "test": "npm run tests-only", + "posttest": "aud --production", + "version": "auto-changelog && git add CHANGELOG.md", + "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" + }, + "testling": { + "files": "test/*.js", + "browsers": [ + "ie/6..latest", + "ff/5", + "firefox/latest", + "chrome/10", + "chrome/latest", + "safari/5.1", + "safari/latest", + "opera/12" + ] + }, + "repository": { + "type": "git", + "url": "git://github.com/minimistjs/minimist.git" + }, + "homepage": "https://github.com/minimistjs/minimist", + "keywords": [ + "argv", + "getopt", + "parser", + "optimist" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + }, + "license": "MIT", + "auto-changelog": { + "output": "CHANGELOG.md", + "template": "keepachangelog", + "unreleased": false, + "commitLimit": false, + "backfillLimit": false, + "hideCredit": true + }, + "publishConfig": { + "ignore": [ + ".github/workflows" + ] + } +} diff --git a/node_modules/minimist/test/all_bool.js b/node_modules/minimist/test/all_bool.js new file mode 100644 index 0000000..befa0c9 --- /dev/null +++ b/node_modules/minimist/test/all_bool.js @@ -0,0 +1,34 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('flag boolean true (default all --args to boolean)', function (t) { + var argv = parse(['moo', '--honk', 'cow'], { + boolean: true, + }); + + t.deepEqual(argv, { + honk: true, + _: ['moo', 'cow'], + }); + + t.deepEqual(typeof argv.honk, 'boolean'); + t.end(); +}); + +test('flag boolean true only affects double hyphen arguments without equals signs', function (t) { + var argv = parse(['moo', '--honk', 'cow', '-p', '55', '--tacos=good'], { + boolean: true, + }); + + t.deepEqual(argv, { + honk: true, + tacos: 'good', + p: 55, + _: ['moo', 'cow'], + }); + + t.deepEqual(typeof argv.honk, 'boolean'); + t.end(); +}); diff --git a/node_modules/minimist/test/bool.js b/node_modules/minimist/test/bool.js new file mode 100644 index 0000000..e58d47e --- /dev/null +++ b/node_modules/minimist/test/bool.js @@ -0,0 +1,177 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('flag boolean default false', function (t) { + var argv = parse(['moo'], { + boolean: ['t', 'verbose'], + default: { verbose: false, t: false }, + }); + + t.deepEqual(argv, { + verbose: false, + t: false, + _: ['moo'], + }); + + t.deepEqual(typeof argv.verbose, 'boolean'); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); + +}); + +test('boolean groups', function (t) { + var argv = parse(['-x', '-z', 'one', 'two', 'three'], { + boolean: ['x', 'y', 'z'], + }); + + t.deepEqual(argv, { + x: true, + y: false, + z: true, + _: ['one', 'two', 'three'], + }); + + t.deepEqual(typeof argv.x, 'boolean'); + t.deepEqual(typeof argv.y, 'boolean'); + t.deepEqual(typeof argv.z, 'boolean'); + t.end(); +}); +test('boolean and alias with chainable api', function (t) { + var aliased = ['-h', 'derp']; + var regular = ['--herp', 'derp']; + var aliasedArgv = parse(aliased, { + boolean: 'herp', + alias: { h: 'herp' }, + }); + var propertyArgv = parse(regular, { + boolean: 'herp', + alias: { h: 'herp' }, + }); + var expected = { + herp: true, + h: true, + _: ['derp'], + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +test('boolean and alias with options hash', function (t) { + var aliased = ['-h', 'derp']; + var regular = ['--herp', 'derp']; + var opts = { + alias: { h: 'herp' }, + boolean: 'herp', + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var expected = { + herp: true, + h: true, + _: ['derp'], + }; + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +test('boolean and alias array with options hash', function (t) { + var aliased = ['-h', 'derp']; + var regular = ['--herp', 'derp']; + var alt = ['--harp', 'derp']; + var opts = { + alias: { h: ['herp', 'harp'] }, + boolean: 'h', + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var altPropertyArgv = parse(alt, opts); + var expected = { + harp: true, + herp: true, + h: true, + _: ['derp'], + }; + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.same(altPropertyArgv, expected); + t.end(); +}); + +test('boolean and alias using explicit true', function (t) { + var aliased = ['-h', 'true']; + var regular = ['--herp', 'true']; + var opts = { + alias: { h: 'herp' }, + boolean: 'h', + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var expected = { + herp: true, + h: true, + _: [], + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +// regression, see https://github.com/substack/node-optimist/issues/71 +test('boolean and --x=true', function (t) { + var parsed = parse(['--boool', '--other=true'], { + boolean: 'boool', + }); + + t.same(parsed.boool, true); + t.same(parsed.other, 'true'); + + parsed = parse(['--boool', '--other=false'], { + boolean: 'boool', + }); + + t.same(parsed.boool, true); + t.same(parsed.other, 'false'); + t.end(); +}); + +test('boolean --boool=true', function (t) { + var parsed = parse(['--boool=true'], { + default: { + boool: false, + }, + boolean: ['boool'], + }); + + t.same(parsed.boool, true); + t.end(); +}); + +test('boolean --boool=false', function (t) { + var parsed = parse(['--boool=false'], { + default: { + boool: true, + }, + boolean: ['boool'], + }); + + t.same(parsed.boool, false); + t.end(); +}); + +test('boolean using something similar to true', function (t) { + var opts = { boolean: 'h' }; + var result = parse(['-h', 'true.txt'], opts); + var expected = { + h: true, + _: ['true.txt'], + }; + + t.same(result, expected); + t.end(); +}); diff --git a/node_modules/minimist/test/dash.js b/node_modules/minimist/test/dash.js new file mode 100644 index 0000000..7078817 --- /dev/null +++ b/node_modules/minimist/test/dash.js @@ -0,0 +1,43 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('-', function (t) { + t.plan(6); + t.deepEqual(parse(['-n', '-']), { n: '-', _: [] }); + t.deepEqual(parse(['--nnn', '-']), { nnn: '-', _: [] }); + t.deepEqual(parse(['-']), { _: ['-'] }); + t.deepEqual(parse(['-f-']), { f: '-', _: [] }); + t.deepEqual( + parse(['-b', '-'], { boolean: 'b' }), + { b: true, _: ['-'] } + ); + t.deepEqual( + parse(['-s', '-'], { string: 's' }), + { s: '-', _: [] } + ); +}); + +test('-a -- b', function (t) { + t.plan(2); + t.deepEqual(parse(['-a', '--', 'b']), { a: true, _: ['b'] }); + t.deepEqual(parse(['--a', '--', 'b']), { a: true, _: ['b'] }); +}); + +test('move arguments after the -- into their own `--` array', function (t) { + t.plan(1); + t.deepEqual( + parse(['--name', 'John', 'before', '--', 'after'], { '--': true }), + { name: 'John', _: ['before'], '--': ['after'] } + ); +}); + +test('--- option value', function (t) { + // A multi-dash value is largely an edge case, but check the behaviour is as expected, + // and in particular the same for short option and long option (as made consistent in Jan 2023). + t.plan(2); + t.deepEqual(parse(['-n', '---']), { n: '---', _: [] }); + t.deepEqual(parse(['--nnn', '---']), { nnn: '---', _: [] }); +}); + diff --git a/node_modules/minimist/test/default_bool.js b/node_modules/minimist/test/default_bool.js new file mode 100644 index 0000000..4e9f625 --- /dev/null +++ b/node_modules/minimist/test/default_bool.js @@ -0,0 +1,37 @@ +'use strict'; + +var test = require('tape'); +var parse = require('../'); + +test('boolean default true', function (t) { + var argv = parse([], { + boolean: 'sometrue', + default: { sometrue: true }, + }); + t.equal(argv.sometrue, true); + t.end(); +}); + +test('boolean default false', function (t) { + var argv = parse([], { + boolean: 'somefalse', + default: { somefalse: false }, + }); + t.equal(argv.somefalse, false); + t.end(); +}); + +test('boolean default to null', function (t) { + var argv = parse([], { + boolean: 'maybe', + default: { maybe: null }, + }); + t.equal(argv.maybe, null); + + var argvLong = parse(['--maybe'], { + boolean: 'maybe', + default: { maybe: null }, + }); + t.equal(argvLong.maybe, true); + t.end(); +}); diff --git a/node_modules/minimist/test/dotted.js b/node_modules/minimist/test/dotted.js new file mode 100644 index 0000000..126ff03 --- /dev/null +++ b/node_modules/minimist/test/dotted.js @@ -0,0 +1,24 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('dotted alias', function (t) { + var argv = parse(['--a.b', '22'], { default: { 'a.b': 11 }, alias: { 'a.b': 'aa.bb' } }); + t.equal(argv.a.b, 22); + t.equal(argv.aa.bb, 22); + t.end(); +}); + +test('dotted default', function (t) { + var argv = parse('', { default: { 'a.b': 11 }, alias: { 'a.b': 'aa.bb' } }); + t.equal(argv.a.b, 11); + t.equal(argv.aa.bb, 11); + t.end(); +}); + +test('dotted default with no alias', function (t) { + var argv = parse('', { default: { 'a.b': 11 } }); + t.equal(argv.a.b, 11); + t.end(); +}); diff --git a/node_modules/minimist/test/kv_short.js b/node_modules/minimist/test/kv_short.js new file mode 100644 index 0000000..6d1b53a --- /dev/null +++ b/node_modules/minimist/test/kv_short.js @@ -0,0 +1,32 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('short -k=v', function (t) { + t.plan(1); + + var argv = parse(['-b=123']); + t.deepEqual(argv, { b: 123, _: [] }); +}); + +test('multi short -k=v', function (t) { + t.plan(1); + + var argv = parse(['-a=whatever', '-b=robots']); + t.deepEqual(argv, { a: 'whatever', b: 'robots', _: [] }); +}); + +test('short with embedded equals -k=a=b', function (t) { + t.plan(1); + + var argv = parse(['-k=a=b']); + t.deepEqual(argv, { k: 'a=b', _: [] }); +}); + +test('short with later equals like -ab=c', function (t) { + t.plan(1); + + var argv = parse(['-ab=c']); + t.deepEqual(argv, { a: true, b: 'c', _: [] }); +}); diff --git a/node_modules/minimist/test/long.js b/node_modules/minimist/test/long.js new file mode 100644 index 0000000..9fef51f --- /dev/null +++ b/node_modules/minimist/test/long.js @@ -0,0 +1,33 @@ +'use strict'; + +var test = require('tape'); +var parse = require('../'); + +test('long opts', function (t) { + t.deepEqual( + parse(['--bool']), + { bool: true, _: [] }, + 'long boolean' + ); + t.deepEqual( + parse(['--pow', 'xixxle']), + { pow: 'xixxle', _: [] }, + 'long capture sp' + ); + t.deepEqual( + parse(['--pow=xixxle']), + { pow: 'xixxle', _: [] }, + 'long capture eq' + ); + t.deepEqual( + parse(['--host', 'localhost', '--port', '555']), + { host: 'localhost', port: 555, _: [] }, + 'long captures sp' + ); + t.deepEqual( + parse(['--host=localhost', '--port=555']), + { host: 'localhost', port: 555, _: [] }, + 'long captures eq' + ); + t.end(); +}); diff --git a/node_modules/minimist/test/num.js b/node_modules/minimist/test/num.js new file mode 100644 index 0000000..074393e --- /dev/null +++ b/node_modules/minimist/test/num.js @@ -0,0 +1,38 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('nums', function (t) { + var argv = parse([ + '-x', '1234', + '-y', '5.67', + '-z', '1e7', + '-w', '10f', + '--hex', '0xdeadbeef', + '789', + ]); + t.deepEqual(argv, { + x: 1234, + y: 5.67, + z: 1e7, + w: '10f', + hex: 0xdeadbeef, + _: [789], + }); + t.deepEqual(typeof argv.x, 'number'); + t.deepEqual(typeof argv.y, 'number'); + t.deepEqual(typeof argv.z, 'number'); + t.deepEqual(typeof argv.w, 'string'); + t.deepEqual(typeof argv.hex, 'number'); + t.deepEqual(typeof argv._[0], 'number'); + t.end(); +}); + +test('already a number', function (t) { + var argv = parse(['-x', 1234, 789]); + t.deepEqual(argv, { x: 1234, _: [789] }); + t.deepEqual(typeof argv.x, 'number'); + t.deepEqual(typeof argv._[0], 'number'); + t.end(); +}); diff --git a/node_modules/minimist/test/parse.js b/node_modules/minimist/test/parse.js new file mode 100644 index 0000000..65d9d90 --- /dev/null +++ b/node_modules/minimist/test/parse.js @@ -0,0 +1,209 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('parse args', function (t) { + t.deepEqual( + parse(['--no-moo']), + { moo: false, _: [] }, + 'no' + ); + t.deepEqual( + parse(['-v', 'a', '-v', 'b', '-v', 'c']), + { v: ['a', 'b', 'c'], _: [] }, + 'multi' + ); + t.end(); +}); + +test('comprehensive', function (t) { + t.deepEqual( + parse([ + '--name=meowmers', 'bare', '-cats', 'woo', + '-h', 'awesome', '--multi=quux', + '--key', 'value', + '-b', '--bool', '--no-meep', '--multi=baz', + '--', '--not-a-flag', 'eek', + ]), + { + c: true, + a: true, + t: true, + s: 'woo', + h: 'awesome', + b: true, + bool: true, + key: 'value', + multi: ['quux', 'baz'], + meep: false, + name: 'meowmers', + _: ['bare', '--not-a-flag', 'eek'], + } + ); + t.end(); +}); + +test('flag boolean', function (t) { + var argv = parse(['-t', 'moo'], { boolean: 't' }); + t.deepEqual(argv, { t: true, _: ['moo'] }); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); +}); + +test('flag boolean value', function (t) { + var argv = parse(['--verbose', 'false', 'moo', '-t', 'true'], { + boolean: ['t', 'verbose'], + default: { verbose: true }, + }); + + t.deepEqual(argv, { + verbose: false, + t: true, + _: ['moo'], + }); + + t.deepEqual(typeof argv.verbose, 'boolean'); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); +}); + +test('newlines in params', function (t) { + var args = parse(['-s', 'X\nX']); + t.deepEqual(args, { _: [], s: 'X\nX' }); + + // reproduce in bash: + // VALUE="new + // line" + // node program.js --s="$VALUE" + args = parse(['--s=X\nX']); + t.deepEqual(args, { _: [], s: 'X\nX' }); + t.end(); +}); + +test('strings', function (t) { + var s = parse(['-s', '0001234'], { string: 's' }).s; + t.equal(s, '0001234'); + t.equal(typeof s, 'string'); + + var x = parse(['-x', '56'], { string: 'x' }).x; + t.equal(x, '56'); + t.equal(typeof x, 'string'); + t.end(); +}); + +test('stringArgs', function (t) { + var s = parse([' ', ' '], { string: '_' })._; + t.same(s.length, 2); + t.same(typeof s[0], 'string'); + t.same(s[0], ' '); + t.same(typeof s[1], 'string'); + t.same(s[1], ' '); + t.end(); +}); + +test('empty strings', function (t) { + var s = parse(['-s'], { string: 's' }).s; + t.equal(s, ''); + t.equal(typeof s, 'string'); + + var str = parse(['--str'], { string: 'str' }).str; + t.equal(str, ''); + t.equal(typeof str, 'string'); + + var letters = parse(['-art'], { + string: ['a', 't'], + }); + + t.equal(letters.a, ''); + t.equal(letters.r, true); + t.equal(letters.t, ''); + + t.end(); +}); + +test('string and alias', function (t) { + var x = parse(['--str', '000123'], { + string: 's', + alias: { s: 'str' }, + }); + + t.equal(x.str, '000123'); + t.equal(typeof x.str, 'string'); + t.equal(x.s, '000123'); + t.equal(typeof x.s, 'string'); + + var y = parse(['-s', '000123'], { + string: 'str', + alias: { str: 's' }, + }); + + t.equal(y.str, '000123'); + t.equal(typeof y.str, 'string'); + t.equal(y.s, '000123'); + t.equal(typeof y.s, 'string'); + + var z = parse(['-s123'], { + alias: { str: ['s', 'S'] }, + string: ['str'], + }); + + t.deepEqual( + z, + { _: [], s: '123', S: '123', str: '123' }, + 'opt.string works with multiple aliases' + ); + t.end(); +}); + +test('slashBreak', function (t) { + t.same( + parse(['-I/foo/bar/baz']), + { I: '/foo/bar/baz', _: [] } + ); + t.same( + parse(['-xyz/foo/bar/baz']), + { x: true, y: true, z: '/foo/bar/baz', _: [] } + ); + t.end(); +}); + +test('alias', function (t) { + var argv = parse(['-f', '11', '--zoom', '55'], { + alias: { z: 'zoom' }, + }); + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.f, 11); + t.end(); +}); + +test('multiAlias', function (t) { + var argv = parse(['-f', '11', '--zoom', '55'], { + alias: { z: ['zm', 'zoom'] }, + }); + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.z, argv.zm); + t.equal(argv.f, 11); + t.end(); +}); + +test('nested dotted objects', function (t) { + var argv = parse([ + '--foo.bar', '3', '--foo.baz', '4', + '--foo.quux.quibble', '5', '--foo.quux.o_O', + '--beep.boop', + ]); + + t.same(argv.foo, { + bar: 3, + baz: 4, + quux: { + quibble: 5, + o_O: true, + }, + }); + t.same(argv.beep, { boop: true }); + t.end(); +}); diff --git a/node_modules/minimist/test/parse_modified.js b/node_modules/minimist/test/parse_modified.js new file mode 100644 index 0000000..32965d1 --- /dev/null +++ b/node_modules/minimist/test/parse_modified.js @@ -0,0 +1,11 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('parse with modifier functions', function (t) { + t.plan(1); + + var argv = parse(['-b', '123'], { boolean: 'b' }); + t.deepEqual(argv, { b: true, _: [123] }); +}); diff --git a/node_modules/minimist/test/proto.js b/node_modules/minimist/test/proto.js new file mode 100644 index 0000000..6e629dd --- /dev/null +++ b/node_modules/minimist/test/proto.js @@ -0,0 +1,64 @@ +'use strict'; + +/* eslint no-proto: 0 */ + +var parse = require('../'); +var test = require('tape'); + +test('proto pollution', function (t) { + var argv = parse(['--__proto__.x', '123']); + t.equal({}.x, undefined); + t.equal(argv.__proto__.x, undefined); + t.equal(argv.x, undefined); + t.end(); +}); + +test('proto pollution (array)', function (t) { + var argv = parse(['--x', '4', '--x', '5', '--x.__proto__.z', '789']); + t.equal({}.z, undefined); + t.deepEqual(argv.x, [4, 5]); + t.equal(argv.x.z, undefined); + t.equal(argv.x.__proto__.z, undefined); + t.end(); +}); + +test('proto pollution (number)', function (t) { + var argv = parse(['--x', '5', '--x.__proto__.z', '100']); + t.equal({}.z, undefined); + t.equal((4).z, undefined); + t.equal(argv.x, 5); + t.equal(argv.x.z, undefined); + t.end(); +}); + +test('proto pollution (string)', function (t) { + var argv = parse(['--x', 'abc', '--x.__proto__.z', 'def']); + t.equal({}.z, undefined); + t.equal('...'.z, undefined); + t.equal(argv.x, 'abc'); + t.equal(argv.x.z, undefined); + t.end(); +}); + +test('proto pollution (constructor)', function (t) { + var argv = parse(['--constructor.prototype.y', '123']); + t.equal({}.y, undefined); + t.equal(argv.y, undefined); + t.end(); +}); + +test('proto pollution (constructor function)', function (t) { + var argv = parse(['--_.concat.constructor.prototype.y', '123']); + function fnToBeTested() {} + t.equal(fnToBeTested.y, undefined); + t.equal(argv.y, undefined); + t.end(); +}); + +// powered by snyk - https://github.com/backstage/backstage/issues/10343 +test('proto pollution (constructor function) snyk', function (t) { + var argv = parse('--_.constructor.constructor.prototype.foo bar'.split(' ')); + t.equal(function () {}.foo, undefined); + t.equal(argv.y, undefined); + t.end(); +}); diff --git a/node_modules/minimist/test/short.js b/node_modules/minimist/test/short.js new file mode 100644 index 0000000..4a7b843 --- /dev/null +++ b/node_modules/minimist/test/short.js @@ -0,0 +1,69 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('numeric short args', function (t) { + t.plan(2); + t.deepEqual(parse(['-n123']), { n: 123, _: [] }); + t.deepEqual( + parse(['-123', '456']), + { 1: true, 2: true, 3: 456, _: [] } + ); +}); + +test('short', function (t) { + t.deepEqual( + parse(['-b']), + { b: true, _: [] }, + 'short boolean' + ); + t.deepEqual( + parse(['foo', 'bar', 'baz']), + { _: ['foo', 'bar', 'baz'] }, + 'bare' + ); + t.deepEqual( + parse(['-cats']), + { c: true, a: true, t: true, s: true, _: [] }, + 'group' + ); + t.deepEqual( + parse(['-cats', 'meow']), + { c: true, a: true, t: true, s: 'meow', _: [] }, + 'short group next' + ); + t.deepEqual( + parse(['-h', 'localhost']), + { h: 'localhost', _: [] }, + 'short capture' + ); + t.deepEqual( + parse(['-h', 'localhost', '-p', '555']), + { h: 'localhost', p: 555, _: [] }, + 'short captures' + ); + t.end(); +}); + +test('mixed short bool and capture', function (t) { + t.same( + parse(['-h', 'localhost', '-fp', '555', 'script.js']), + { + f: true, p: 555, h: 'localhost', + _: ['script.js'], + } + ); + t.end(); +}); + +test('short and long', function (t) { + t.deepEqual( + parse(['-h', 'localhost', '-fp', '555', 'script.js']), + { + f: true, p: 555, h: 'localhost', + _: ['script.js'], + } + ); + t.end(); +}); diff --git a/node_modules/minimist/test/stop_early.js b/node_modules/minimist/test/stop_early.js new file mode 100644 index 0000000..52a6a91 --- /dev/null +++ b/node_modules/minimist/test/stop_early.js @@ -0,0 +1,17 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('stops parsing on the first non-option when stopEarly is set', function (t) { + var argv = parse(['--aaa', 'bbb', 'ccc', '--ddd'], { + stopEarly: true, + }); + + t.deepEqual(argv, { + aaa: 'bbb', + _: ['ccc', '--ddd'], + }); + + t.end(); +}); diff --git a/node_modules/minimist/test/unknown.js b/node_modules/minimist/test/unknown.js new file mode 100644 index 0000000..4f2e0ca --- /dev/null +++ b/node_modules/minimist/test/unknown.js @@ -0,0 +1,104 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('boolean and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = ['-h', 'true', '--derp', 'true']; + var regular = ['--herp', 'true', '-d', 'true']; + var opts = { + alias: { h: 'herp' }, + boolean: 'h', + unknown: unknownFn, + }; + parse(aliased, opts); + parse(regular, opts); + + t.same(unknown, ['--derp', '-d']); + t.end(); +}); + +test('flag boolean true any double hyphen argument is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var argv = parse(['--honk', '--tacos=good', 'cow', '-p', '55'], { + boolean: true, + unknown: unknownFn, + }); + t.same(unknown, ['--tacos=good', 'cow', '-p']); + t.same(argv, { + honk: true, + _: [], + }); + t.end(); +}); + +test('string and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = ['-h', 'hello', '--derp', 'goodbye']; + var regular = ['--herp', 'hello', '-d', 'moon']; + var opts = { + alias: { h: 'herp' }, + string: 'h', + unknown: unknownFn, + }; + parse(aliased, opts); + parse(regular, opts); + + t.same(unknown, ['--derp', '-d']); + t.end(); +}); + +test('default and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = ['-h', 'hello']; + var regular = ['--herp', 'hello']; + var opts = { + default: { h: 'bar' }, + alias: { h: 'herp' }, + unknown: unknownFn, + }; + parse(aliased, opts); + parse(regular, opts); + + t.same(unknown, []); + t.end(); + unknownFn(); // exercise fn for 100% coverage +}); + +test('value following -- is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = ['--bad', '--', 'good', 'arg']; + var opts = { + '--': true, + unknown: unknownFn, + }; + var argv = parse(aliased, opts); + + t.same(unknown, ['--bad']); + t.same(argv, { + '--': ['good', 'arg'], + _: [], + }); + t.end(); +}); diff --git a/node_modules/minimist/test/whitespace.js b/node_modules/minimist/test/whitespace.js new file mode 100644 index 0000000..4fdaf1d --- /dev/null +++ b/node_modules/minimist/test/whitespace.js @@ -0,0 +1,10 @@ +'use strict'; + +var parse = require('../'); +var test = require('tape'); + +test('whitespace should be whitespace', function (t) { + t.plan(1); + var x = parse(['-x', '\t']).x; + t.equal(x, '\t'); +}); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..3f42253 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,75 @@ +{ + "name": "edam-interview-test", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "edam-interview-test", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "csv-parser": "^3.0.0", + "csv-writer": "^1.6.0", + "fs": "^0.0.1-security" + } + }, + "node_modules/csv-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.0.0.tgz", + "integrity": "sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "csv-parser": "bin/csv-parser" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/csv-writer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/csv-writer/-/csv-writer-1.6.0.tgz", + "integrity": "sha512-NOx7YDFWEsM/fTRAJjRpPp8t+MKRVvniAg9wQlUKx20MFrPs73WLJhFf5iteqrxNYnsy924K3Iroh3yNHeYd2g==" + }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + } + }, + "dependencies": { + "csv-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.0.0.tgz", + "integrity": "sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ==", + "requires": { + "minimist": "^1.2.0" + } + }, + "csv-writer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/csv-writer/-/csv-writer-1.6.0.tgz", + "integrity": "sha512-NOx7YDFWEsM/fTRAJjRpPp8t+MKRVvniAg9wQlUKx20MFrPs73WLJhFf5iteqrxNYnsy924K3Iroh3yNHeYd2g==" + }, + "fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + } + } +} diff --git a/package.json b/package.json index d632128..f113daf 100644 --- a/package.json +++ b/package.json @@ -15,5 +15,10 @@ "bugs": { "url": "https://github.com/ffelizp/interview-test/issues" }, - "homepage": "https://github.com/ffelizp/interview-test#readme" + "homepage": "https://github.com/ffelizp/interview-test#readme", + "dependencies": { + "csv-parser": "^3.0.0", + "csv-writer": "^1.6.0", + "fs": "^0.0.1-security" + } } From fadb6154aeb6b23b6421356329ca35c3f80e8605 Mon Sep 17 00:00:00 2001 From: ffelizp Date: Thu, 19 Oct 2023 11:01:21 -0400 Subject: [PATCH 3/7] Moving Files - Input Files into Data Directory --- customers.csv => data/customers.csv | 0 orders.csv => data/orders.csv | 0 products.csv => data/products.csv | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename customers.csv => data/customers.csv (100%) rename orders.csv => data/orders.csv (100%) rename products.csv => data/products.csv (100%) diff --git a/customers.csv b/data/customers.csv similarity index 100% rename from customers.csv rename to data/customers.csv diff --git a/orders.csv b/data/orders.csv similarity index 100% rename from orders.csv rename to data/orders.csv diff --git a/products.csv b/data/products.csv similarity index 100% rename from products.csv rename to data/products.csv From 69d66d87cf794cbf0a2344b632067abbad531563 Mon Sep 17 00:00:00 2001 From: ffelizp Date: Thu, 19 Oct 2023 11:10:29 -0400 Subject: [PATCH 4/7] Utils Creation - Functions to Handle the Utils --- utils/csvUtils.js | 32 ++++++++++++++++++++++++++++++++ utils/filePaths.js | 13 +++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 utils/csvUtils.js create mode 100644 utils/filePaths.js diff --git a/utils/csvUtils.js b/utils/csvUtils.js new file mode 100644 index 0000000..f4f0745 --- /dev/null +++ b/utils/csvUtils.js @@ -0,0 +1,32 @@ +const fs = require('fs'); +const csv = require('csv-parser'); +const { createObjectCsvWriter } = require('csv-writer'); + +// Create Async Function readCsv +async function readCsv(filePath) { + return new Promise((resolve, reject) => { + const results = []; + + fs.createReadStream(filePath) + .pipe(csv()) + .on('data', (data) => results.push(data)) + .on('end', () => resolve(results)) + .on('error', (error) => reject(error)); + }); +} + +// Create Async Function writeCsv +async function writeCsv(filePath, data, header) { + const csvWriter = createObjectCsvWriter({ + path: filePath, + header: header + }); + + await csvWriter.writeRecords(data); +} + +// Export readCsv and writeCsv +module.exports = { + readCsv, + writeCsv +}; diff --git a/utils/filePaths.js b/utils/filePaths.js new file mode 100644 index 0000000..2316f30 --- /dev/null +++ b/utils/filePaths.js @@ -0,0 +1,13 @@ +const path = require('path'); + +// Input Files +const customersFilePath = path.join(__dirname, '../data/customers.csv'); +const productsFilePath = path.join(__dirname, '../data/products.csv'); +const ordersFilePath = path.join(__dirname, '../data/orders.csv'); + +// Export Files +module.exports = { + customersFilePath, + productsFilePath, + ordersFilePath, +}; \ No newline at end of file From 97e24faf4c2c97369debae7defe46d97bf3a75ac Mon Sep 17 00:00:00 2001 From: ffelizp Date: Thu, 19 Oct 2023 11:35:37 -0400 Subject: [PATCH 5/7] Task1 - Calculate Order Total Costs --- data/order_prices.csv | 51 +++++++++++++++++++++++++++++++++++++++++++ package.json | 3 ++- scripts/task1.js | 45 ++++++++++++++++++++++++++++++++++++++ utils/filePaths.js | 6 ++++- 4 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 data/order_prices.csv create mode 100644 scripts/task1.js diff --git a/data/order_prices.csv b/data/order_prices.csv new file mode 100644 index 0000000..866b684 --- /dev/null +++ b/data/order_prices.csv @@ -0,0 +1,51 @@ +id,euros +0,18.943120182823662 +1,61.42542135303493 +2,23.145479220995195 +3,34.399455367824324 +4,45.54089635777854 +5,15.356455867079758 +6,73.09493147116578 +7,25.221717724883998 +8,18.865688649668115 +9,37.19065233220561 +10,54.635600426844064 +11,34.59258967318633 +12,22.810544398180582 +13,39.20812389251662 +14,32.31761482321626 +15,40.34169368202541 +16,51.168288843787415 +17,65.34702049159344 +18,28.202881379295736 +19,52.64239549683006 +20,9.806494914226443 +21,12.710227035482633 +22,51.36702518986868 +23,20.870504371025124 +24,54.641202467563325 +25,43.672279113154886 +26,64.52788982037238 +27,69.26444199447735 +28,16.925648622512657 +29,2.9037321212561906 +30,33.6581629396633 +31,60.777999492171055 +32,38.27994213203973 +33,5.8848957756679265 +34,36.668828177075135 +35,29.143316863442514 +36,10.435252185512562 +37,46.06896548595517 +38,16.296891351226538 +39,18.295698321959794 +40,23.145479220995195 +41,71.48064990086962 +42,73.17796504504058 +43,50.91273763436682 +44,38.5374454216988 +45,63.28526894160777 +46,51.73605361605959 +47,9.394128558256284 +48,46.91370696265276 +49,6.490396437000094 diff --git a/package.json b/package.json index f113daf..98445f9 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Choose whatever language you're most comfortable with to solve these problems.", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "task1": "node scripts/task1.js" }, "repository": { "type": "git", diff --git a/scripts/task1.js b/scripts/task1.js new file mode 100644 index 0000000..0f96c74 --- /dev/null +++ b/scripts/task1.js @@ -0,0 +1,45 @@ +const {readCsv, writeCsv} = require('../utils/csvUtils'); +const {customersFilePath, productsFilePath, ordersFilePath, orderPricesFilePath} = require('../utils/filePaths'); + +// Create Task1 Function +async function task1() { + // Handle Errors by using try and catch + try { + // Read CSV Files + const products = await readCsv(productsFilePath); + const orders = await readCsv(ordersFilePath); + + // Calculate Order Total Prices + const orderPrices = orders.map(order => { + // Get Product IDs + const productsIds = order.products.split(' '); + // Calculate Total Cost + const totalCost = productsIds.reduce((total, productId) => { + const product = products.find(product => product.id === productId); + return product ? total + parseFloat(product.cost) : total; + }, 0); + + // Return Order Price + return { + id: order.id, + euros: totalCost + }; + }); + + // Write Order Prices to CSV File + await writeCsv(orderPricesFilePath, orderPrices, [ + {id: 'id', title: 'id'}, + {id: 'euros', title: 'euros'}, + ]); + + // Console Log Success Message + console.log('Task1 Completed Successfully!'); + + } catch (error) { + // Console Log error + console.error('An Error has Occurred: ', error); + } +} + +// Execute Task1 Function +task1(); \ No newline at end of file diff --git a/utils/filePaths.js b/utils/filePaths.js index 2316f30..35a548c 100644 --- a/utils/filePaths.js +++ b/utils/filePaths.js @@ -5,9 +5,13 @@ const customersFilePath = path.join(__dirname, '../data/customers.csv'); const productsFilePath = path.join(__dirname, '../data/products.csv'); const ordersFilePath = path.join(__dirname, '../data/orders.csv'); +// Output Files +const orderPricesFilePath = path.join(__dirname, '../data/order_prices.csv'); + // Export Files module.exports = { customersFilePath, productsFilePath, ordersFilePath, -}; \ No newline at end of file + orderPricesFilePath, +}; From 0b5cb0a988323c4fa2f70efe0f27ac4b17510336 Mon Sep 17 00:00:00 2001 From: ffelizp Date: Thu, 19 Oct 2023 11:51:20 -0400 Subject: [PATCH 6/7] Task2 - Customer who have purchased Products --- data/product_customers.csv | 7 +++++ package.json | 3 +- scripts/task2.js | 59 ++++++++++++++++++++++++++++++++++++++ utils/filePaths.js | 2 ++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 data/product_customers.csv create mode 100644 scripts/task2.js diff --git a/data/product_customers.csv b/data/product_customers.csv new file mode 100644 index 0000000..d69c02d --- /dev/null +++ b/data/product_customers.csv @@ -0,0 +1,7 @@ +id,customer_ids +0,0 22 20 28 40 32 5 45 37 38 6 44 50 24 54 59 15 21 34 19 47 48 46 10 17 29 +1,0 22 40 32 45 38 51 6 44 34 3 50 24 15 5 41 47 46 35 29 10 17 9 58 +2,22 57 20 40 5 45 37 51 6 44 54 8 15 21 41 48 46 29 24 17 9 +3,22 20 28 32 5 38 51 34 50 24 54 21 41 47 46 44 29 17 9 +4,22 57 20 28 51 24 59 36 8 15 21 5 34 19 41 44 32 35 10 17 9 +5,22 57 28 32 5 37 38 6 44 34 3 50 24 54 59 15 25 21 45 19 41 47 10 17 9 29 diff --git a/package.json b/package.json index 98445f9..3b19315 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "task1": "node scripts/task1.js" + "task1": "node scripts/task1.js", + "task2": "node scripts/task2.js" }, "repository": { "type": "git", diff --git a/scripts/task2.js b/scripts/task2.js new file mode 100644 index 0000000..06d2c0e --- /dev/null +++ b/scripts/task2.js @@ -0,0 +1,59 @@ +const {readCsv, writeCsv} = require('../utils/csvUtils'); +const {ordersFilePath, productsFilePath, productCustomersFilePath} = require('../utils/filePaths'); + +// Create Task2 Function +async function task2() { + // Handle Errors by using try and catch + try { + // Read CSV Files + const products = await readCsv(productsFilePath); + const orders = await readCsv(ordersFilePath); + + // Calculate Product Customers + const productCustomers = {}; + + // Process Orders to Determine witch customers bought witch products + orders.forEach((order) => { + // Get Product IDs + const productsIds = order.products.split(' '); + + // Foreach Product ID + productsIds.forEach(productId => { + // Initialize Product Customers + if (!productCustomers[productId]) { + productCustomers[productId] = []; + } + + // If Customer ID is not in Product Customers - Add It + if (!productCustomers[productId].includes(order.customer)) { + productCustomers[productId].push(order.customer); + } + }); + }); + + + // Prepare Data for CSV File - Foreach Product, Get the Customer Who Purchased it + const productCustomersData = products.map(product => { + return { + id: product.id, + customer_ids: productCustomers[product.id] ? productCustomers[product.id].join(' ') : '' + }; + }); + + // Write Order Prices to CSV File + await writeCsv(productCustomersFilePath, productCustomersData, [ + {id: 'id', title: 'id'}, + {id: 'customer_ids', title: 'customer_ids'}, + ]); + + // Console Log Success Message + console.log('Task2 Completed Successfully!'); + + } catch (error) { + // Console Log error + console.error('An Error has Occurred: ', error); + } +} + +// Execute Task2 Function +task2(); \ No newline at end of file diff --git a/utils/filePaths.js b/utils/filePaths.js index 35a548c..fbf0381 100644 --- a/utils/filePaths.js +++ b/utils/filePaths.js @@ -7,6 +7,7 @@ const ordersFilePath = path.join(__dirname, '../data/orders.csv'); // Output Files const orderPricesFilePath = path.join(__dirname, '../data/order_prices.csv'); +const productCustomersFilePath = path.join(__dirname, '../data/product_customers.csv'); // Export Files module.exports = { @@ -14,4 +15,5 @@ module.exports = { productsFilePath, ordersFilePath, orderPricesFilePath, + productCustomersFilePath, }; From b8743e6bb2ee61e4c057229f972efadeecdbcc8f Mon Sep 17 00:00:00 2001 From: ffelizp Date: Thu, 19 Oct 2023 12:04:01 -0400 Subject: [PATCH 7/7] Task3 - Customer Ranking According to Total Purchased --- data/customer_ranking.csv | 61 ++++++++++++++++++++++++++++++++++++ package.json | 3 +- scripts/task3.js | 66 +++++++++++++++++++++++++++++++++++++++ utils/filePaths.js | 2 ++ 4 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 data/customer_ranking.csv create mode 100644 scripts/task3.js diff --git a/data/customer_ranking.csv b/data/customer_ranking.csv new file mode 100644 index 0000000..7c8437d --- /dev/null +++ b/data/customer_ranking.csv @@ -0,0 +1,61 @@ +id,firstname,lastname,total_euros +34,Samuel,Lavoisier,145.2543359308485 +44,Mary,Fermi,138.41062693960708 +24,Ringo,Maxwell,136.82767039246306 +22,Paul,Lavoisier,124.71069029464269 +32,Samuel,Fermi,119.16389695712095 +5,John,Pasteur,99.14373610351267 +10,James,Lavoisier,73.17796504504058 +29,Ringo,Pasteur,70.03175193801938 +38,Sam,Fermi,65.07085261235663 +41,Sam,Pasteur,60.777999492171055 +21,Paul,Feynman,54.641202467563325 +15,Peter,Feynman,54.27075731112487 +59,Jane,Pasteur,52.64239549683006 +50,Sarah,Fermi,51.168288843787415 +17,Peter,Pasteur,50.91273763436682 +28,Ringo,Lavoisier,45.54089635777854 +3,John,Feynman,40.34169368202541 +9,James,Feynman,38.5374454216988 +47,Mary,Pasteur,38.27994213203973 +37,Sam,Heisenberg,37.19065233220561 +46,Mary,Lavoisier,36.668828177075135 +45,Mary,Feynman,35.79133727218077 +51,Sarah,Feynman,34.59258967318633 +20,Paul,Fermi,34.399455367824324 +19,Paul,Heisenberg,33.6581629396633 +54,Jane,Maxwell,28.202881379295736 +57,Jane,Feynman,23.145479220995195 +6,James,Maxwell,22.810544398180582 +25,Ringo,Heisenberg,20.870504371025124 +0,John,Maxwell,18.943120182823662 +35,Samuel,Pasteur,16.296891351226538 +40,Sam,Lavoisier,15.356455867079758 +8,James,Fermi,12.710227035482633 +36,Sam,Maxwell,9.806494914226443 +58,Jane,Lavoisier,6.490396437000094 +48,Sarah,Maxwell,5.8848957756679265 +1,John,Heisenberg,0 +2,John,Fermi,0 +4,John,Lavoisier,0 +7,James,Heisenberg,0 +11,James,Pasteur,0 +12,Peter,Maxwell,0 +13,Peter,Heisenberg,0 +14,Peter,Fermi,0 +16,Peter,Lavoisier,0 +18,Paul,Maxwell,0 +23,Paul,Pasteur,0 +26,Ringo,Fermi,0 +27,Ringo,Feynman,0 +30,Samuel,Maxwell,0 +31,Samuel,Heisenberg,0 +33,Samuel,Feynman,0 +39,Sam,Feynman,0 +42,Mary,Maxwell,0 +43,Mary,Heisenberg,0 +49,Sarah,Heisenberg,0 +52,Sarah,Lavoisier,0 +53,Sarah,Pasteur,0 +55,Jane,Heisenberg,0 +56,Jane,Fermi,0 diff --git a/package.json b/package.json index 3b19315..dfd4e53 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "task1": "node scripts/task1.js", - "task2": "node scripts/task2.js" + "task2": "node scripts/task2.js", + "task3": "node scripts/task3.js" }, "repository": { "type": "git", diff --git a/scripts/task3.js b/scripts/task3.js new file mode 100644 index 0000000..1ee592e --- /dev/null +++ b/scripts/task3.js @@ -0,0 +1,66 @@ +const {readCsv, writeCsv} = require('../utils/csvUtils'); +const {customersFilePath, ordersFilePath, productsFilePath, customerRankingFilePath} = require('../utils/filePaths'); + +// Create Task3 Function +async function task3() { + // Handle Errors by using try and catch + try { + // Read CSV Files + const customers = await readCsv(customersFilePath); + const products = await readCsv(productsFilePath); + const orders = await readCsv(ordersFilePath); + + // Calculate the total euros spent by each customer + const customerTotalEuros = {}; + + // Foreach Order + orders.forEach((order) => { + // Get Product IDs + const productsIds = order.products.split(' '); + // Calculate Total Cost + const totalCost = productsIds.reduce((total, productId) => { + const product = products.find(product => product.id === productId); + return product ? total + parseFloat(product.cost) : total; + }, 0); + + // Initialize Customer Total Euros + if (!customerTotalEuros[order.customer]) { + customerTotalEuros[order.customer] = 0; + } + + // Add Total Cost to customer Total Euros + customerTotalEuros[order.customer] += totalCost; + }); + + // Prepare Data for CSV File - Foreach Customer, Get the Total Euros Spent + const customerRankingData = customers.map(customer => { + return { + id: customer.id, + firstname: customer.firstname, + lastname: customer.lastname, + total_euros: customerTotalEuros[customer.id] ? customerTotalEuros[customer.id] : 0 + }; + }); + + // Sort The data by Total Euros Spent in descending order + customerRankingData.sort((a, b) => parseFloat(b.total_euros) - parseFloat(a.total_euros)); + + // Write Order Prices to CSV File + await writeCsv(customerRankingFilePath, customerRankingData, [ + {id: 'id', title: 'id'}, + {id: 'firstname', title: 'firstname'}, + {id: 'lastname', title: 'lastname'}, + {id: 'total_euros', title: 'total_euros'}, + ]); + + // Console Log Success Message + console.log('Task3 Completed Successfully!'); + + } catch (error) { + // Console Log error + console.error('An Error has Occurred: ', error); + } +} + +// Execute Task3 Function +task3(); \ No newline at end of file diff --git a/utils/filePaths.js b/utils/filePaths.js index fbf0381..85d86ef 100644 --- a/utils/filePaths.js +++ b/utils/filePaths.js @@ -8,6 +8,7 @@ const ordersFilePath = path.join(__dirname, '../data/orders.csv'); // Output Files const orderPricesFilePath = path.join(__dirname, '../data/order_prices.csv'); const productCustomersFilePath = path.join(__dirname, '../data/product_customers.csv'); +const customerRankingFilePath = path.join(__dirname, '../data/customer_ranking.csv'); // Export Files module.exports = { @@ -16,4 +17,5 @@ module.exports = { ordersFilePath, orderPricesFilePath, productCustomersFilePath, + customerRankingFilePath, };