├── .commitlintrc.json
├── .eslintignore
├── .eslintrc.js
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── pull_request_template.md
└── workflows
│ └── test.yml
├── .gitignore
├── .huskyrc
├── .npmrc
├── .nvmrc
├── .prettierrc
├── .run
├── Run Examples.run.xml
├── Serve Docs.run.xml
└── jest.config.js.run.xml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── contributing.md
├── documentation
├── .gitignore
├── CHANGELOG.md
├── README.md
├── blog
│ └── 2020-03-11-new-docs.md
├── docs
│ ├── formatting
│ │ ├── examples.mdx
│ │ ├── getting-started.mdx
│ │ ├── methods.mdx
│ │ ├── options.md
│ │ └── row-types.md
│ ├── introduction
│ │ ├── example.mdx
│ │ ├── getting-started.md
│ │ └── install.md
│ ├── migration-guides
│ │ └── v2.x-to-v3.x.md
│ └── parsing
│ │ ├── benchmark.md
│ │ ├── events.md
│ │ ├── examples.mdx
│ │ ├── getting-started.mdx
│ │ ├── methods.mdx
│ │ └── options.md
├── docusaurus.config.js
├── package.json
├── sidebars.js
├── src
│ ├── css
│ │ └── custom.css
│ └── pages
│ │ ├── index.js
│ │ └── styles.module.css
└── static
│ └── img
│ ├── favicon.ico
│ ├── format_parse.svg
│ ├── logo.svg
│ ├── nodejs_icon.svg
│ └── ts_logo.png
├── examples
├── benchmark
│ ├── .eslintrc.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── assets
│ │ ├── 1000.nonquoted.csv
│ │ ├── 1000.quoted.csv
│ │ ├── 10000.nonquoted.csv
│ │ ├── 10000.quoted.csv
│ │ ├── 100000.nonquoted.csv
│ │ ├── 100000.quoted.csv
│ │ ├── 20000.nonquoted.csv
│ │ ├── 20000.quoted.csv
│ │ ├── 50000.nonquoted.csv
│ │ └── 50000.quoted.csv
│ ├── createData.js
│ ├── index.js
│ └── package.json
├── example-runner
│ ├── .eslintrc.js
│ ├── CHANGELOG.md
│ ├── bin
│ │ └── run-examples
│ └── package.json
├── fast-csv-js
│ ├── .eslintrc.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── examples
│ │ ├── assets
│ │ │ ├── parse.csv
│ │ │ └── snake_case_users.csv
│ │ ├── format.example.js
│ │ ├── models
│ │ │ └── user.js
│ │ ├── parse.example.js
│ │ └── parse_and_format_transform_async.example.js
│ └── package.json
├── fast-csv-ts
│ ├── .eslintrc.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── assets
│ │ ├── parse.csv
│ │ └── snake_case_users.csv
│ ├── examples
│ │ ├── format.example.ts
│ │ ├── models
│ │ │ └── user.ts
│ │ ├── parse.example.ts
│ │ └── parse_and_format_transform_async.example.ts
│ ├── package.json
│ └── tsconfig.json
├── formatting-js
│ ├── .eslintrc.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── examples
│ │ ├── append.example.js
│ │ ├── delimiter_option.example.js
│ │ ├── escape_option.example.js
│ │ ├── format.example.js
│ │ ├── hash_array.example.js
│ │ ├── headers_auto_discovery_hash_array.example.js
│ │ ├── headers_auto_discovery_object.example.js
│ │ ├── headers_provided_array.example.js
│ │ ├── headers_provided_hash_array.example.js
│ │ ├── headers_provided_object.example.js
│ │ ├── headers_provided_object_remove_column.example.js
│ │ ├── quote_all_columns.example.js
│ │ ├── quote_all_headers.example.js
│ │ ├── quote_columns_array.example.js
│ │ ├── quote_columns_not_headers.example.js
│ │ ├── quote_columns_object.example.js
│ │ ├── quote_headers_array.example.js
│ │ ├── quote_headers_object.example.js
│ │ ├── quote_option.example.js
│ │ ├── quote_some_columns_and_headers.example.js
│ │ ├── row_delimiter_option.example.js
│ │ ├── transform.example.js
│ │ ├── transform_async.example.js
│ │ ├── transform_option.example.js
│ │ ├── write.example.js
│ │ ├── write_headers_auto_discover.example.js
│ │ ├── write_headers_provided_headers.example.js
│ │ ├── write_to_buffer.example.js
│ │ ├── write_to_path.example.js
│ │ ├── write_to_stream.example.js
│ │ ├── write_to_string.example.js
│ │ ├── write_to_string_no_headers.example.js
│ │ └── write_to_string_transform.example.js
│ └── package.json
├── formatting-ts
│ ├── .eslintrc.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── examples
│ │ ├── append.example.ts
│ │ ├── delimiter_option.example.ts
│ │ ├── escape_option.example.ts
│ │ ├── format.example.ts
│ │ ├── hash_array.example.ts
│ │ ├── headers_auto_discovery_hash_array.example.ts
│ │ ├── headers_auto_discovery_object.example.ts
│ │ ├── headers_provided_array.example.ts
│ │ ├── headers_provided_hash_array.example.ts
│ │ ├── headers_provided_object.example.ts
│ │ ├── headers_provided_object_remove_column.example.ts
│ │ ├── quote_all_columns.example.ts
│ │ ├── quote_all_headers.example.ts
│ │ ├── quote_columns_array.example.ts
│ │ ├── quote_columns_not_headers.example.ts
│ │ ├── quote_columns_object.example.ts
│ │ ├── quote_headers_array.example.ts
│ │ ├── quote_headers_object.example.ts
│ │ ├── quote_option.example.ts
│ │ ├── quote_some_columns_and_headers.example.ts
│ │ ├── row_delimiter_option.example.ts
│ │ ├── transform.example.ts
│ │ ├── transform_async.example.ts
│ │ ├── transform_option.example.ts
│ │ ├── write.example.ts
│ │ ├── write_headers_auto_discover.example.ts
│ │ ├── write_headers_provided_headers.example.ts
│ │ ├── write_to_buffer.example.ts
│ │ ├── write_to_path.example.ts
│ │ ├── write_to_stream.example.ts
│ │ ├── write_to_string.example.ts
│ │ ├── write_to_string_no_headers.example.ts
│ │ └── write_to_string_transform.example.ts
│ ├── package.json
│ └── tsconfig.json
├── js.eslintrc.js
├── parsing-js
│ ├── .eslintrc.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── assets
│ │ └── snake_case_users.csv
│ ├── examples
│ │ ├── alternate_delimiter.example.js
│ │ ├── custom_headers.example.js
│ │ ├── first_row_as_headers.example.js
│ │ ├── ignore_empty_rows.example.js
│ │ ├── manual_write.example.js
│ │ ├── max_rows.example.js
│ │ ├── parse_string.example.js
│ │ ├── pipe.example.js
│ │ ├── rename_headers.example.js
│ │ ├── skip_lines.example.js
│ │ ├── skip_rows.example.js
│ │ ├── skipping_columns.example.js
│ │ ├── transform.example.js
│ │ ├── transform_async.example.js
│ │ ├── transform_headers.example.js
│ │ ├── validate.example.js
│ │ ├── validate_async.example.js
│ │ └── validate_with_reason.example.js
│ └── package.json
└── parsing-ts
│ ├── .eslintrc.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── assets
│ └── snake_case_users.csv
│ ├── examples
│ ├── alternate_delimiter.example.ts
│ ├── custom_headers.example.ts
│ ├── first_row_as_headers.example.ts
│ ├── ignore_empty_rows.example.ts
│ ├── manual_write.example.ts
│ ├── max_rows.example.ts
│ ├── parse_string.example.ts
│ ├── pipe.example.ts
│ ├── rename_headers.example.ts
│ ├── skip_lines.example.ts
│ ├── skip_rows.example.ts
│ ├── skipping_columns.example.ts
│ ├── transform.example.ts
│ ├── transform_async.example.ts
│ ├── transform_headers.example.ts
│ ├── validate.example.ts
│ ├── validate_async.example.ts
│ └── validate_with_reason.example.ts
│ ├── package.json
│ └── tsconfig.json
├── jest.config.js
├── lerna.json
├── package-lock.json
├── package.json
├── packages
├── fast-csv
│ ├── .eslintrc.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __tests__
│ │ └── fast-csv.spec.ts
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ └── tsconfig.json
├── format
│ ├── .eslintrc.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __tests__
│ │ ├── CsvFormatterStream.spec.ts
│ │ ├── FormatterOptions.spec.ts
│ │ ├── __fixtures__
│ │ │ ├── .gitkeep
│ │ │ ├── RecordingStream.ts
│ │ │ └── index.ts
│ │ ├── format.spec.ts
│ │ ├── formatter
│ │ │ ├── FieldFormatter.spec.ts
│ │ │ └── RowFormatter.spec.ts
│ │ └── issues
│ │ │ ├── __fixtures__
│ │ │ └── .gitkeep
│ │ │ ├── issue158.spec.ts
│ │ │ ├── issue252.spec.ts
│ │ │ ├── issue446.spec.ts
│ │ │ ├── issue503.spec.ts
│ │ │ ├── issue77.spec.ts
│ │ │ └── issue97.spec.ts
│ ├── package.json
│ ├── src
│ │ ├── CsvFormatterStream.ts
│ │ ├── FormatterOptions.ts
│ │ ├── formatter
│ │ │ ├── FieldFormatter.ts
│ │ │ ├── RowFormatter.ts
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ └── types.ts
│ └── tsconfig.json
└── parse
│ ├── .eslintrc.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __tests__
│ ├── CsvParsingStream.spec.ts
│ ├── ParserOptions.spec.ts
│ ├── __fixtures__
│ │ ├── RecordingStream.ts
│ │ ├── alternateEncoding.ts
│ │ ├── duplicateHeaders.ts
│ │ ├── emptyRows.ts
│ │ ├── headerColumnMismatch.ts
│ │ ├── helpers.ts
│ │ ├── index.ts
│ │ ├── malformed.ts
│ │ ├── noHeadersAndQuotes.ts
│ │ ├── skipLines.ts
│ │ ├── tmp
│ │ │ ├── malformed.csv
│ │ │ └── with_headers.csv
│ │ ├── trailingComma.ts
│ │ ├── withHeaders.ts
│ │ ├── withHeadersAlternateDelimiter.ts
│ │ ├── withHeadersAndAlternateQuote.ts
│ │ ├── withHeadersAndMissingColumns.ts
│ │ ├── withHeadersAndQuotes.ts
│ │ └── withHeadersAndSkippedLines.ts
│ ├── issues
│ │ ├── __fixtures__
│ │ │ ├── issue102.csv
│ │ │ ├── issue68-invalid.tsv
│ │ │ ├── issue68.tsv
│ │ │ └── issue87.csv
│ │ ├── issue102.spec.ts
│ │ ├── issue111.spec.ts
│ │ ├── issue131.spec.ts
│ │ ├── issue150.spec.ts
│ │ ├── issue174.spec.ts
│ │ ├── issue214.spec.ts
│ │ ├── issue223.spec.ts
│ │ ├── issue317.spec.ts
│ │ ├── issue340.spec.ts
│ │ ├── issue356.spec.ts
│ │ ├── issue540.spec.ts
│ │ ├── issue68.spec.ts
│ │ ├── issue87.spec.ts
│ │ └── issue93.spec.ts
│ ├── parse.spec.ts
│ ├── parser
│ │ ├── Parser.spec.ts
│ │ ├── RowParser.spec.ts
│ │ ├── Scanner.spec.ts
│ │ └── column
│ │ │ ├── ColumnParser.spec.ts
│ │ │ ├── NonQuotedColumnParser.spec.ts
│ │ │ └── QuotedColumnParser.spec.ts
│ └── transforms
│ │ ├── HeaderTransformer.spec.ts
│ │ └── RowTransformerValidator.spec.ts
│ ├── package.json
│ ├── src
│ ├── CsvParserStream.ts
│ ├── ParserOptions.ts
│ ├── index.ts
│ ├── parser
│ │ ├── Parser.ts
│ │ ├── RowParser.ts
│ │ ├── Scanner.ts
│ │ ├── Token.ts
│ │ ├── column
│ │ │ ├── ColumnFormatter.ts
│ │ │ ├── ColumnParser.ts
│ │ │ ├── NonQuotedColumnParser.ts
│ │ │ ├── QuotedColumnParser.ts
│ │ │ └── index.ts
│ │ └── index.ts
│ ├── transforms
│ │ ├── HeaderTransformer.ts
│ │ ├── RowTransformerValidator.ts
│ │ └── index.ts
│ └── types.ts
│ └── tsconfig.json
├── renovate.json
├── tsconfig.build.json
└── tsconfig.json
/.commitlintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@commitlint/config-angular"],
3 | "rules": {
4 | "subject-case": [
5 | 2,
6 | "always",
7 | ["sentence-case", "start-case", "pascal-case", "upper-case", "lower-case"]
8 | ],
9 | "type-enum": [
10 | 2,
11 | "always",
12 | [
13 | "build",
14 | "chore",
15 | "ci",
16 | "docs",
17 | "feat",
18 | "fix",
19 | "perf",
20 | "refactor",
21 | "revert",
22 | "style",
23 | "test",
24 | "example"
25 | ]
26 | ]
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | **/build
2 | **/node_modules
3 | documentation
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[BUG]"
5 | labels: bug
6 | assignees: doug-martin, dustinsmith1024
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **Parsing or Formatting?**
14 |
15 | - [ ] Formatting
16 | - [ ] Parsing
17 |
18 | **To Reproduce**
19 | Steps to reproduce the behavior:
20 | 1. Example file contents if applicable
21 | 2. Example code to reproduce the issue.
22 |
23 | **Expected behavior**
24 | A clear and concise description of what you expected to happen.
25 |
26 | **Screenshots**
27 | If applicable, add screenshots to help explain your problem.
28 |
29 | **Desktop (please complete the following information):**
30 | - OS: [e.g. MacOS]
31 | - OS Version [e.g. Mojave]
32 | - Node Version [e.g. 10.16.0]
33 |
34 | **Additional context**
35 | Add any other context about the problem here.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: "[FEATURE]"
5 | labels: enhancement
6 | assignees: doug-martin, dustinsmith1024
7 |
8 | ---
9 |
10 | **Parsing or Formatting?**
11 |
12 | - [ ] Formatting
13 | - [ ] Parsing
14 |
15 | **Is your feature request related to a problem? Please describe.**
16 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
17 |
18 | **Describe the solution you'd like**
19 | A clear and concise description of what you want to happen.
20 |
21 | **Describe alternatives you've considered**
22 | A clear and concise description of any alternative solutions or features you've considered.
23 |
24 | **Additional context**
25 | Add any other context or screenshots about the feature request here.
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ### All Submissions:
2 |
3 | * [ ] Have you followed the guidelines in our Contributing document?
4 | * [ ] Have you checked to ensure there aren't other open [Pull Requests](https://github.com/c2fo/fast-csv/pulls) for the same update/change?
5 |
6 |
7 |
8 | ### New Feature Submissions:
9 |
10 | 1. [ ] Have you added tests for the new feature
11 | 2. [ ] Does your submission pass tests?
12 | 3. [ ] Have you lint your code locally prior to submission?
13 | 4. [ ] Have you updated the docs?
14 | * [ ] If you added new parsing or formatting options have you added them to the docs?
15 | * [ ] If applicable have you added an example to the parsing or formatting docs?
16 |
17 | ### Changes to Core Features:
18 |
19 | * [ ] Have you added an explanation of what your changes do and why you'd like us to include them?
20 | * [ ] Have you written new tests for your core changes, as applicable?
21 | * [ ] Have you successfully ran tests with your changes locally?
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 |
3 | on:
4 | push:
5 | branches: # Array of patterns that match refs/heads
6 | - main # Push events on main branch
7 | pull_request: # Specify a second event with pattern matching
8 | env:
9 | CI: true
10 | jobs:
11 | unit:
12 | runs-on: ubuntu-latest
13 | strategy:
14 | matrix:
15 | node-version: [18.x, 20.x, 21.x]
16 | steps:
17 | - uses: actions/checkout@v4
18 | - name: Use Node.js ${{ matrix.node-version }}
19 | uses: actions/setup-node@v4
20 | with:
21 | node-version: ${{ matrix.node-version }}
22 | - name: Restore Dependencies
23 | uses: actions/cache@v4
24 | with:
25 | path: ~/.npm
26 | key: ${{ runner.os }}-node-${{matrix.node-version}}-${{ hashFiles('**/package-lock.json') }}
27 | restore-keys: |
28 | ${{ runner.os }}-node-${{matrix.node-version}}-
29 | - run: npm ci
30 | - run: npm run build
31 | - run: npm run lint
32 | - run: npm run jest
33 | - run: npm run examples
34 | - run: npm run benchmarks
35 | - name: Coveralls GitHub Action
36 | # Per Actions best practices, SHA is the safest for third party actions
37 | # https://github.com/coverallsapp/github-action/releases/tag/v2.3.4
38 | uses: coverallsapp/github-action@cfd0633edbd2411b532b808ba7a8b5e04f76d2c8
39 | with:
40 | github-token: ${{ secrets.GITHUB_TOKEN }}
41 | flag-name: run-unit-${{ matrix.node-version }}
42 | parallel: true
43 |
44 | finish:
45 | needs: unit
46 | runs-on: ubuntu-latest
47 | steps:
48 | - name: Coveralls Finished
49 | # Per Actions best practices, SHA is the safest for third party actions
50 | # https://github.com/coverallsapp/github-action/releases/tag/v2.3.4
51 | uses: coverallsapp/github-action@cfd0633edbd2411b532b808ba7a8b5e04f76d2c8
52 | with:
53 | github-token: ${{ secrets.github_token }}
54 | parallel-finished: true
55 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.iml
3 | .DS_Store
4 | .idea
5 | benchmark/results
6 | .nyc_output
7 | build
8 | coverage
9 | **/*.tmp.csv
10 | **/*.tsbuildinfo
11 | lerna-debug.log
12 |
--------------------------------------------------------------------------------
/.huskyrc:
--------------------------------------------------------------------------------
1 | {
2 | "skipCI": false,
3 | "hooks": {
4 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
5 | "pre-commit": "npm test"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | if-present=true
2 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 20.18.0
2 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "printWidth": 120,
4 | "trailingComma": "all",
5 | "tabWidth": 4
6 | }
7 |
--------------------------------------------------------------------------------
/.run/Run Examples.run.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.run/Serve Docs.run.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.run/jest.config.js.run.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2011-2025 C2FO
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [](https://www.npmjs.org/package/fast-csv)
6 | [](https://coveralls.io/github/C2FO/fast-csv?branch=main)
7 | [](https://snyk.io/test/github/C2FO/fast-csv?targetFile=package.json)
8 |
9 | # Fast-csv
10 |
11 | Fast-csv is library for parsing and formatting CSVs or any other delimited value file in node.
12 |
13 | ## Features
14 |
15 | * CSV Formatting
16 | * CSV Parsing
17 | * Built using typescript.
18 | * Flexible [formatting](https://c2fo.github.io/fast-csv/docs/formatting/options) and [parsing](https://c2fo.github.io/fast-csv/docs/parsing/options) options, to fit almost any scenario.
19 | * Built with streams first to avoid creating large memory footprint when parsing large files.
20 | * Battle tested in production, parsing and formatting millions of records every day.
21 |
22 | ## Install
23 |
24 | See [installation docs](https://c2fo.github.io/fast-csv/docs/introduction/install)
25 |
26 | ## Packages
27 |
28 |
29 | * `fast-csv` - One-stop shop for all methods and options from `@fast-csv/format` and `@fast-csv/parse`. [Get Started!](https://c2fo.github.io/fast-csv/docs/introduction/getting-started)
30 | * `@fast-csv/parse` - Parsing package, use this if you only need to parse files. [Get Started!](https://c2fo.github.io/fast-csv/docs/parsing/getting-started)
31 | * `@fast-csv/format` - Formatting package, use this if you only need to format files. [Get Started!](https://c2fo.github.io/fast-csv/docs/formatting/getting-started)
32 |
33 | ## License
34 |
35 | MIT
36 |
37 | ## Meta
38 | * Code: `git clone git://github.com/C2FO/fast-csv.git`
39 | * Website:
40 | * X: [http://x.com/c2fo](http://x.com/c2fo) - 877.465.4045
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/contributing.md:
--------------------------------------------------------------------------------
1 | ## Contributions
2 |
3 | First of all **thank you** for considering contributing to this open source project!
4 |
5 | I am always welcoming contributions of any type. Please open an issue or create a PR if you find an issue with any of the following.
6 |
7 | * An issue with Documentation (typo, incorrect code example)
8 | * You found the documentation lacking in some way
9 |
10 | If you have an issue with the library please include the following
11 |
12 | * A description of the problem
13 | * Does this issue occur while formatting or parsing a csv.
14 | * A short example of how to reproduce (if applicable)
15 | * A sample csv
16 | * Sample code to reproduce the issue
17 |
18 | Without those basics it can be difficult to reproduce your issue locally. You may be asked for more information but that is a good starting point.
19 |
20 | ### New Features
21 |
22 | New features and/or enhancements are great and I encourage you to either submit a PR or create an issue. In both cases include the following as the need/requirement may not be readily apparent.
23 |
24 | 1. The use case
25 | 2. A short example
26 |
27 | If you are issuing a PR also also include the following
28 |
29 | 1. Tests - otherwise the PR will not be merged
30 | 2. Documentation - otherwise the PR will not be merged
31 | 3. Examples
32 |
33 | If you find an issue you want to work on please comment on it letting other people know you are looking at it and I will assign the issue to you.
34 |
35 | If want to work on an issue but dont know where to start just leave a comment and I'll be more than happy to point you in the right direction.
--------------------------------------------------------------------------------
/documentation/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | /node_modules
3 |
4 | # Production
5 | /build
6 |
7 | # Generated files
8 | .docusaurus
9 | .cache-loader
10 |
11 | # Misc
12 | .DS_Store
13 | .env.local
14 | .env.development.local
15 | .env.test.local
16 | .env.production.local
17 |
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 |
--------------------------------------------------------------------------------
/documentation/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [5.0.2](https://github.com/C2FO/fast-csv/compare/v5.0.1...v5.0.2) (2024-10-22)
7 |
8 | ### Bug Fixes
9 |
10 | - **deps:** update docusaurus monorepo to v3.3.2 ([#888](https://github.com/C2FO/fast-csv/issues/888)) ([60f5e27](https://github.com/C2FO/fast-csv/commit/60f5e2759f8d4455dd39745aab88a6eb6f97e83d))
11 | - **deps:** update docusaurus monorepo to v3.4.0 ([#961](https://github.com/C2FO/fast-csv/issues/961)) ([cef2f2e](https://github.com/C2FO/fast-csv/commit/cef2f2ece4612db7d52bac8bbc34dd181c2b19c0))
12 |
13 | # [5.0.0](https://github.com/C2FO/fast-csv/compare/v4.3.6...v5.0.0) (2024-01-13)
14 |
15 | ### Bug Fixes
16 |
17 | - **deps:** update dependency classnames to v2.4.0 ([#642](https://github.com/C2FO/fast-csv/issues/642)) ([3ce8ad8](https://github.com/C2FO/fast-csv/commit/3ce8ad8b57a84e6b00630c0ca82c987de157d248))
18 | - **deps:** update dependency classnames to v2.5.0 ([#847](https://github.com/C2FO/fast-csv/issues/847)) ([8a38bd2](https://github.com/C2FO/fast-csv/commit/8a38bd275fb53f07a0b2bba99652219f6b660809))
19 | - **deps:** update dependency classnames to v2.5.1 ([#849](https://github.com/C2FO/fast-csv/issues/849)) ([4187b08](https://github.com/C2FO/fast-csv/commit/4187b08b4d66822b84c92bd60c18893ce5893403))
20 | - **deps:** update docusaurus monorepo to v2.4.3 ([#531](https://github.com/C2FO/fast-csv/issues/531)) ([ed71ed4](https://github.com/C2FO/fast-csv/commit/ed71ed4ec7f3ce69dbe3ec174ac9e9170f154712))
21 | - **deps:** update docusaurus monorepo to v3 ([#844](https://github.com/C2FO/fast-csv/issues/844)) ([7fdb903](https://github.com/C2FO/fast-csv/commit/7fdb9032b8a67fd1443c56da36ceb72ddf8c9e94))
22 | - **deps:** update docusaurus monorepo to v3.1.0 ([#855](https://github.com/C2FO/fast-csv/issues/855)) ([4f67398](https://github.com/C2FO/fast-csv/commit/4f673981120e46a3616ca39f12596f85fe3a0275))
23 | - **deps:** update react monorepo to v18 ([#845](https://github.com/C2FO/fast-csv/issues/845)) ([a447d06](https://github.com/C2FO/fast-csv/commit/a447d0686cebc7f1a2db157166cfe77ffe52523d))
24 |
--------------------------------------------------------------------------------
/documentation/README.md:
--------------------------------------------------------------------------------
1 | # Website
2 |
3 | This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator.
4 |
5 | ### Installation
6 |
7 | ```
8 | $ yarn
9 | ```
10 |
11 | ### Local Development
12 |
13 | ```
14 | $ yarn start
15 | ```
16 |
17 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server.
18 |
19 | ### Build
20 |
21 | ```
22 | $ yarn build
23 | ```
24 |
25 | This command generates static content into the `build` directory and can be served using any static contents hosting service.
26 |
27 | ### Deployment
28 |
29 | ```
30 | $ GIT_USER= USE_SSH=true yarn deploy
31 | ```
32 |
33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
34 |
--------------------------------------------------------------------------------
/documentation/blog/2020-03-11-new-docs.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Initial Release
3 | author: Doug Martin
4 | author_title: Creator
5 | author_url: https://github.com/doug-martin
6 | author_image_url: https://avatars1.githubusercontent.com/u/361261?v=4
7 | tags: [fast-csv, docs]
8 | ---
9 |
10 | New docs!
11 |
--------------------------------------------------------------------------------
/documentation/docs/formatting/getting-started.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Getting Started
3 | ---
4 |
5 | import Tabs from '@theme/Tabs';
6 | import TabItem from '@theme/TabItem';
7 |
8 | `fast-csv` package to create CSVs.
9 |
10 | ## Installation
11 |
12 | See [installation docs](../introduction/install.md)
13 |
14 | ## Usage
15 |
16 |
23 |
24 |
25 | ```ts
26 | import * as csv from '@fast-csv/format';
27 | ```
28 |
29 |
30 |
31 |
32 | ```js
33 | const csv = require('@fast-csv/format');
34 | ```
35 |
36 |
37 |
38 |
39 | ### Docs
40 |
41 | * [Options](options.md) - Documentation options that can be passed to formatting methods.
42 | * [Row Types](row-types.md) - Documentation for supported row formats and their usages.
43 | * [Methods](methods.mdx) - Documentation for exported formatting methods.
44 | * [Examples](examples.mdx) - TypeScript and JavaScript examples.
45 |
--------------------------------------------------------------------------------
/documentation/docs/formatting/row-types.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Row Types
3 | ---
4 | When creating a CSV `fast-csv` supports a few row formats.
5 |
6 | **`{[string]: any}`**
7 |
8 | You can pass in object to any formatter function if your CSV requires headers the keys of the first object will be used as the header names.
9 |
10 | ```javascript
11 | {
12 | a: "a1",
13 | b: "b1",
14 | c: "c1",
15 | }
16 |
17 | //Generated CSV
18 | //a,b,c
19 | //a1,b1,c1
20 | ```
21 |
22 | **`string[]`**
23 |
24 | You can also pass in your rows as arrays. If your CSV requires headers the first row passed in will be the headers used.
25 |
26 | ```javascript
27 | [
28 | ["a", "b", "c"],
29 | ["a1", "b1", "c1"]
30 | ]
31 | //Generated CSV
32 | //a,b,c
33 | //a1,b1,c1
34 | ```
35 |
36 | **`[string, any][]`**
37 |
38 | This is the least commonly used format but can be useful if you have requirements to generate a CSV with headers with the same column name (Crazy we know but we have seen it).
39 |
40 | ```javascript
41 | [
42 | [
43 | ["a", "a1"],
44 | ["a", "a2"],
45 | ["b", "b1"],
46 | ["b", "b2"],
47 | ["c", "c1"],
48 | ["c", "c2"]
49 | ]
50 | ]
51 |
52 | //Generated CSV
53 | //a,a,b,b,c,c
54 | //a1,a2,b1,b2,c1,c2
55 | ```
56 |
--------------------------------------------------------------------------------
/documentation/docs/introduction/getting-started.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Getting Started
3 | ---
4 |
5 |
6 | Fast-csv is library for parsing and formatting CSVs or any other delimited value file in node.
7 |
8 | ## Features
9 |
10 | * CSV Formatting
11 | * CSV Parsing
12 | * Built using typescript.
13 | * Flexible [formatting](../formatting/options.md) and [parsing](../parsing/options.md) options, to fit almost any scenario.
14 | * Built with streams first to avoid creating large memory footprint when parsing large files.
15 | * Battle tested in production, parsing and formatting millions of records every day.
16 |
17 | ## Install
18 |
19 | See [installation docs](./install.md)
20 |
21 | ## Packages
22 |
23 |
24 | * `fast-csv` - One stop shop for all methods and options from `@fast-csv/format` and `@fast-csv/parse`.
25 | * `@fast-csv/parse` - Parsing package, use this if you only need to parse files. [Get Started!](../parsing/getting-started.mdx)
26 | * `@fast-csv/format` - Formatting package, use this if you only need to format files. [Get Started!](../formatting/getting-started.mdx)
27 |
28 | ### Migrating from older versions
29 |
30 | * [From `v2.x` to `v3.x`](../migration-guides/v2.x-to-v3.x.md)
31 |
--------------------------------------------------------------------------------
/documentation/docs/introduction/install.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Installation
3 | ---
4 |
5 | > [!NOTE]
6 | > `fast-csv` only supports the currently supported releases of [nodejs](https://nodejs.org/en/about/releases/).
7 | > You can find the currently supported releases [here](https://endoflife.date/nodejs).
8 |
9 | ## fast-csv
10 |
11 | ```sh
12 | npm i -S fast-csv
13 | ```
14 |
15 | ## @fast-csv/parse
16 |
17 | ```sh
18 | npm i -S @fast-csv/parse
19 | ```
20 |
21 | ## @fast-csv/format
22 |
23 | ```sh
24 | npm i -S @fast-csv/format
25 | ```
26 |
--------------------------------------------------------------------------------
/documentation/docs/migration-guides/v2.x-to-v3.x.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: v0.2.x to v0.3.x
3 | ---
4 |
5 | ### Parsing Changed
6 |
7 | #### Signature changes
8 |
9 | * Calling the library as a function has been removed in favor of `csv.parse`.
10 | * `csv()` change to `csv.parse()`
11 | * Deprecated `fromString` in favor of `parseString`
12 | * `csv.fromString()` change to `csv.parseString()`
13 | * Deprecated `fromStream` in favor of `parseStream`a
14 | * `csv.fromStream()` change to `csv.parseStream()`
15 | * Deprecated`fromPath` in favor of `parseFile`
16 | * `csv.fromPath()` change to `csv.parseFile()`
17 |
18 | ### Formatting Changes
19 | * `csv.createWriteStream` has been removed in favor of `csv.format`
20 | * `csv.writeToBuffer` and `csv.writeToString` no longer accepts a `callback`, instead they return a promise `Promise`
21 |
--------------------------------------------------------------------------------
/documentation/docs/parsing/benchmark.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Benchmarks
3 | ---
4 |
5 | [Source in github](https://github.com/C2FO/fast-csv/tree/master/examples/benchmark)
6 |
7 | ## Quoted
8 |
9 | A csv with quoted columns.
10 |
11 | This is benchmark is important because quoted columns require additional logic to parse.
12 |
13 |
14 | |Type|Row Count|No. Runs|Avg|
15 | |-|-|-|-|
16 | |quoted|1000|5|10.8ms|
17 | |quoted|10000|5|70.8ms|
18 | |quoted|20000|5|144.2ms|
19 | |quoted|50000|5|356.6ms|
20 | |quoted|100000|5|712.2ms|
21 |
22 | ## Non-quoted
23 |
24 | A csv without quoted columns.
25 |
26 | Non-quoted fields require less logic to be parsed, and should be faster.
27 |
28 | |Type|Row Count|No. Runs|Avg|
29 | |-|-|-|-|
30 | |nonquoted|1000|5|15ms|
31 | |nonquoted|10000|5|62ms|
32 | |nonquoted|20000|5|102.2ms|
33 | |nonquoted|50000|5|259ms|
34 | |nonquoted|100000|5|513ms|
35 |
--------------------------------------------------------------------------------
/documentation/docs/parsing/events.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Events
3 | ---
4 |
5 | ## `headers`
6 | Emitted when the headers are parsed
7 |
8 | * If the [headers option](./options.md#headers) is a function that transform headers, the array passed to this event will be the transformed headers
9 | * If the [headers option](./options.md#headers) is set to an array of headers, the emitted header will be the option passed in.
10 | * If the [headers option](./options.md#headers) is set to `true` the headers will be the parsed headers from the csv.
11 |
12 | :::note
13 | If the [headers option](./options.md#headers) is set to `false` or the csv has no rows then the event WILL NOT be emitted.
14 | :::
15 |
16 | ## `data`
17 | Emitted when a record is parsed.
18 |
19 | * If headers are present then all rows will be an object.
20 | * If headers are not present then all rows will be an array.
21 |
22 | :::note
23 | If [objectMode](./options.md#objectmode) is set to false then all rows will be a buffer with a JSON row.
24 | :::
25 |
26 | ## data-invalid
27 | Emitted if there was invalid row encounted;
28 |
29 | * Emitted when a `validate` function is provided and an invalid row is encountered.
30 | * Emitted when [strictColumnHandling](./options.md#strictcolumnhandling) is `true` and a row with a different number of fields than headers is encountered.
31 |
--------------------------------------------------------------------------------
/documentation/docs/parsing/getting-started.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Getting Started
3 | ---
4 | import Tabs from '@theme/Tabs';
5 | import TabItem from '@theme/TabItem';
6 |
7 | `fast-csv` package to parse CSVs.
8 |
9 | ## Installation
10 |
11 | See [installation docs](../introduction/install.md)
12 |
13 | ## Usage
14 |
15 |
22 |
23 |
24 | ```ts
25 | import * as csv from '@fast-csv/parse';
26 | ```
27 |
28 |
29 |
30 |
31 | ```js
32 | const csv = require('@fast-csv/parse');
33 | ```
34 |
35 |
36 |
37 |
38 | ### Docs
39 |
40 | * [Options](./options.md) - Documentation options that can be passed to parsing methods.
41 | * [Events](./events.md) - Documentation for events emitted from the parser stream.
42 | * [Methods](./methods.mdx) - Documentation for exported parsing methods.
43 | * [Examples](./examples.mdx) - TypeScript and JavaScript examples.
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/documentation/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fast-csv/docs",
3 | "version": "5.0.3",
4 | "private": true,
5 | "scripts": {
6 | "start": "docusaurus start --port=3001",
7 | "build": "docusaurus build",
8 | "swizzle": "docusaurus swizzle",
9 | "deploy": "docusaurus deploy"
10 | },
11 | "dependencies": {
12 | "@docusaurus/core": "3.7.0",
13 | "@docusaurus/preset-classic": "3.7.0",
14 | "classnames": "2.5.1",
15 | "react": "18.3.1",
16 | "react-dom": "18.3.1"
17 | },
18 | "browserslist": {
19 | "production": [
20 | ">0.2%",
21 | "not dead",
22 | "not op_mini all"
23 | ],
24 | "development": [
25 | "last 1 chrome version",
26 | "last 1 firefox version",
27 | "last 1 safari version"
28 | ]
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/documentation/sidebars.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | docs: {
3 | Introduction: ['introduction/getting-started', 'introduction/install', 'introduction/example'],
4 | Parsing: [
5 | 'parsing/getting-started',
6 | 'parsing/options',
7 | 'parsing/events',
8 | 'parsing/methods',
9 | 'parsing/examples',
10 | 'parsing/benchmark',
11 | ],
12 | Formatting: [
13 | 'formatting/getting-started',
14 | 'formatting/options',
15 | 'formatting/row-types',
16 | 'formatting/methods',
17 | 'formatting/examples',
18 | ],
19 | 'Migration Guides': ['migration-guides/v2.x-to-v3.x'],
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/documentation/src/css/custom.css:
--------------------------------------------------------------------------------
1 | /* stylelint-disable docusaurus/copyright-header */
2 | /**
3 | * Any CSS included here will be global. The classic template
4 | * bundles Infima by default. Infima is a CSS framework designed to
5 | * work well for content-centric websites.
6 | */
7 |
8 | /* You can override the default Infima variables here. */
9 | :root {
10 | --ifm-color-primary: #18b7b7;
11 | --ifm-color-primary-dark: rgb(33, 175, 144);
12 | --ifm-color-primary-darker: rgb(31, 165, 136);
13 | --ifm-color-primary-darkest: rgb(26, 136, 112);
14 | --ifm-color-primary-light: rgb(70, 203, 174);
15 | --ifm-color-primary-lighter: rgb(102, 212, 189);
16 | --ifm-color-primary-lightest: rgb(146, 224, 208);
17 | --ifm-code-font-size: 95%;
18 | }
19 |
20 | .docusaurus-highlight-code-line {
21 | background-color: rgb(72, 77, 91);
22 | display: block;
23 | margin: 0 calc(-1 * var(--ifm-pre-padding));
24 | padding: 0 var(--ifm-pre-padding);
25 | }
26 |
--------------------------------------------------------------------------------
/documentation/src/pages/styles.module.css:
--------------------------------------------------------------------------------
1 | /* stylelint-disable docusaurus/copyright-header */
2 | /**
3 | * CSS files with the .module.css suffix will be treated as CSS modules
4 | * and scoped locally.
5 | */
6 |
7 | .heroBanner {
8 | padding: 4rem 0;
9 | text-align: center;
10 | position: relative;
11 | overflow: hidden;
12 | }
13 |
14 | @keyframes lightSpeedIn {
15 | from {
16 | transform: translate3d(100%, 0, 0) skewX(-30deg);
17 | opacity: 0;
18 | }
19 |
20 | 60% {
21 | transform: skewX(20deg);
22 | opacity: 1;
23 | }
24 |
25 | 80% {
26 | transform: skewX(-5deg);
27 | }
28 |
29 | to {
30 | transform: translate3d(0, 0, 0);
31 | }
32 | }
33 |
34 | .heroLogo {
35 | animation-duration: 1s;
36 | animation-name: lightSpeedIn;
37 | padding: 20px;
38 | max-width: 250px;
39 | }
40 |
41 | @media screen and (max-width: 966px) {
42 | .heroBanner {
43 | padding: 2rem;
44 | }
45 | }
46 |
47 | .buttons {
48 | display: flex;
49 | align-items: center;
50 | justify-content: center;
51 | }
52 |
53 | .features {
54 | display: flex;
55 | align-items: center;
56 | padding: 2rem 0;
57 | width: 100%;
58 | }
59 |
60 | .featureImage {
61 | height: 100px;
62 | width: 100px;
63 | }
64 |
--------------------------------------------------------------------------------
/documentation/static/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/C2FO/fast-csv/44272f806d122b96a6fe0a7202d4695de943f18a/documentation/static/img/favicon.ico
--------------------------------------------------------------------------------
/documentation/static/img/format_parse.svg:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/documentation/static/img/ts_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/C2FO/fast-csv/44272f806d122b96a6fe0a7202d4695de943f18a/documentation/static/img/ts_logo.png
--------------------------------------------------------------------------------
/examples/benchmark/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | rules: {
3 | 'no-console': 0,
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/examples/benchmark/README.md:
--------------------------------------------------------------------------------
1 | ## Benchmark Results
2 |
3 | |Type|Row Count|No. Runs|Avg|
4 | |-|-|-|-|
5 | |nonquoted|1000|5|5.6ms|
6 | |nonquoted|10000|5|23ms|
7 | |nonquoted|20000|5|42.2ms|
8 | |nonquoted|50000|5|95.8ms|
9 | |nonquoted|100000|5|209.2ms|
10 | |quoted|1000|5|4ms|
11 | |quoted|10000|5|28ms|
12 | |quoted|20000|5|51.4ms|
13 | |quoted|50000|5|122.2ms|
14 | |quoted|100000|5|243.2ms|
--------------------------------------------------------------------------------
/examples/benchmark/createData.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const fastCsv = require('fast-csv');
3 |
4 | const headers = [['first_name', 'last_name', 'email_address', 'address']];
5 |
6 | const nonQuotedLines = [
7 | ['First1', 'Last1', 'email1@email.com', '1 Street St State ST 88888'],
8 | ['First1', 'Last1', 'email1@email.com', ''],
9 | ['First1', 'Last1', '', ''],
10 | ['First1', '', '', ''],
11 | ['', '', '', ''],
12 | ];
13 |
14 | const quotedLines = [
15 | ["First'1", '"Last1"', '"email1@email.com"', '1 Street St, State ST, 88888'],
16 | ["First'1", '"Last1"', '"email1@email.com"', '""'],
17 | ["First'1", '"Last1"', '""', '""'],
18 | ["First'1", '""', '""', '""'],
19 | ['""', '""', '""', '""'],
20 | ];
21 |
22 | const writeCsv = (count, lineOptions, filename) => {
23 | console.log(`Writing ${filename}...`);
24 | const rows = [...headers];
25 | const lineOptionLength = lineOptions.length;
26 | for (let i = 0; i < count; i += 1) {
27 | rows.push(lineOptions[i % lineOptionLength]);
28 | }
29 | return new Promise((res, rej) => {
30 | fastCsv
31 | .writeToPath(path.resolve(__dirname, `./assets/${filename}`), rows)
32 | .on('finish', res)
33 | .on('error', rej);
34 | });
35 | };
36 |
37 | writeCsv(1000, nonQuotedLines, '1000.nonquoted.csv')
38 | .then(() => writeCsv(10000, nonQuotedLines, '10000.nonquoted.csv'))
39 | .then(() => writeCsv(20000, nonQuotedLines, '20000.nonquoted.csv'))
40 | .then(() => writeCsv(50000, nonQuotedLines, '50000.nonquoted.csv'))
41 | .then(() => writeCsv(100000, nonQuotedLines, '100000.nonquoted.csv'))
42 | .then(() => writeCsv(1000, quotedLines, '1000.quoted.csv'))
43 | .then(() => writeCsv(10000, quotedLines, '10000.quoted.csv'))
44 | .then(() => writeCsv(20000, quotedLines, '20000.quoted.csv'))
45 | .then(() => writeCsv(50000, quotedLines, '50000.quoted.csv'))
46 | .then(() => writeCsv(100000, quotedLines, '100000.quoted.csv'))
47 | .catch((e) => console.error(e));
48 |
--------------------------------------------------------------------------------
/examples/benchmark/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fast-csv-benchmarks",
3 | "version": "5.0.2",
4 | "private": true,
5 | "description": "fast-csv examples",
6 | "dependencies": {
7 | "fast-csv": "5.0.2"
8 | },
9 | "scripts": {
10 | "benchmarks": "node ./index.js"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/examples/example-runner/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | rules: {
3 | 'no-console': 0,
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/examples/example-runner/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example-runner",
3 | "version": "5.0.0",
4 | "private": true,
5 | "description": "Runs examples and checks output",
6 | "bin": {
7 | "run-all-examples": "./bin/run-examples",
8 | "run-examples": "./bin/run-examples"
9 | },
10 | "dependencies": {
11 | "@types/yargs": "17.0.32",
12 | "globby": "11.1.0",
13 | "jest-diff": "29.7.0",
14 | "typescript": "5.6.3",
15 | "yargs": "17.7.2"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/fast-csv-js/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | rules: {
3 | 'no-console': 0,
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/examples/fast-csv-js/README.md:
--------------------------------------------------------------------------------
1 | `fast-csv` javascript examples.
2 |
3 | ## Usage
4 |
5 | To run all examples
6 |
7 | ```sh
8 | npm run all-examples
9 | ```
10 |
11 | To see a list of all available examples
12 |
13 | ```sh
14 | npm run list
15 | ```
16 |
17 | To run a specific example
18 |
19 | ```sh
20 | npm run example -- {example_name}
21 | ```
22 |
--------------------------------------------------------------------------------
/examples/fast-csv-js/examples/assets/parse.csv:
--------------------------------------------------------------------------------
1 | header1,header2
2 | row1-col1,row1-col2
3 | row2-col1,row2-col2
4 | row3-col1,row3-col2
5 | row4-col1,row4-col2
6 | row5-col1,row5-col2
--------------------------------------------------------------------------------
/examples/fast-csv-js/examples/assets/snake_case_users.csv:
--------------------------------------------------------------------------------
1 | id,first_name,last_name,address
2 | 1,Bob,Yukon,1111 State St. Yukon AK
3 | 2,Sally,Yukon,1111 State St. Yukon AK
4 | 3,Bobby,Yukon,1111 State St. Yukon AK
5 | 4,Jane,Yukon,1111 State St. Yukon AK
6 | 5,Dick,Yukon,1111 State St. Yukon AK
7 | 6,John,Doe,1112 State St. Yukon AK
8 | 7,Jane,Doe,1113 State St. Yukon AK
9 | 8,Billy,Doe,1112 State St. Yukon AK
10 | 9,Edith,Doe,1112 State St. Yukon AK
--------------------------------------------------------------------------------
/examples/fast-csv-js/examples/format.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('fast-csv');
2 |
3 | const csvStream = csv.format({ headers: true });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write({ header1: 'row1-col1', header2: 'row1-col2' });
8 | csvStream.write({ header1: 'row2-col1', header2: 'row2-col2' });
9 | csvStream.write({ header1: 'row3-col1', header2: 'row3-col2' });
10 | csvStream.write({ header1: 'row4-col1', header2: 'row4-col2' });
11 | csvStream.end();
12 |
13 | // Output:
14 | // header1,header2
15 | // row1-col1,row1-col2
16 | // row2-col1,row2-col2
17 | // row3-col1,row3-col2
18 | // row4-col1,row4-col2
19 |
--------------------------------------------------------------------------------
/examples/fast-csv-js/examples/models/user.js:
--------------------------------------------------------------------------------
1 | class User {
2 | static findById(id, cb) {
3 | setImmediate(() => {
4 | cb(null, new User(id));
5 | });
6 | }
7 |
8 | constructor(id) {
9 | this.id = id;
10 | this.isVerified = id % 2 === 0;
11 | this.hasLoggedIn = this.isVerified ? id % 4 === 0 : false;
12 | this.age = +id + 10;
13 | }
14 | }
15 |
16 | module.exports = User;
17 |
--------------------------------------------------------------------------------
/examples/fast-csv-js/examples/parse.example.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const path = require('path');
3 | const csv = require('fast-csv');
4 |
5 | fs.createReadStream(path.resolve(__dirname, 'assets', 'parse.csv'))
6 | .pipe(csv.parse({ headers: true }))
7 | .on('error', (error) => console.error(error))
8 | .on('data', (row) => console.log(row))
9 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
10 |
11 | // Output:
12 | // { header1: 'row1-col1', header2: 'row1-col2' }
13 | // { header1: 'row2-col1', header2: 'row2-col2' }
14 | // { header1: 'row3-col1', header2: 'row3-col2' }
15 | // { header1: 'row4-col1', header2: 'row4-col2' }
16 | // { header1: 'row5-col1', header2: 'row5-col2' }
17 | // Parsed 5 rows
18 |
--------------------------------------------------------------------------------
/examples/fast-csv-js/examples/parse_and_format_transform_async.example.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const path = require('path');
3 | const csv = require('fast-csv');
4 | const User = require('./models/user');
5 |
6 | fs.createReadStream(path.resolve(__dirname, 'assets', 'snake_case_users.csv'))
7 | .pipe(csv.parse({ headers: true }))
8 | // pipe the parsed input into a csv formatter
9 | .pipe(csv.format({ headers: true }))
10 | // Using the transform function from the formatting stream
11 | .transform((row, next) => {
12 | User.findById(row.id, (err, user) => {
13 | if (err) {
14 | return next(err);
15 | }
16 | return next(null, {
17 | id: row.id,
18 | firstName: row.first_name,
19 | lastName: row.last_name,
20 | address: row.address,
21 | // properties from user
22 | isVerified: user.isVerified,
23 | hasLoggedIn: user.hasLoggedIn,
24 | age: user.age,
25 | });
26 | });
27 | })
28 | .pipe(process.stdout)
29 | .on('end', () => process.exit());
30 |
31 | // Output:
32 | // id,firstName,lastName,address,isVerified,hasLoggedIn,age
33 | // 1,Bob,Yukon,1111 State St. Yukon AK,false,false,11
34 | // 2,Sally,Yukon,1111 State St. Yukon AK,true,false,12
35 | // 3,Bobby,Yukon,1111 State St. Yukon AK,false,false,13
36 | // 4,Jane,Yukon,1111 State St. Yukon AK,true,true,14
37 | // 5,Dick,Yukon,1111 State St. Yukon AK,false,false,15
38 | // 6,John,Doe,1112 State St. Yukon AK,true,false,16
39 | // 7,Jane,Doe,1113 State St. Yukon AK,false,false,17
40 | // 8,Billy,Doe,1112 State St. Yukon AK,true,true,18
41 | // 9,Edith,Doe,1112 State St. Yukon AK,false,false,19
42 |
--------------------------------------------------------------------------------
/examples/fast-csv-js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fast-csv-js-examples",
3 | "version": "5.0.2",
4 | "private": true,
5 | "description": "fast-csv examples",
6 | "scripts": {
7 | "list": "run-examples list",
8 | "all-examples": "run-examples all",
9 | "example": "run-examples run"
10 | },
11 | "dependencies": {
12 | "example-runner": "5.0.0",
13 | "fast-csv": "5.0.2"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/fast-csv-ts/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | rules: {
3 | 'no-console': 0,
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/examples/fast-csv-ts/README.md:
--------------------------------------------------------------------------------
1 | `fast-csv` typescript examples.
2 |
3 | ## Usage
4 |
5 | ```sh
6 | npm run build
7 | ```
8 |
9 | To run all examples
10 |
11 | ```sh
12 | npm run all-examples
13 | ```
14 |
15 | To see a list of all available examples
16 |
17 | ```sh
18 | npm run example
19 | ```
20 |
21 | To run a specific example
22 |
23 | ```sh
24 | npm run example -- {example_name}
25 | ```
26 |
--------------------------------------------------------------------------------
/examples/fast-csv-ts/assets/parse.csv:
--------------------------------------------------------------------------------
1 | header1,header2
2 | row1-col1,row1-col2
3 | row2-col1,row2-col2
4 | row3-col1,row3-col2
5 | row4-col1,row4-col2
6 | row5-col1,row5-col2
--------------------------------------------------------------------------------
/examples/fast-csv-ts/assets/snake_case_users.csv:
--------------------------------------------------------------------------------
1 | id,first_name,last_name,address
2 | 1,Bob,Yukon,1111 State St. Yukon AK
3 | 2,Sally,Yukon,1111 State St. Yukon AK
4 | 3,Bobby,Yukon,1111 State St. Yukon AK
5 | 4,Jane,Yukon,1111 State St. Yukon AK
6 | 5,Dick,Yukon,1111 State St. Yukon AK
7 | 6,John,Doe,1112 State St. Yukon AK
8 | 7,Jane,Doe,1113 State St. Yukon AK
9 | 8,Billy,Doe,1112 State St. Yukon AK
10 | 9,Edith,Doe,1112 State St. Yukon AK
--------------------------------------------------------------------------------
/examples/fast-csv-ts/examples/format.example.ts:
--------------------------------------------------------------------------------
1 | import * as csv from 'fast-csv';
2 |
3 | const csvStream = csv.format({ headers: true });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write({ header1: 'row1-col1', header2: 'row1-col2' });
10 | csvStream.write({ header1: 'row2-col1', header2: 'row2-col2' });
11 | csvStream.write({ header1: 'row3-col1', header2: 'row3-col2' });
12 | csvStream.write({ header1: 'row4-col1', header2: 'row4-col2' });
13 | csvStream.write({ header1: 'row5-col1', header2: 'row5-col2' });
14 | csvStream.end();
15 |
16 | // Output:
17 | // header1,header2
18 | // row1-col1,row1-col2
19 | // row2-col1,row2-col2
20 | // row3-col1,row3-col2
21 | // row4-col1,row4-col2
22 | // row5-col1,row5-col2
23 |
--------------------------------------------------------------------------------
/examples/fast-csv-ts/examples/models/user.ts:
--------------------------------------------------------------------------------
1 | export type UserCallback = (err: Error | null, user?: User) => void;
2 |
3 | export class User {
4 | public readonly id: number;
5 |
6 | public readonly isVerified: boolean;
7 |
8 | public readonly hasLoggedIn: boolean;
9 |
10 | public readonly age: number;
11 |
12 | static findById(id: number, cb: UserCallback): void {
13 | setImmediate(() => {
14 | cb(null, new User(id));
15 | });
16 | }
17 |
18 | constructor(id: number) {
19 | this.id = id;
20 | this.isVerified = id % 2 === 0;
21 | this.hasLoggedIn = this.isVerified ? id % 4 === 0 : false;
22 | this.age = +id + 10;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/examples/fast-csv-ts/examples/parse.example.ts:
--------------------------------------------------------------------------------
1 | import * as fs from 'fs';
2 | import * as path from 'path';
3 | import * as csv from 'fast-csv';
4 |
5 | fs.createReadStream(path.resolve(__dirname, '..', 'assets', 'parse.csv'))
6 | .pipe(csv.parse({ headers: true }))
7 | .on('error', (error) => {
8 | return console.error(error);
9 | })
10 | .on('data', (row) => {
11 | return console.log(row);
12 | })
13 | .on('end', (rowCount: number) => {
14 | return console.log(`Parsed ${rowCount} rows`);
15 | });
16 |
17 | // Output:
18 | // { header1: 'row1-col1', header2: 'row1-col2' }
19 | // { header1: 'row2-col1', header2: 'row2-col2' }
20 | // { header1: 'row3-col1', header2: 'row3-col2' }
21 | // { header1: 'row4-col1', header2: 'row4-col2' }
22 | // { header1: 'row5-col1', header2: 'row5-col2' }
23 | // Parsed 5 rows
24 |
--------------------------------------------------------------------------------
/examples/fast-csv-ts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fast-csv-ts-examples",
3 | "version": "5.0.2",
4 | "private": true,
5 | "description": "fast-csv examples",
6 | "scripts": {
7 | "list": "run-examples --dir=build list",
8 | "all-examples": "run-examples --dir=build all",
9 | "example": "run-examples --dir=build run",
10 | "build": "npm run clean && npm run compile",
11 | "clean": "rm -rf ./build && rm -rf tsconfig.tsbuildinfo",
12 | "compile": "tsc"
13 | },
14 | "dependencies": {
15 | "example-runner": "5.0.0",
16 | "fast-csv": "5.0.2",
17 | "typescript": "5.6.3"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/fast-csv-ts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.build.json",
3 | "compilerOptions": {
4 | "outDir": "./build",
5 | "rootDir": "./examples"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/examples/formatting-js/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | rules: {
3 | 'no-console': 0,
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/examples/formatting-js/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [5.0.2](https://github.com/C2FO/fast-csv/compare/v5.0.1...v5.0.2) (2024-10-22)
7 |
8 | **Note:** Version bump only for package @fast-csv/format-js-examples
9 |
10 | # [5.0.0](https://github.com/C2FO/fast-csv/compare/v4.3.6...v5.0.0) (2024-01-13)
11 |
12 | **Note:** Version bump only for package @fast-csv/format-js-examples
13 |
14 | ## [4.3.6](https://github.com/C2FO/fast-csv/compare/v4.3.5...v4.3.6) (2020-12-04)
15 |
16 | **Note:** Version bump only for package @fast-csv/format-js-examples
17 |
18 | ## [4.3.5](https://github.com/C2FO/fast-csv/compare/v4.3.4...v4.3.5) (2020-11-03)
19 |
20 | **Note:** Version bump only for package @fast-csv/format-js-examples
21 |
22 | ## [4.3.4](https://github.com/C2FO/fast-csv/compare/v4.3.3...v4.3.4) (2020-11-03)
23 |
24 | **Note:** Version bump only for package @fast-csv/format-js-examples
25 |
26 | ## [4.3.3](https://github.com/C2FO/fast-csv/compare/v4.3.2...v4.3.3) (2020-10-30)
27 |
28 | **Note:** Version bump only for package @fast-csv/format-js-examples
29 |
30 | ## [4.3.2](https://github.com/C2FO/fast-csv/compare/v4.3.1...v4.3.2) (2020-09-02)
31 |
32 | **Note:** Version bump only for package @fast-csv/format-js-examples
33 |
34 | ## [4.3.1](https://github.com/C2FO/fast-csv/compare/v4.3.0...v4.3.1) (2020-06-23)
35 |
36 | **Note:** Version bump only for package @fast-csv/format-js-examples
37 |
38 | # [4.3.0](https://github.com/C2FO/fast-csv/compare/v4.2.0...v4.3.0) (2020-05-27)
39 |
40 | **Note:** Version bump only for package @fast-csv/format-js-examples
41 |
42 | # [4.2.0](https://github.com/C2FO/fast-csv/compare/v4.1.6...v4.2.0) (2020-05-19)
43 |
44 | **Note:** Version bump only for package @fast-csv/format-js-examples
45 |
46 | ## [4.1.5](https://github.com/C2FO/fast-csv/compare/v4.1.4...v4.1.5) (2020-05-15)
47 |
48 | **Note:** Version bump only for package @fast-csv/format-js-examples
49 |
50 | ## [4.1.4](https://github.com/C2FO/fast-csv/compare/v4.1.3...v4.1.4) (2020-05-15)
51 |
52 | **Note:** Version bump only for package @fast-csv/format-js-examples
53 |
--------------------------------------------------------------------------------
/examples/formatting-js/README.md:
--------------------------------------------------------------------------------
1 | `@fast-csv/format` javascript formatting examples.
2 |
3 | ## Usage
4 |
5 | To run all examples
6 |
7 | ```sh
8 | npm run all-examples
9 | ```
10 |
11 | To see a list of all available examples
12 |
13 | ```sh
14 | npm run list
15 | ```
16 |
17 | To run a specific example
18 |
19 | ```sh
20 | npm run example -- {example_name}
21 | ```
22 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/delimiter_option.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const stream = csv.format({ delimiter: '\t' });
4 | stream.pipe(process.stdout);
5 |
6 | stream.write(['a', 'b']);
7 | stream.write(['a1', 'b1']);
8 | stream.write(['a2', 'b2']);
9 | stream.end();
10 |
11 | // Output:
12 | // a b
13 | // a1 b1
14 | // a2 b2
15 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/escape_option.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const stream = csv.format({ escape: "'" });
4 | stream.pipe(process.stdout);
5 |
6 | // wrap each field in a quote so it is escaped and quoted
7 | stream.write(['"a"', '"b"']);
8 | stream.write(['"a1"', '"b1"']);
9 | stream.write(['"a2"', '"b2"']);
10 | stream.end();
11 |
12 | // Output:
13 | // "'"a'"","'"b'""
14 | // "'"a1'"","'"b1'""
15 | // "'"a2'"","'"b2'""
16 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/format.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const stream = csv.format();
4 | stream.pipe(process.stdout);
5 |
6 | stream.write(['a', 'b']);
7 | stream.write(['a1', 'b1']);
8 | stream.write(['a2', 'b2']);
9 | stream.end();
10 |
11 | // Output:
12 | // a,b
13 | // a1,b1
14 | // a2,b2
15 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/hash_array.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: true });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write([
8 | ['header', 'value1a'],
9 | ['header2', 'value2a'],
10 | ]);
11 | csvStream.write([
12 | ['header', 'value1b'],
13 | ['header2', 'value2b'],
14 | ]);
15 | csvStream.write([
16 | ['header', 'value1c'],
17 | ['header2', 'value2c'],
18 | ]);
19 | csvStream.write([
20 | ['header', 'value1d'],
21 | ['header2', 'value2d'],
22 | ]);
23 | csvStream.end();
24 |
25 | // Output:
26 | // header,header2
27 | // value1a,value2a
28 | // value1b,value2b
29 | // value1c,value2c
30 | // value1d,value2d
31 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/headers_auto_discovery_hash_array.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: true });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write([
8 | ['header1', 'value1a'],
9 | ['header2', 'value1b'],
10 | ]);
11 | csvStream.write([
12 | ['header1', 'value2a'],
13 | ['header2', 'value2b'],
14 | ]);
15 | csvStream.write([
16 | ['header1', 'value3a'],
17 | ['header2', 'value3b'],
18 | ]);
19 | csvStream.write([
20 | ['header1', 'value4a'],
21 | ['header2', 'value4b'],
22 | ]);
23 | csvStream.end();
24 |
25 | // Output:
26 | // header1,header2
27 | // value1a,value1b
28 | // value2a,value2b
29 | // value3a,value3b
30 | // value4a,value4b
31 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/headers_auto_discovery_object.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: true });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write({ header1: 'value1a', header2: 'value1b' });
8 | csvStream.write({ header1: 'value2a', header2: 'value2b' });
9 | csvStream.write({ header1: 'value3a', header2: 'value3b' });
10 | csvStream.write({ header1: 'value4a', header2: 'value4b' });
11 | csvStream.end();
12 |
13 | // Output:
14 | // header1,header2
15 | // value1a,value1b
16 | // value2a,value2b
17 | // value3a,value3b
18 | // value4a,value4b
19 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/headers_provided_array.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: ['header1', 'header2'] });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write(['value1a', 'value1b']);
8 | csvStream.write(['value2a', 'value2b']);
9 | csvStream.write(['value3a', 'value3b']);
10 | csvStream.write(['value4a', 'value4b']);
11 | csvStream.end();
12 |
13 | // Output:
14 | // header1,header2
15 | // value1a,value1b
16 | // value2a,value2b
17 | // value3a,value3b
18 | // value4a,value4b
19 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/headers_provided_hash_array.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: ['header1', 'header2'] });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write([
8 | ['h1', 'value1a'],
9 | ['h2', 'value1b'],
10 | ]);
11 | csvStream.write([
12 | ['h1', 'value2a'],
13 | ['h2', 'value2b'],
14 | ]);
15 | csvStream.write([
16 | ['h1', 'value3a'],
17 | ['h2', 'value3b'],
18 | ]);
19 | csvStream.write([
20 | ['h1', 'value4a'],
21 | ['h2', 'value4b'],
22 | ]);
23 | csvStream.end();
24 |
25 | // Output:
26 | // header1,header2
27 | // value1a,value1b
28 | // value2a,value2b
29 | // value3a,value3b
30 | // value4a,value4b
31 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/headers_provided_object.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: ['header2', 'header1'] });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write({ header1: 'value1a', header2: 'value1b' });
8 | csvStream.write({ header1: 'value2a', header2: 'value2b' });
9 | csvStream.write({ header1: 'value3a', header2: 'value3b' });
10 | csvStream.write({ header1: 'value4a', header2: 'value4b' });
11 | csvStream.end();
12 |
13 | // Output:
14 | // header2,header1
15 | // value1b,value1a
16 | // value2b,value2a
17 | // value3b,value3a
18 | // value4b,value4a
19 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/headers_provided_object_remove_column.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: ['header2'] });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write({ header1: 'value1a', header2: 'value1b' });
8 | csvStream.write({ header1: 'value2a', header2: 'value2b' });
9 | csvStream.write({ header1: 'value3a', header2: 'value3b' });
10 | csvStream.write({ header1: 'value4a', header2: 'value4b' });
11 | csvStream.end();
12 |
13 | // Output:
14 | // header2
15 | // value1b
16 | // value2b
17 | // value3b
18 | // value4b
19 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/quote_all_columns.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: true, quoteColumns: true });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
8 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.end();
12 |
13 | // Output:
14 | // "header1","header2"
15 | // "value1a","value2a"
16 | // "value1a","value2a"
17 | // "value1a","value2a"
18 | // "value1a","value2a"
19 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/quote_all_headers.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: true, quoteHeaders: true });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
8 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.end();
12 |
13 | // Output:
14 | // "header1","header2"
15 | // value1a,value2a
16 | // value1a,value2a
17 | // value1a,value2a
18 | // value1a,value2a
19 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/quote_columns_array.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: ['header1', 'header2'], quoteColumns: [false, true] });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
8 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.end();
12 |
13 | // Output:
14 | // header1,"header2"
15 | // value1a,"value2a"
16 | // value1a,"value2a"
17 | // value1a,"value2a"
18 | // value1a,"value2a"
19 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/quote_columns_not_headers.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: true, quoteColumns: { header2: true }, quoteHeaders: false });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
8 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.end();
12 |
13 | // Output:
14 | // header1,header2
15 | // value1a,"value2a"
16 | // value1a,"value2a"
17 | // value1a,"value2a"
18 | // value1a,"value2a"
19 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/quote_columns_object.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: true, quoteColumns: { header2: true } });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
8 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.end();
12 |
13 | // Output:
14 | // header1,"header2"
15 | // value1a,"value2a"
16 | // value1a,"value2a"
17 | // value1a,"value2a"
18 | // value1a,"value2a"
19 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/quote_headers_array.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: ['header1', 'header2'], quoteHeaders: [false, true] });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
8 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.end();
12 |
13 | // Output:
14 | // header1,"header2"
15 | // value1a,value2a
16 | // value1a,value2a
17 | // value1a,value2a
18 | // value1a,value2a
19 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/quote_headers_object.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: true, quoteHeaders: { header2: true } });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
8 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.end();
12 |
13 | // Output:
14 | // header1,"header2"
15 | // value1a,value2a
16 | // value1a,value2a
17 | // value1a,value2a
18 | // value1a,value2a
19 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/quote_option.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const stream = csv.format({ quote: "'" });
4 | stream.pipe(process.stdout);
5 |
6 | // each field will be quoted because it contains a delimiter
7 | stream.write(['a,a', 'b,b']);
8 | stream.write(['a1,a1', 'b1,b1']);
9 | stream.write(['a2,a2', 'b2,b2']);
10 | stream.end();
11 |
12 | // Output:
13 | // 'a,a','b,b'
14 | // 'a1,a1','b1,b1'
15 | // 'a2,a2','b2,b2'
16 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/quote_some_columns_and_headers.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({
4 | headers: true,
5 | quoteColumns: { header1: true },
6 | quoteHeaders: { header2: true },
7 | });
8 |
9 | csvStream.pipe(process.stdout).on('end', () => process.exit());
10 |
11 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
12 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
13 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
14 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
15 | csvStream.end();
16 |
17 | // Output:
18 | // header1,"header2"
19 | // "value1a",value2a
20 | // "value1a",value2a
21 | // "value1a",value2a
22 | // "value1a",value2a
23 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/row_delimiter_option.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const stream = csv.format({ rowDelimiter: '||' });
4 | stream.pipe(process.stdout);
5 |
6 | stream.write(['a', 'b']);
7 | stream.write(['a1', 'b1']);
8 | stream.write(['a2', 'b2']);
9 | stream.end();
10 |
11 | // Output:
12 | // a,b||a1,b1||a2,b2
13 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/transform.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: true }).transform((row) => ({
4 | header1: row.header1.toUpperCase(),
5 | header2: row.header2.toUpperCase(),
6 | }));
7 |
8 | csvStream.pipe(process.stdout).on('end', () => process.exit());
9 |
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
12 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
13 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
14 | csvStream.end();
15 |
16 | // Output:
17 | // header1,header2
18 | // VALUE1A,VALUE2A
19 | // VALUE1A,VALUE2A
20 | // VALUE1A,VALUE2A
21 | // VALUE1A,VALUE2A
22 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/transform_async.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: true }).transform((row, cb) => {
4 | setImmediate(() =>
5 | cb(null, {
6 | header1: row.header1.toUpperCase(),
7 | header2: row.header2.toUpperCase(),
8 | }),
9 | );
10 | });
11 |
12 | csvStream.pipe(process.stdout).on('end', () => process.exit());
13 |
14 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
15 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
16 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
17 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
18 | csvStream.end();
19 |
20 | // Output:
21 | // header1,header2
22 | // VALUE1A,VALUE2A
23 | // VALUE1A,VALUE2A
24 | // VALUE1A,VALUE2A
25 | // VALUE1A,VALUE2A
26 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/transform_option.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const transform = (row) => ({
4 | header1: row.header1.toUpperCase(),
5 | header2: row.header2.toUpperCase(),
6 | });
7 |
8 | const csvStream = csv.format({ headers: true, transform });
9 |
10 | csvStream.pipe(process.stdout).on('end', () => process.exit());
11 |
12 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
13 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
14 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
15 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
16 | csvStream.end();
17 |
18 | // Output:
19 | // header1,header2
20 | // VALUE1A,VALUE2A
21 | // VALUE1A,VALUE2A
22 | // VALUE1A,VALUE2A
23 | // VALUE1A,VALUE2A
24 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/write.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const rows = [
4 | ['a', 'b'],
5 | ['a1', 'b1'],
6 | ['a2', 'b2'],
7 | ];
8 | csv.write(rows).pipe(process.stdout);
9 |
10 | // Output:
11 | // a,b
12 | // a1,b1
13 | // a2,b2
14 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/write_headers_auto_discover.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: true, writeHeaders: false });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
8 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.end();
12 |
13 | // Output:
14 | // value1a,value2a
15 | // value1a,value2a
16 | // value1a,value2a
17 | // value1a,value2a
18 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/write_headers_provided_headers.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const csvStream = csv.format({ headers: ['header2', 'header1'], writeHeaders: false });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => process.exit());
6 |
7 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
8 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.end();
12 |
13 | // Output:
14 | // value2a,value1a
15 | // value2a,value1a
16 | // value2a,value1a
17 | // value2a,value1a
18 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/write_to_buffer.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const rows = [
4 | ['a', 'b'],
5 | ['a1', 'b1'],
6 | ['a2', 'b2'],
7 | ];
8 | csv.writeToBuffer(rows)
9 | .then((data) => console.log(data.toString()))
10 | .catch((e) => console.error(e));
11 |
12 | // Output:
13 | // a,b
14 | // a1,b1
15 | // a2,b2
16 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/write_to_path.example.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const path = require('path');
3 | const csv = require('@fast-csv/format');
4 |
5 | const rows = [
6 | ['a', 'b'],
7 | ['a1', 'b1'],
8 | ['a2', 'b2'],
9 | ];
10 | const filePath = path.resolve(__dirname, 'write_to_path.tmp.csv');
11 | csv.writeToPath(filePath, rows)
12 | .on('error', (err) => console.error(err))
13 | .on('finish', () => {
14 | console.log('File Contents:');
15 | console.log(fs.readFileSync(filePath).toString());
16 | });
17 |
18 | // Output:
19 | // File Contents:
20 | // a,b
21 | // a1,b1
22 | // a2,b2
23 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/write_to_stream.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const rows = [
4 | ['a', 'b'],
5 | ['a1', 'b1'],
6 | ['a2', 'b2'],
7 | ];
8 | csv.writeToStream(process.stdout, rows);
9 |
10 | // Output:
11 | // a,b
12 | // a1,b1
13 | // a2,b2
14 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/write_to_string.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const rows = [
4 | ['a', 'b'],
5 | ['a1', 'b1'],
6 | ['a2', 'b2'],
7 | ];
8 | csv.writeToString(rows)
9 | .then((data) => console.log(data))
10 | .catch((e) => console.error(e));
11 |
12 | // Output:
13 | // a,b
14 | // a1,b1
15 | // a2,b2
16 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/write_to_string_no_headers.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const data = [
4 | { a: 'a1', b: 'b1' },
5 | { a: 'a2', b: 'b2' },
6 | ];
7 | csv.writeToString(data, { headers: false })
8 | .then((formattedCsv) => {
9 | console.log(formattedCsv);
10 | process.exit();
11 | })
12 | .catch((err) => {
13 | console.error(err.stack);
14 | process.exit(1);
15 | });
16 |
17 | // Output:
18 | // a1,b1
19 | // a2,b2
20 |
--------------------------------------------------------------------------------
/examples/formatting-js/examples/write_to_string_transform.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/format');
2 |
3 | const data = [
4 | { a: 'a1', b: 'b1' },
5 | { a: 'a2', b: 'b2' },
6 | ];
7 |
8 | const transform = (row) => ({
9 | A: row.a,
10 | B: row.b,
11 | });
12 |
13 | csv.writeToString(data, { headers: true, transform })
14 | .then((formattedCsv) => console.log(formattedCsv))
15 | .catch((err) => console.error(err.stack));
16 |
17 | // Output:
18 | // A,B
19 | // a1,b1
20 | // a2,b2
21 |
--------------------------------------------------------------------------------
/examples/formatting-js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fast-csv/format-js-examples",
3 | "version": "5.0.2",
4 | "private": true,
5 | "description": "fast-csv formatting examples",
6 | "scripts": {
7 | "list": "run-examples list",
8 | "all-examples": "run-examples all",
9 | "example": "run-examples run"
10 | },
11 | "dependencies": {
12 | "@fast-csv/format": "5.0.2",
13 | "example-runner": "5.0.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/formatting-ts/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | rules: {
3 | 'no-console': 0,
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/examples/formatting-ts/README.md:
--------------------------------------------------------------------------------
1 | `@fast-csv/format` typescript formatting examples.
2 |
3 | ## Usage
4 |
5 | ```sh
6 | npm run build
7 | ```
8 |
9 | To run all examples
10 |
11 | ```sh
12 | npm run all-examples
13 | ```
14 |
15 | To see a list of all available examples
16 |
17 | ```sh
18 | npm run list
19 | ```
20 |
21 | To run a specific example
22 |
23 | ```sh
24 | npm run example -- {example_name}
25 | ```
26 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/delimiter_option.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const stream = format({ delimiter: '\t' });
4 | stream.pipe(process.stdout);
5 |
6 | stream.write(['a', 'b']);
7 | stream.write(['a1', 'b1']);
8 | stream.write(['a2', 'b2']);
9 | stream.end();
10 |
11 | // Output:
12 | // a b
13 | // a1 b1
14 | // a2 b2
15 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/escape_option.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const stream = format({ escape: "'" });
4 | stream.pipe(process.stdout);
5 |
6 | // wrap each field in a quote so it is escaped and quoted
7 | stream.write(['"a"', '"b"']);
8 | stream.write(['"a1"', '"b1"']);
9 | stream.write(['"a2"', '"b2"']);
10 | stream.end();
11 |
12 | // Output:
13 | // "'"a'"","'"b'""
14 | // "'"a1'"","'"b1'""
15 | // "'"a2'"","'"b2'""
16 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/format.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const stream = format();
4 | stream.pipe(process.stdout);
5 |
6 | stream.write(['a', 'b']);
7 | stream.write(['a1', 'b1']);
8 | stream.write(['a2', 'b2']);
9 | stream.end();
10 |
11 | // Output:
12 | // a,b
13 | // a1,b1
14 | // a2,b2
15 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/hash_array.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: true });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write([
10 | ['header', 'value1a'],
11 | ['header2', 'value2a'],
12 | ]);
13 | csvStream.write([
14 | ['header', 'value1b'],
15 | ['header2', 'value2b'],
16 | ]);
17 | csvStream.write([
18 | ['header', 'value1c'],
19 | ['header2', 'value2c'],
20 | ]);
21 | csvStream.write([
22 | ['header', 'value1d'],
23 | ['header2', 'value2d'],
24 | ]);
25 | csvStream.end();
26 |
27 | // Output:
28 | // header,header2
29 | // value1a,value2a
30 | // value1b,value2b
31 | // value1c,value2c
32 | // value1d,value2d
33 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/headers_auto_discovery_hash_array.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: true });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write([
10 | ['header1', 'value1a'],
11 | ['header2', 'value1b'],
12 | ]);
13 | csvStream.write([
14 | ['header1', 'value2a'],
15 | ['header2', 'value2b'],
16 | ]);
17 | csvStream.write([
18 | ['header1', 'value3a'],
19 | ['header2', 'value3b'],
20 | ]);
21 | csvStream.write([
22 | ['header1', 'value4a'],
23 | ['header2', 'value4b'],
24 | ]);
25 | csvStream.end();
26 |
27 | // Output:
28 | // header1,header2
29 | // value1a,value1b
30 | // value2a,value2b
31 | // value3a,value3b
32 | // value4a,value4b
33 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/headers_auto_discovery_object.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: true });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write({ header1: 'value1a', header2: 'value1b' });
10 | csvStream.write({ header1: 'value2a', header2: 'value2b' });
11 | csvStream.write({ header1: 'value3a', header2: 'value3b' });
12 | csvStream.write({ header1: 'value4a', header2: 'value4b' });
13 | csvStream.end();
14 |
15 | // Output:
16 | // header1,header2
17 | // value1a,value1b
18 | // value2a,value2b
19 | // value3a,value3b
20 | // value4a,value4b
21 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/headers_provided_array.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: ['header1', 'header2'] });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write(['value1a', 'value1b']);
10 | csvStream.write(['value2a', 'value2b']);
11 | csvStream.write(['value3a', 'value3b']);
12 | csvStream.write(['value4a', 'value4b']);
13 | csvStream.end();
14 |
15 | // Output:
16 | // header1,header2
17 | // value1a,value1b
18 | // value2a,value2b
19 | // value3a,value3b
20 | // value4a,value4b
21 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/headers_provided_hash_array.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: ['header1', 'header2'] });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write([
10 | ['h1', 'value1a'],
11 | ['h2', 'value1b'],
12 | ]);
13 | csvStream.write([
14 | ['h1', 'value2a'],
15 | ['h2', 'value2b'],
16 | ]);
17 | csvStream.write([
18 | ['h1', 'value3a'],
19 | ['h2', 'value3b'],
20 | ]);
21 | csvStream.write([
22 | ['h1', 'value4a'],
23 | ['h2', 'value4b'],
24 | ]);
25 | csvStream.end();
26 |
27 | // Output:
28 | // header1,header2
29 | // value1a,value1b
30 | // value2a,value2b
31 | // value3a,value3b
32 | // value4a,value4b
33 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/headers_provided_object.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: ['header2', 'header1'] });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write({ header1: 'value1a', header2: 'value1b' });
10 | csvStream.write({ header1: 'value2a', header2: 'value2b' });
11 | csvStream.write({ header1: 'value3a', header2: 'value3b' });
12 | csvStream.write({ header1: 'value4a', header2: 'value4b' });
13 | csvStream.end();
14 |
15 | // Output:
16 | // header2,header1
17 | // value1b,value1a
18 | // value2b,value2a
19 | // value3b,value3a
20 | // value4b,value4a
21 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/headers_provided_object_remove_column.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: ['header2'] });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write({ header1: 'value1a', header2: 'value1b' });
10 | csvStream.write({ header1: 'value2a', header2: 'value2b' });
11 | csvStream.write({ header1: 'value3a', header2: 'value3b' });
12 | csvStream.write({ header1: 'value4a', header2: 'value4b' });
13 | csvStream.end();
14 |
15 | // Output:
16 | // header2
17 | // value1b
18 | // value2b
19 | // value3b
20 | // value4b
21 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/quote_all_columns.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: true, quoteColumns: true });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
12 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
13 | csvStream.end();
14 |
15 | // Output:
16 | // "header1","header2"
17 | // "value1a","value2a"
18 | // "value1a","value2a"
19 | // "value1a","value2a"
20 | // "value1a","value2a"
21 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/quote_all_headers.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: true, quoteHeaders: true });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
12 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
13 | csvStream.end();
14 |
15 | // Output:
16 | // "header1","header2"
17 | // value1a,value2a
18 | // value1a,value2a
19 | // value1a,value2a
20 | // value1a,value2a
21 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/quote_columns_array.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: ['header1', 'header2'], quoteColumns: [false, true] });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
12 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
13 | csvStream.end();
14 |
15 | // Output:
16 | // header1,"header2"
17 | // value1a,"value2a"
18 | // value1a,"value2a"
19 | // value1a,"value2a"
20 | // value1a,"value2a"
21 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/quote_columns_not_headers.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: true, quoteColumns: { header2: true }, quoteHeaders: false });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
12 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
13 | csvStream.end();
14 |
15 | // Output:
16 | // header1,header2
17 | // value1a,"value2a"
18 | // value1a,"value2a"
19 | // value1a,"value2a"
20 | // value1a,"value2a"
21 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/quote_columns_object.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: true, quoteColumns: { header2: true } });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
12 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
13 | csvStream.end();
14 |
15 | // Output:
16 | // header1,"header2"
17 | // value1a,"value2a"
18 | // value1a,"value2a"
19 | // value1a,"value2a"
20 | // value1a,"value2a"
21 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/quote_headers_array.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: ['header1', 'header2'], quoteHeaders: [false, true] });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
12 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
13 | csvStream.end();
14 |
15 | // Output:
16 | // header1,"header2"
17 | // value1a,value2a
18 | // value1a,value2a
19 | // value1a,value2a
20 | // value1a,value2a
21 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/quote_headers_object.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: true, quoteHeaders: { header2: true } });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
12 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
13 | csvStream.end();
14 |
15 | // Output:
16 | // header1,"header2"
17 | // value1a,value2a
18 | // value1a,value2a
19 | // value1a,value2a
20 | // value1a,value2a
21 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/quote_option.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const stream = format({ quote: "'" });
4 | stream.pipe(process.stdout);
5 |
6 | // each field will be quoted because it contains a delimiter
7 | stream.write(['a,a', 'b,b']);
8 | stream.write(['a1,a1', 'b1,b1']);
9 | stream.write(['a2,a2', 'b2,b2']);
10 | stream.end();
11 |
12 | // Output:
13 | // 'a,a','b,b'
14 | // 'a1,a1','b1,b1'
15 | // 'a2,a2','b2,b2'
16 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/quote_some_columns_and_headers.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({
4 | headers: true,
5 | quoteColumns: { header1: true },
6 | quoteHeaders: { header2: true },
7 | });
8 |
9 | csvStream.pipe(process.stdout).on('end', () => {
10 | return process.exit();
11 | });
12 |
13 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
14 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
15 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
16 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
17 | csvStream.end();
18 |
19 | // Output:
20 | // header1,"header2"
21 | // "value1a",value2a
22 | // "value1a",value2a
23 | // "value1a",value2a
24 | // "value1a",value2a
25 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/row_delimiter_option.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const stream = format({ rowDelimiter: '||' });
4 | stream.pipe(process.stdout);
5 |
6 | stream.write(['a', 'b']);
7 | stream.write(['a1', 'b1']);
8 | stream.write(['a2', 'b2']);
9 | stream.end();
10 |
11 | // Output:
12 | // a,b||a1,b1||a2,b2
13 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/transform.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | interface CsvRow {
4 | header1: string;
5 | header2: string;
6 | }
7 |
8 | const csvStream = format({ headers: true }).transform((row: CsvRow) => {
9 | return {
10 | header1: row.header1.toUpperCase(),
11 | header2: row.header2.toUpperCase(),
12 | };
13 | });
14 |
15 | csvStream.pipe(process.stdout).on('end', () => {
16 | return process.exit();
17 | });
18 |
19 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
20 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
21 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
22 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
23 | csvStream.end();
24 |
25 | // Output:
26 | // header1,header2
27 | // VALUE1A,VALUE2A
28 | // VALUE1A,VALUE2A
29 | // VALUE1A,VALUE2A
30 | // VALUE1A,VALUE2A
31 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/transform_async.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | interface CsvRow {
4 | header1: string;
5 | header2: string;
6 | }
7 |
8 | const csvStream = format({ headers: true }).transform((row, cb) => {
9 | setImmediate(() => {
10 | return cb(null, {
11 | header1: row.header1.toUpperCase(),
12 | header2: row.header2.toUpperCase(),
13 | });
14 | });
15 | });
16 |
17 | csvStream.pipe(process.stdout).on('end', () => {
18 | return process.exit();
19 | });
20 |
21 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
22 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
23 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
24 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
25 | csvStream.end();
26 |
27 | // Output:
28 | // header1,header2
29 | // VALUE1A,VALUE2A
30 | // VALUE1A,VALUE2A
31 | // VALUE1A,VALUE2A
32 | // VALUE1A,VALUE2A
33 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/transform_option.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | interface CsvRow {
4 | header1: string;
5 | header2: string;
6 | }
7 |
8 | const transform = (row: CsvRow): CsvRow => {
9 | return {
10 | header1: row.header1.toUpperCase(),
11 | header2: row.header2.toUpperCase(),
12 | };
13 | };
14 |
15 | const csvStream = format({ headers: true, transform });
16 |
17 | csvStream.pipe(process.stdout).on('end', () => {
18 | return process.exit();
19 | });
20 |
21 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
22 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
23 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
24 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
25 | csvStream.end();
26 |
27 | // Output:
28 | // header1,header2
29 | // VALUE1A,VALUE2A
30 | // VALUE1A,VALUE2A
31 | // VALUE1A,VALUE2A
32 | // VALUE1A,VALUE2A
33 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/write.example.ts:
--------------------------------------------------------------------------------
1 | import { write } from '@fast-csv/format';
2 |
3 | const rows = [
4 | ['a', 'b'],
5 | ['a1', 'b1'],
6 | ['a2', 'b2'],
7 | ];
8 | write(rows).pipe(process.stdout);
9 |
10 | // Output:
11 | // a,b
12 | // a1,b1
13 | // a2,b2
14 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/write_headers_auto_discover.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: true, writeHeaders: false });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
12 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
13 | csvStream.end();
14 |
15 | // Output:
16 | // value1a,value2a
17 | // value1a,value2a
18 | // value1a,value2a
19 | // value1a,value2a
20 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/write_headers_provided_headers.example.ts:
--------------------------------------------------------------------------------
1 | import { format } from '@fast-csv/format';
2 |
3 | const csvStream = format({ headers: ['header2', 'header1'], writeHeaders: false });
4 |
5 | csvStream.pipe(process.stdout).on('end', () => {
6 | return process.exit();
7 | });
8 |
9 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
10 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
11 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
12 | csvStream.write({ header1: 'value1a', header2: 'value2a' });
13 | csvStream.end();
14 |
15 | // Output:
16 | // value2a,value1a
17 | // value2a,value1a
18 | // value2a,value1a
19 | // value2a,value1a
20 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/write_to_buffer.example.ts:
--------------------------------------------------------------------------------
1 | import { writeToBuffer } from '@fast-csv/format';
2 |
3 | const rows = [
4 | ['a', 'b'],
5 | ['a1', 'b1'],
6 | ['a2', 'b2'],
7 | ];
8 | writeToBuffer(rows)
9 | .then((data) => {
10 | return console.log(data.toString());
11 | })
12 | .catch((err: Error) => {
13 | return console.error(err.stack);
14 | });
15 |
16 | // Output:
17 | // a,b
18 | // a1,b1
19 | // a2,b2
20 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/write_to_path.example.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import { readFileSync } from 'fs';
3 | import { writeToPath } from '@fast-csv/format';
4 |
5 | const rows = [
6 | ['a', 'b'],
7 | ['a1', 'b1'],
8 | ['a2', 'b2'],
9 | ];
10 | const filePath = resolve(__dirname, 'write_to_path.tmp.csv');
11 | writeToPath(filePath, rows)
12 | .on('error', (err) => {
13 | return console.error(err);
14 | })
15 | .on('finish', () => {
16 | console.log('File Contents:');
17 | console.log(readFileSync(filePath).toString());
18 | });
19 |
20 | // Output:
21 | // File Contents:
22 | // a,b
23 | // a1,b1
24 | // a2,b2
25 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/write_to_stream.example.ts:
--------------------------------------------------------------------------------
1 | import { writeToStream } from '@fast-csv/format';
2 |
3 | const rows = [
4 | ['a', 'b'],
5 | ['a1', 'b1'],
6 | ['a2', 'b2'],
7 | ];
8 | writeToStream(process.stdout, rows);
9 |
10 | // Output:
11 | // a,b
12 | // a1,b1
13 | // a2,b2
14 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/write_to_string.example.ts:
--------------------------------------------------------------------------------
1 | import { writeToString } from '@fast-csv/format';
2 |
3 | const rows = [
4 | ['a', 'b'],
5 | ['a1', 'b1'],
6 | ['a2', 'b2'],
7 | ];
8 | writeToString(rows)
9 | .then((data) => {
10 | return console.log(data);
11 | })
12 | .catch((err: Error) => {
13 | return console.error(err.stack);
14 | });
15 |
16 | // Output:
17 | // a,b
18 | // a1,b1
19 | // a2,b2
20 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/write_to_string_no_headers.example.ts:
--------------------------------------------------------------------------------
1 | import { writeToString } from '@fast-csv/format';
2 |
3 | const data = [
4 | { a: 'a1', b: 'b1' },
5 | { a: 'a2', b: 'b2' },
6 | ];
7 | writeToString(data, { headers: false })
8 | .then((formattedCsv) => {
9 | return console.log(formattedCsv);
10 | })
11 | .catch((err: Error) => {
12 | return console.error(err.stack);
13 | });
14 |
15 | // Output:
16 | // a1,b1
17 | // a2,b2
18 |
--------------------------------------------------------------------------------
/examples/formatting-ts/examples/write_to_string_transform.example.ts:
--------------------------------------------------------------------------------
1 | import { RowMap, writeToString } from '@fast-csv/format';
2 |
3 | const data = [
4 | { a: 'a1', b: 'b1' },
5 | { a: 'a2', b: 'b2' },
6 | ];
7 |
8 | const transform = (row: RowMap): RowMap => {
9 | return {
10 | A: row.a,
11 | B: row.b,
12 | };
13 | };
14 |
15 | writeToString(data, { headers: true, transform })
16 | .then((formattedCsv) => {
17 | return console.log(formattedCsv);
18 | })
19 | .catch((err: Error) => {
20 | return console.error(err.stack);
21 | });
22 |
23 | // Output:
24 | // A,B
25 | // a1,b1
26 | // a2,b2
27 |
--------------------------------------------------------------------------------
/examples/formatting-ts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fast-csv/formatting-ts-examples",
3 | "version": "5.0.2",
4 | "private": true,
5 | "description": "fast-csv formatting typescript examples",
6 | "scripts": {
7 | "list": "run-examples --dir=build list",
8 | "all-examples": "run-examples --dir=build all",
9 | "example": "run-examples --dir=build run",
10 | "build": "npm run clean && npm run compile",
11 | "clean": "rm -rf ./build && rm -rf tsconfig.tsbuildinfo",
12 | "compile": "tsc"
13 | },
14 | "dependencies": {
15 | "@fast-csv/format": "5.0.2",
16 | "example-runner": "5.0.0",
17 | "typescript": "5.6.3"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/formatting-ts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.build.json",
3 | "compilerOptions": {
4 | "outDir": "./build",
5 | "rootDir": "./examples"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/examples/js.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true,
5 | },
6 | parser: 'esprima',
7 | parserOptions: {
8 | sourceType: 'module',
9 | project: null,
10 | },
11 | plugins: ['prettier', 'import', 'jest'],
12 | extends: ['airbnb-base', 'eslint:recommended', 'prettier'],
13 | ignorePatterns: ['**/build', '**/node_modules', 'documentation', '.eslintrc.js'],
14 | rules: {
15 | 'prettier/prettier': 'error',
16 | 'no-console': 0,
17 | },
18 | };
19 |
--------------------------------------------------------------------------------
/examples/parsing-js/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | rules: {
3 | 'no-console': 0,
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/examples/parsing-js/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [5.0.2](https://github.com/C2FO/fast-csv/compare/v5.0.1...v5.0.2) (2024-10-22)
7 |
8 | **Note:** Version bump only for package @fast-csv/parse-js-examples
9 |
10 | # [5.0.0](https://github.com/C2FO/fast-csv/compare/v4.3.6...v5.0.0) (2024-01-13)
11 |
12 | **Note:** Version bump only for package @fast-csv/parse-js-examples
13 |
14 | ## [4.3.6](https://github.com/C2FO/fast-csv/compare/v4.3.5...v4.3.6) (2020-12-04)
15 |
16 | **Note:** Version bump only for package @fast-csv/parse-js-examples
17 |
18 | ## [4.3.4](https://github.com/C2FO/fast-csv/compare/v4.3.3...v4.3.4) (2020-11-03)
19 |
20 | **Note:** Version bump only for package @fast-csv/parse-js-examples
21 |
22 | ## [4.3.3](https://github.com/C2FO/fast-csv/compare/v4.3.2...v4.3.3) (2020-10-30)
23 |
24 | **Note:** Version bump only for package @fast-csv/parse-js-examples
25 |
26 | ## [4.3.2](https://github.com/C2FO/fast-csv/compare/v4.3.1...v4.3.2) (2020-09-02)
27 |
28 | **Note:** Version bump only for package @fast-csv/parse-js-examples
29 |
30 | ## [4.3.1](https://github.com/C2FO/fast-csv/compare/v4.3.0...v4.3.1) (2020-06-23)
31 |
32 | **Note:** Version bump only for package @fast-csv/parse-js-examples
33 |
34 | # [4.3.0](https://github.com/C2FO/fast-csv/compare/v4.2.0...v4.3.0) (2020-05-27)
35 |
36 | **Note:** Version bump only for package @fast-csv/parse-js-examples
37 |
38 | # [4.2.0](https://github.com/C2FO/fast-csv/compare/v4.1.6...v4.2.0) (2020-05-19)
39 |
40 | **Note:** Version bump only for package @fast-csv/parse-js-examples
41 |
42 | ## [4.1.6](https://github.com/C2FO/fast-csv/compare/v4.1.5...v4.1.6) (2020-05-15)
43 |
44 | **Note:** Version bump only for package @fast-csv/parse-js-examples
45 |
46 | ## [4.1.5](https://github.com/C2FO/fast-csv/compare/v4.1.4...v4.1.5) (2020-05-15)
47 |
48 | **Note:** Version bump only for package @fast-csv/parse-js-examples
49 |
50 | ## [4.1.4](https://github.com/C2FO/fast-csv/compare/v4.1.3...v4.1.4) (2020-05-15)
51 |
52 | **Note:** Version bump only for package @fast-csv/parse-js-examples
53 |
--------------------------------------------------------------------------------
/examples/parsing-js/README.md:
--------------------------------------------------------------------------------
1 | `@fast-csv/parse` javascript parsing examples.
2 |
3 | ## Usage
4 |
5 | To run all examples
6 |
7 | ```sh
8 | npm run all-examples
9 | ```
10 |
11 | To see a list of all available examples
12 |
13 | ```sh
14 | npm run list
15 | ```
16 |
17 | To run a specific example
18 |
19 | ```sh
20 | npm run example -- {example_name}
21 | ```
22 |
23 |
--------------------------------------------------------------------------------
/examples/parsing-js/assets/snake_case_users.csv:
--------------------------------------------------------------------------------
1 | id,first_name,last_name,address
2 | 1,Bob,Yukon,1111 State St. Yukon AK
3 | 2,Sally,Yukon,1111 State St. Yukon AK
4 | 3,Bobby,Yukon,1111 State St. Yukon AK
5 | 4,Jane,Yukon,1111 State St. Yukon AK
6 | 5,Dick,Yukon,1111 State St. Yukon AK
7 | 6,John,Doe,1112 State St. Yukon AK
8 | 7,Jane,Doe,1113 State St. Yukon AK
9 | 8,Billy,Doe,1112 State St. Yukon AK
10 | 9,Edith,Doe,1112 State St. Yukon AK
--------------------------------------------------------------------------------
/examples/parsing-js/examples/alternate_delimiter.example.js:
--------------------------------------------------------------------------------
1 | const { EOL } = require('os');
2 | const csv = require('@fast-csv/parse');
3 |
4 | const CSV_STRING = ['a1\tb1', 'a2\tb2'].join(EOL);
5 |
6 | const stream = csv
7 | .parse({ delimiter: '\t' })
8 | .on('error', (error) => console.error(error))
9 | .on('data', (row) => console.log(row))
10 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
11 |
12 | stream.write(CSV_STRING);
13 | stream.end();
14 |
15 | // Output:
16 | // [ 'a1', 'b1' ]
17 | // [ 'a2', 'b2' ]
18 | // Parsed 2 rows
19 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/custom_headers.example.js:
--------------------------------------------------------------------------------
1 | const { EOL } = require('os');
2 | const csv = require('@fast-csv/parse');
3 |
4 | const CSV_STRING = ['a1,b1', 'a2,b2'].join(EOL);
5 |
6 | const stream = csv
7 | .parse({ headers: ['a', 'b'] })
8 | .on('error', (error) => console.error(error))
9 | .on('data', (row) => console.log(row))
10 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
11 |
12 | stream.write(CSV_STRING);
13 | stream.end();
14 |
15 | // Output:
16 | // { a: 'a1', b: 'b1' }
17 | // { a: 'a2', b: 'b2' }
18 | // Parsed 2 rows
19 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/first_row_as_headers.example.js:
--------------------------------------------------------------------------------
1 | const { EOL } = require('os');
2 | const csv = require('@fast-csv/parse');
3 |
4 | const CSV_STRING = ['a,b', 'a1,b1', 'a2,b2'].join(EOL);
5 |
6 | const stream = csv
7 | .parse({ headers: true })
8 | .on('error', (error) => console.error(error))
9 | .on('data', (row) => console.log(row))
10 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
11 |
12 | stream.write(CSV_STRING);
13 | stream.end();
14 |
15 | // Output:
16 | // { a: 'a1', b: 'b1' }
17 | // { a: 'a2', b: 'b2' }
18 | // Parsed 2 rows
19 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/ignore_empty_rows.example.js:
--------------------------------------------------------------------------------
1 | const { EOL } = require('os');
2 | const csv = require('@fast-csv/parse');
3 |
4 | const CSV_STRING = ['a1,b1', ',', 'a2,b2', ' ,\t', ''].join(EOL);
5 |
6 | const stream = csv
7 | .parse({ ignoreEmpty: true })
8 | .on('error', (error) => console.error(error))
9 | .on('data', (row) => console.log(row))
10 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
11 |
12 | stream.write(CSV_STRING);
13 | stream.end();
14 |
15 | // Output:
16 | // [ 'a1', 'b1' ]
17 | // [ 'a2', 'b2' ]
18 | // Parsed 2 rows
19 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/manual_write.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/parse');
2 |
3 | const stream = csv
4 | .parse({ headers: true })
5 | .on('error', (error) => console.error(error))
6 | .on('data', (row) => console.log(row))
7 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
8 |
9 | stream.write('header1,header2\n');
10 | stream.write('col1,col2');
11 | stream.end();
12 |
13 | // Output:
14 | // { header1: 'col1', header2: 'col2' }
15 | // Parsed 1 rows
16 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/max_rows.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/parse');
2 |
3 | const rows = [
4 | 'header1,header2\n',
5 | 'col1,col1\n',
6 | 'col2,col2\n',
7 | 'col3,col3\n',
8 | 'col4,col4\n',
9 | 'col5,col5\n',
10 | 'col6,col6\n',
11 | 'col7,col7\n',
12 | 'col8,col8\n',
13 | 'col9,col9\n',
14 | 'col10,col10',
15 | ];
16 |
17 | const stream = csv
18 | .parse({ headers: true, maxRows: 5 })
19 | .on('error', (error) => console.error(error))
20 | .on('data', (row) => console.log(row))
21 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
22 |
23 | rows.forEach((row) => stream.write(row));
24 | stream.end();
25 |
26 | // Output:
27 | // { header1: 'col1', header2: 'col1' }
28 | // { header1: 'col2', header2: 'col2' }
29 | // { header1: 'col3', header2: 'col3' }
30 | // { header1: 'col4', header2: 'col4' }
31 | // { header1: 'col5', header2: 'col5' }
32 | // Parsed 5 rows
33 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/parse_string.example.js:
--------------------------------------------------------------------------------
1 | const { EOL } = require('os');
2 | const csv = require('@fast-csv/parse');
3 |
4 | const CSV_STRING = ['a,b', 'a1,b1', 'a2,b2'].join(EOL);
5 |
6 | csv.parseString(CSV_STRING, { headers: true })
7 | .on('error', (error) => console.error(error))
8 | .on('data', (row) => console.log(row))
9 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
10 |
11 | // Output:
12 | // { a: 'a1', b: 'b1' }
13 | // { a: 'a2', b: 'b2' }
14 | // Parsed 2 rows
15 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/pipe.example.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const path = require('path');
3 | const csv = require('@fast-csv/parse');
4 |
5 | fs.createReadStream(path.resolve(__dirname, '..', 'assets', 'snake_case_users.csv'))
6 | .pipe(csv.parse())
7 | .on('error', (error) => console.error(error))
8 | .on('data', (row) => console.log(row))
9 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
10 |
11 | // Output:
12 | // [ 'id', 'first_name', 'last_name', 'address' ]
13 | // [ '1', 'Bob', 'Yukon', '1111 State St. Yukon AK' ]
14 | // [ '2', 'Sally', 'Yukon', '1111 State St. Yukon AK' ]
15 | // [ '3', 'Bobby', 'Yukon', '1111 State St. Yukon AK' ]
16 | // [ '4', 'Jane', 'Yukon', '1111 State St. Yukon AK' ]
17 | // [ '5', 'Dick', 'Yukon', '1111 State St. Yukon AK' ]
18 | // [ '6', 'John', 'Doe', '1112 State St. Yukon AK' ]
19 | // [ '7', 'Jane', 'Doe', '1113 State St. Yukon AK' ]
20 | // [ '8', 'Billy', 'Doe', '1112 State St. Yukon AK' ]
21 | // [ '9', 'Edith', 'Doe', '1112 State St. Yukon AK' ]
22 | // Parsed 10 rows
23 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/rename_headers.example.js:
--------------------------------------------------------------------------------
1 | const { EOL } = require('os');
2 | const csv = require('@fast-csv/parse');
3 |
4 | const CSV_STRING = ['header1,header2', 'a1,b1', 'a2,b2'].join(EOL);
5 |
6 | const stream = csv
7 | .parse({ headers: ['a', 'b'], renameHeaders: true })
8 | .on('error', (error) => console.error(error))
9 | .on('data', (row) => console.log(row))
10 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
11 |
12 | stream.write(CSV_STRING);
13 | stream.end();
14 |
15 | // Output:
16 | // { a: 'a1', b: 'b1' }
17 | // { a: 'a2', b: 'b2' }
18 | // Parsed 2 rows
19 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/skip_lines.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/parse');
2 |
3 | const rows = [
4 | 'skip1_header1,skip1_header2\n',
5 | 'skip2_header1,skip2_header2\n',
6 | 'header1,header2\n',
7 | 'col1,col1\n',
8 | 'col2,col2\n',
9 | 'col3,col3\n',
10 | 'col4,col4\n',
11 | ];
12 |
13 | const stream = csv
14 | .parse({ headers: true, skipLines: 2 })
15 | .on('error', (error) => console.error(error))
16 | .on('data', (row) => console.log(row))
17 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
18 |
19 | rows.forEach((row) => stream.write(row));
20 | stream.end();
21 |
22 | // Output:
23 | // { header1: 'col1', header2: 'col1' }
24 | // { header1: 'col2', header2: 'col2' }
25 | // { header1: 'col3', header2: 'col3' }
26 | // { header1: 'col4', header2: 'col4' }
27 | // Parsed 4 rows
28 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/skip_rows.example.js:
--------------------------------------------------------------------------------
1 | const csv = require('@fast-csv/parse');
2 |
3 | const rows = [
4 | 'header1,header2\n',
5 | 'col1,col1\n',
6 | 'col2,col2\n',
7 | 'col3,col3\n',
8 | 'col4,col4\n',
9 | 'col5,col5\n',
10 | 'col6,col6\n',
11 | ];
12 |
13 | const stream = csv
14 | .parse({ headers: true, skipRows: 2 })
15 | .on('error', (error) => console.error(error))
16 | .on('data', (row) => console.log(row))
17 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
18 |
19 | rows.forEach((row) => stream.write(row));
20 | stream.end();
21 |
22 | // Output:
23 | // { header1: 'col3', header2: 'col3' }
24 | // { header1: 'col4', header2: 'col4' }
25 | // { header1: 'col5', header2: 'col5' }
26 | // { header1: 'col6', header2: 'col6' }
27 | // Parsed 4 rows
28 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/skipping_columns.example.js:
--------------------------------------------------------------------------------
1 | const { EOL } = require('os');
2 | const csv = require('@fast-csv/parse');
3 |
4 | const CSV_STRING = ['a1,b1,c1', 'a2,b2,c2'].join(EOL);
5 |
6 | const stream = csv
7 | .parse({ headers: ['a', undefined, 'c'] })
8 | .on('error', (error) => console.error(error))
9 | .on('data', (row) => console.log(row))
10 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
11 |
12 | stream.write(CSV_STRING);
13 | stream.end();
14 |
15 | // Output:
16 | // { a: 'a1', c: 'c1' }
17 | // { a: 'a2', c: 'c2' }
18 | // Parsed 2 rows
19 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/transform.example.js:
--------------------------------------------------------------------------------
1 | const { EOL } = require('os');
2 | const csv = require('@fast-csv/parse');
3 |
4 | const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL);
5 |
6 | const stream = csv
7 | .parse({ headers: true })
8 | .transform((data) => ({
9 | firstName: data.firstName.toUpperCase(),
10 | lastName: data.lastName.toUpperCase(),
11 | properName: `${data.firstName} ${data.lastName}`,
12 | }))
13 | .on('error', (error) => console.error(error))
14 | .on('data', (row) => console.log(JSON.stringify(row)))
15 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
16 |
17 | stream.write(CSV_STRING);
18 | stream.end();
19 |
20 | // Output:
21 | // {"firstName":"BOB","lastName":"YUKON","properName":"bob yukon"}
22 | // {"firstName":"SALLY","lastName":"YUKON","properName":"sally yukon"}
23 | // {"firstName":"TIMMY","lastName":"YUKON","properName":"timmy yukon"}
24 | // Parsed 3 rows
25 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/transform_async.example.js:
--------------------------------------------------------------------------------
1 | const { EOL } = require('os');
2 | const csv = require('@fast-csv/parse');
3 |
4 | const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL);
5 |
6 | const stream = csv
7 | .parse({ headers: true })
8 | .transform((data, cb) => {
9 | setImmediate(() =>
10 | cb(null, {
11 | firstName: data.firstName.toUpperCase(),
12 | lastName: data.lastName.toUpperCase(),
13 | properName: `${data.firstName} ${data.lastName}`,
14 | }),
15 | );
16 | })
17 | .on('error', (error) => console.error(error))
18 | .on('data', (row) => console.log(JSON.stringify(row)))
19 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
20 |
21 | stream.write(CSV_STRING);
22 | stream.end();
23 |
24 | // Output:
25 | // {"firstName":"BOB","lastName":"YUKON","properName":"bob yukon"}
26 | // {"firstName":"SALLY","lastName":"YUKON","properName":"sally yukon"}
27 | // {"firstName":"TIMMY","lastName":"YUKON","properName":"timmy yukon"}
28 | // Parsed 3 rows
29 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/transform_headers.example.js:
--------------------------------------------------------------------------------
1 | const { EOL } = require('os');
2 | const csv = require('@fast-csv/parse');
3 |
4 | const CSV_STRING = ['header1,header2', 'a1,b1', 'a2,b2'].join(EOL);
5 |
6 | const stream = csv
7 | .parse({
8 | headers: (headers) => headers.map((h) => h.toUpperCase()),
9 | })
10 | .on('error', (error) => console.error(error))
11 | .on('data', (row) => console.log(row))
12 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
13 |
14 | stream.write(CSV_STRING);
15 | stream.end();
16 |
17 | // Output:
18 | // { HEADER1: 'a1', HEADER2: 'b1' }
19 | // { HEADER1: 'a2', HEADER2: 'b2' }
20 | // Parsed 2 rows
21 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/validate.example.js:
--------------------------------------------------------------------------------
1 | const { EOL } = require('os');
2 | const csv = require('@fast-csv/parse');
3 |
4 | const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL);
5 |
6 | const stream = csv
7 | .parse({ headers: true })
8 | .validate((data) => data.firstName !== 'bob')
9 | .on('error', (error) => console.error(error))
10 | .on('data', (row) => console.log(`Valid [row=${JSON.stringify(row)}]`))
11 | .on('data-invalid', (row, rowNumber) =>
12 | console.log(`Invalid [rowNumber=${rowNumber}] [row=${JSON.stringify(row)}]`),
13 | )
14 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
15 |
16 | stream.write(CSV_STRING);
17 | stream.end();
18 |
19 | // Output:
20 | // Invalid [rowNumber=1] [row={"firstName":"bob","lastName":"yukon"}]
21 | // Valid [row={"firstName":"sally","lastName":"yukon"}]
22 | // Valid [row={"firstName":"timmy","lastName":"yukon"}]
23 | // Parsed 3 rows
24 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/validate_async.example.js:
--------------------------------------------------------------------------------
1 | const { EOL } = require('os');
2 | const csv = require('@fast-csv/parse');
3 |
4 | const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL);
5 |
6 | const stream = csv
7 | .parse({ headers: true })
8 | .validate((row, cb) => {
9 | setImmediate(() => cb(null, row.firstName !== 'bob'));
10 | })
11 | .on('error', (error) => console.error(error))
12 | .on('data', (row) => console.log(`Valid [row=${JSON.stringify(row)}]`))
13 | .on('data-invalid', (row) => console.log(`Invalid [row=${JSON.stringify(row)}]`))
14 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
15 |
16 | stream.write(CSV_STRING);
17 | stream.end();
18 |
19 | // Output:
20 | // Invalid [row={"firstName":"bob","lastName":"yukon"}]
21 | // Valid [row={"firstName":"sally","lastName":"yukon"}]
22 | // Valid [row={"firstName":"timmy","lastName":"yukon"}]
23 | // Parsed 3 rows
24 |
--------------------------------------------------------------------------------
/examples/parsing-js/examples/validate_with_reason.example.js:
--------------------------------------------------------------------------------
1 | const { EOL } = require('os');
2 | const csv = require('@fast-csv/parse');
3 |
4 | const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL);
5 |
6 | const stream = csv
7 | .parse({ headers: true })
8 | .validate((row, cb) => {
9 | const isValid = row.firstName !== 'bob';
10 | if (!isValid) {
11 | return cb(null, false, 'Name is bob');
12 | }
13 | return cb(null, true);
14 | })
15 | .on('error', (error) => console.error(error))
16 | .on('data', (row) => console.log(`Valid [row=${JSON.stringify(row)}]`))
17 | .on('data-invalid', (row, rowNumber, reason) => {
18 | console.log(`Invalid [rowNumber=${rowNumber}] [row=${JSON.stringify(row)}] [reason=${reason}]`);
19 | })
20 | .on('end', (rowCount) => console.log(`Parsed ${rowCount} rows`));
21 |
22 | stream.write(CSV_STRING);
23 | stream.end();
24 |
25 | // Output:
26 | // Invalid [rowNumber=1] [row={"firstName":"bob","lastName":"yukon"}] [reason=Name is bob]
27 | // Valid [row={"firstName":"sally","lastName":"yukon"}]
28 | // Valid [row={"firstName":"timmy","lastName":"yukon"}]
29 | // Parsed 3 rows
30 |
--------------------------------------------------------------------------------
/examples/parsing-js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fast-csv/parse-js-examples",
3 | "version": "5.0.2",
4 | "private": true,
5 | "description": "fast-csv parsing examples",
6 | "scripts": {
7 | "list": "run-examples list",
8 | "all-examples": "run-examples all",
9 | "example": "run-examples run"
10 | },
11 | "dependencies": {
12 | "@fast-csv/parse": "5.0.2",
13 | "example-runner": "5.0.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/parsing-ts/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | rules: {
3 | 'no-console': 'off',
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/examples/parsing-ts/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [5.0.2](https://github.com/C2FO/fast-csv/compare/v5.0.1...v5.0.2) (2024-10-22)
7 |
8 | **Note:** Version bump only for package @fast-csv/parse-ts-examples
9 |
10 | # [5.0.0](https://github.com/C2FO/fast-csv/compare/v4.3.6...v5.0.0) (2024-01-13)
11 |
12 | **Note:** Version bump only for package @fast-csv/parse-ts-examples
13 |
14 | ## [4.3.6](https://github.com/C2FO/fast-csv/compare/v4.3.5...v4.3.6) (2020-12-04)
15 |
16 | **Note:** Version bump only for package @fast-csv/parse-ts-examples
17 |
18 | ## [4.3.4](https://github.com/C2FO/fast-csv/compare/v4.3.3...v4.3.4) (2020-11-03)
19 |
20 | **Note:** Version bump only for package @fast-csv/parse-ts-examples
21 |
22 | ## [4.3.3](https://github.com/C2FO/fast-csv/compare/v4.3.2...v4.3.3) (2020-10-30)
23 |
24 | **Note:** Version bump only for package @fast-csv/parse-ts-examples
25 |
26 | ## [4.3.2](https://github.com/C2FO/fast-csv/compare/v4.3.1...v4.3.2) (2020-09-02)
27 |
28 | **Note:** Version bump only for package @fast-csv/parse-ts-examples
29 |
30 | ## [4.3.1](https://github.com/C2FO/fast-csv/compare/v4.3.0...v4.3.1) (2020-06-23)
31 |
32 | **Note:** Version bump only for package @fast-csv/parse-ts-examples
33 |
34 | # [4.3.0](https://github.com/C2FO/fast-csv/compare/v4.2.0...v4.3.0) (2020-05-27)
35 |
36 | **Note:** Version bump only for package @fast-csv/parse-ts-examples
37 |
38 | # [4.2.0](https://github.com/C2FO/fast-csv/compare/v4.1.6...v4.2.0) (2020-05-19)
39 |
40 | **Note:** Version bump only for package @fast-csv/parse-ts-examples
41 |
42 | ## [4.1.6](https://github.com/C2FO/fast-csv/compare/v4.1.5...v4.1.6) (2020-05-15)
43 |
44 | **Note:** Version bump only for package @fast-csv/parse-ts-examples
45 |
46 | ## [4.1.5](https://github.com/C2FO/fast-csv/compare/v4.1.4...v4.1.5) (2020-05-15)
47 |
48 | **Note:** Version bump only for package @fast-csv/parse-ts-examples
49 |
50 | ## [4.1.4](https://github.com/C2FO/fast-csv/compare/v4.1.3...v4.1.4) (2020-05-15)
51 |
52 | **Note:** Version bump only for package @fast-csv/parse-ts-examples
53 |
--------------------------------------------------------------------------------
/examples/parsing-ts/README.md:
--------------------------------------------------------------------------------
1 | `@fast-csv/parse` typescript parsing examples.
2 |
3 | ## Usage
4 |
5 | ```sh
6 | npm run build
7 | ```
8 |
9 | To run all examples
10 |
11 | ```sh
12 | npm run all-examples
13 | ```
14 |
15 | To see a list of all available examples
16 |
17 | ```sh
18 | npm run list
19 | ```
20 |
21 | To run a specific example
22 |
23 | ```sh
24 | npm run example -- {example_name}
25 | ```
26 |
--------------------------------------------------------------------------------
/examples/parsing-ts/assets/snake_case_users.csv:
--------------------------------------------------------------------------------
1 | id,first_name,last_name,address
2 | 1,Bob,Yukon,1111 State St. Yukon AK
3 | 2,Sally,Yukon,1111 State St. Yukon AK
4 | 3,Bobby,Yukon,1111 State St. Yukon AK
5 | 4,Jane,Yukon,1111 State St. Yukon AK
6 | 5,Dick,Yukon,1111 State St. Yukon AK
7 | 6,John,Doe,1112 State St. Yukon AK
8 | 7,Jane,Doe,1113 State St. Yukon AK
9 | 8,Billy,Doe,1112 State St. Yukon AK
10 | 9,Edith,Doe,1112 State St. Yukon AK
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/alternate_delimiter.example.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parse } from '@fast-csv/parse';
3 |
4 | const CSV_STRING = ['a1\tb1', 'a2\tb2'].join(EOL);
5 |
6 | const stream = parse({ delimiter: '\t' })
7 | .on('error', (error) => {
8 | return console.error(error);
9 | })
10 | .on('data', (row) => {
11 | return console.log(row);
12 | })
13 | .on('end', (rowCount: number) => {
14 | return console.log(`Parsed ${rowCount} rows`);
15 | });
16 |
17 | stream.write(CSV_STRING);
18 | stream.end();
19 |
20 | // Output:
21 | // [ 'a1', 'b1' ]
22 | // [ 'a2', 'b2' ]
23 | // Parsed 2 rows
24 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/custom_headers.example.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parse } from '@fast-csv/parse';
3 |
4 | const CSV_STRING = ['a1,b1', 'a2,b2'].join(EOL);
5 |
6 | const stream = parse({ headers: ['a', 'b'] })
7 | .on('error', (error) => {
8 | return console.error(error);
9 | })
10 | .on('data', (row) => {
11 | return console.log(row);
12 | })
13 | .on('end', (rowCount: number) => {
14 | return console.log(`Parsed ${rowCount} rows`);
15 | });
16 |
17 | stream.write(CSV_STRING);
18 | stream.end();
19 |
20 | // Output:
21 | // { a: 'a1', b: 'b1' }
22 | // { a: 'a2', b: 'b2' }
23 | // Parsed 2 rows
24 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/first_row_as_headers.example.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parse } from '@fast-csv/parse';
3 |
4 | const CSV_STRING = ['a,b', 'a1,b1', 'a2,b2'].join(EOL);
5 |
6 | const stream = parse({ headers: true })
7 | .on('error', (error) => {
8 | return console.error(error);
9 | })
10 | .on('data', (row) => {
11 | return console.log(row);
12 | })
13 | .on('end', (rowCount: number) => {
14 | return console.log(`Parsed ${rowCount} rows`);
15 | });
16 |
17 | stream.write(CSV_STRING);
18 | stream.end();
19 |
20 | // Output:
21 | // { a: 'a1', b: 'b1' }
22 | // { a: 'a2', b: 'b2' }
23 | // Parsed 2 rows
24 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/ignore_empty_rows.example.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parse } from '@fast-csv/parse';
3 |
4 | const CSV_STRING = ['a1,b1', ',', 'a2,b2', ' ,\t', ''].join(EOL);
5 |
6 | const stream = parse({ ignoreEmpty: true })
7 | .on('error', (error) => {
8 | return console.error(error);
9 | })
10 | .on('data', (row) => {
11 | return console.log(row);
12 | })
13 | .on('end', (rowCount: number) => {
14 | return console.log(`Parsed ${rowCount} rows`);
15 | });
16 |
17 | stream.write(CSV_STRING);
18 | stream.end();
19 |
20 | // Output:
21 | // [ 'a1', 'b1' ]
22 | // [ 'a2', 'b2' ]
23 | // Parsed 2 rows
24 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/manual_write.example.ts:
--------------------------------------------------------------------------------
1 | import { parse } from '@fast-csv/parse';
2 |
3 | const stream = parse({ headers: true })
4 | .on('error', (error) => {
5 | return console.error(error);
6 | })
7 | .on('data', (row) => {
8 | return console.log(row);
9 | })
10 | .on('end', (rowCount: number) => {
11 | return console.log(`Parsed ${rowCount} rows`);
12 | });
13 |
14 | stream.write('header1,header2\n');
15 | stream.write('col1,col2');
16 | stream.end();
17 |
18 | // Output:
19 | // { header1: 'col1', header2: 'col2' }
20 | // Parsed 1 rows
21 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/max_rows.example.ts:
--------------------------------------------------------------------------------
1 | import { parse } from '@fast-csv/parse';
2 |
3 | const rows = [
4 | 'header1,header2\n',
5 | 'col1,col1\n',
6 | 'col2,col2\n',
7 | 'col3,col3\n',
8 | 'col4,col4\n',
9 | 'col5,col5\n',
10 | 'col6,col6\n',
11 | 'col7,col7\n',
12 | 'col8,col8\n',
13 | 'col9,col9\n',
14 | 'col10,col10',
15 | ];
16 |
17 | const stream = parse({ headers: true, maxRows: 5 })
18 | .on('error', (error) => {
19 | return console.error(error);
20 | })
21 | .on('data', (row) => {
22 | return console.log(row);
23 | })
24 | .on('end', (rowCount: number) => {
25 | return console.log(`Parsed ${rowCount} rows`);
26 | });
27 |
28 | rows.forEach((row) => {
29 | return stream.write(row);
30 | });
31 | stream.end();
32 |
33 | // Output:
34 | // { header1: 'col1', header2: 'col1' }
35 | // { header1: 'col2', header2: 'col2' }
36 | // { header1: 'col3', header2: 'col3' }
37 | // { header1: 'col4', header2: 'col4' }
38 | // { header1: 'col5', header2: 'col5' }
39 | // Parsed 5 rows
40 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/parse_string.example.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parseString } from '@fast-csv/parse';
3 |
4 | const CSV_STRING = ['a,b', 'a1,b1', 'a2,b2'].join(EOL);
5 |
6 | parseString(CSV_STRING, { headers: true })
7 | .on('error', (error) => {
8 | return console.error(error);
9 | })
10 | .on('data', (row) => {
11 | return console.log(row);
12 | })
13 | .on('end', (rowCount: number) => {
14 | return console.log(`Parsed ${rowCount} rows`);
15 | });
16 |
17 | // Output:
18 | // { a: 'a1', b: 'b1' }
19 | // { a: 'a2', b: 'b2' }
20 | // Parsed 2 rows
21 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/pipe.example.ts:
--------------------------------------------------------------------------------
1 | import { createReadStream } from 'fs';
2 | import { resolve } from 'path';
3 | import { parse } from '@fast-csv/parse';
4 |
5 | createReadStream(resolve(__dirname, '..', 'assets', 'snake_case_users.csv'))
6 | .pipe(parse())
7 | .on('error', (error) => {
8 | return console.error(error);
9 | })
10 | .on('data', (row) => {
11 | return console.log(row);
12 | })
13 | .on('end', (rowCount: number) => {
14 | return console.log(`Parsed ${rowCount} rows`);
15 | });
16 |
17 | // Output:
18 | // [ 'id', 'first_name', 'last_name', 'address' ]
19 | // [ '1', 'Bob', 'Yukon', '1111 State St. Yukon AK' ]
20 | // [ '2', 'Sally', 'Yukon', '1111 State St. Yukon AK' ]
21 | // [ '3', 'Bobby', 'Yukon', '1111 State St. Yukon AK' ]
22 | // [ '4', 'Jane', 'Yukon', '1111 State St. Yukon AK' ]
23 | // [ '5', 'Dick', 'Yukon', '1111 State St. Yukon AK' ]
24 | // [ '6', 'John', 'Doe', '1112 State St. Yukon AK' ]
25 | // [ '7', 'Jane', 'Doe', '1113 State St. Yukon AK' ]
26 | // [ '8', 'Billy', 'Doe', '1112 State St. Yukon AK' ]
27 | // [ '9', 'Edith', 'Doe', '1112 State St. Yukon AK' ]
28 | // Parsed 10 rows
29 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/rename_headers.example.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parse } from '@fast-csv/parse';
3 |
4 | const CSV_STRING = ['header1,header2', 'a1,b1', 'a2,b2'].join(EOL);
5 |
6 | const stream = parse({ headers: ['a', 'b'], renameHeaders: true })
7 | .on('error', (error) => {
8 | return console.error(error);
9 | })
10 | .on('data', (row) => {
11 | return console.log(row);
12 | })
13 | .on('end', (rowCount: number) => {
14 | return console.log(`Parsed ${rowCount} rows`);
15 | });
16 |
17 | stream.write(CSV_STRING);
18 | stream.end();
19 |
20 | // Output:
21 | // { a: 'a1', b: 'b1' }
22 | // { a: 'a2', b: 'b2' }
23 | // Parsed 2 rows
24 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/skip_lines.example.ts:
--------------------------------------------------------------------------------
1 | import { parse } from '@fast-csv/parse';
2 |
3 | const rows = [
4 | 'skip1_header1,skip1_header2\n',
5 | 'skip2_header1,skip2_header2\n',
6 | 'header1,header2\n',
7 | 'col1,col1\n',
8 | 'col2,col2\n',
9 | 'col3,col3\n',
10 | 'col4,col4\n',
11 | ];
12 |
13 | const stream = parse({ headers: true, skipLines: 2 })
14 | .on('error', (error) => {
15 | return console.error(error);
16 | })
17 | .on('data', (row) => {
18 | return console.log(row);
19 | })
20 | .on('end', (rowCount: number) => {
21 | return console.log(`Parsed ${rowCount} rows`);
22 | });
23 |
24 | rows.forEach((row) => {
25 | return stream.write(row);
26 | });
27 | stream.end();
28 |
29 | // Output:
30 | // { header1: 'col1', header2: 'col1' }
31 | // { header1: 'col2', header2: 'col2' }
32 | // { header1: 'col3', header2: 'col3' }
33 | // { header1: 'col4', header2: 'col4' }
34 | // Parsed 4 rows
35 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/skip_rows.example.ts:
--------------------------------------------------------------------------------
1 | import { parse } from '@fast-csv/parse';
2 |
3 | const rows = [
4 | 'header1,header2\n',
5 | 'col1,col1\n',
6 | 'col2,col2\n',
7 | 'col3,col3\n',
8 | 'col4,col4\n',
9 | 'col5,col5\n',
10 | 'col6,col6\n',
11 | ];
12 |
13 | const stream = parse({ headers: true, skipRows: 2 })
14 | .on('error', (error) => {
15 | return console.error(error);
16 | })
17 | .on('data', (row) => {
18 | return console.log(row);
19 | })
20 | .on('end', (rowCount: number) => {
21 | return console.log(`Parsed ${rowCount} rows`);
22 | });
23 |
24 | rows.forEach((row) => {
25 | return stream.write(row);
26 | });
27 | stream.end();
28 |
29 | // Output:
30 | // { header1: 'col3', header2: 'col3' }
31 | // { header1: 'col4', header2: 'col4' }
32 | // { header1: 'col5', header2: 'col5' }
33 | // { header1: 'col6', header2: 'col6' }
34 | // Parsed 4 rows
35 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/skipping_columns.example.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parse } from '@fast-csv/parse';
3 |
4 | const CSV_STRING = ['a1,b1,c1', 'a2,b2,c2'].join(EOL);
5 |
6 | const stream = parse({ headers: ['a', undefined, 'c'] })
7 | .on('error', (error) => {
8 | return console.error(error);
9 | })
10 | .on('data', (row) => {
11 | return console.log(row);
12 | })
13 | .on('end', (rowCount: number) => {
14 | return console.log(`Parsed ${rowCount} rows`);
15 | });
16 |
17 | stream.write(CSV_STRING);
18 | stream.end();
19 |
20 | // Output:
21 | // { a: 'a1', c: 'c1' }
22 | // { a: 'a2', c: 'c2' }
23 | // Parsed 2 rows
24 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/transform.example.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parse } from '@fast-csv/parse';
3 |
4 | const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL);
5 |
6 | type UserRow = {
7 | firstName: string;
8 | lastName: string;
9 | };
10 |
11 | type TransformedUserRow = UserRow & {
12 | properName: string;
13 | };
14 |
15 | const stream = parse({ headers: true })
16 | .transform((data: UserRow): TransformedUserRow => {
17 | return {
18 | firstName: data.firstName.toUpperCase(),
19 | lastName: data.lastName.toUpperCase(),
20 | properName: `${data.firstName} ${data.lastName}`,
21 | };
22 | })
23 | .on('error', (error) => {
24 | return console.error(error);
25 | })
26 | .on('data', (row: TransformedUserRow) => {
27 | return console.log(JSON.stringify(row));
28 | })
29 | .on('end', (rowCount: number) => {
30 | return console.log(`Parsed ${rowCount} rows`);
31 | });
32 |
33 | stream.write(CSV_STRING);
34 | stream.end();
35 |
36 | // Output:
37 | // {"firstName":"BOB","lastName":"YUKON","properName":"bob yukon"}
38 | // {"firstName":"SALLY","lastName":"YUKON","properName":"sally yukon"}
39 | // {"firstName":"TIMMY","lastName":"YUKON","properName":"timmy yukon"}
40 | // Parsed 3 rows
41 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/transform_async.example.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parse } from '@fast-csv/parse';
3 |
4 | const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL);
5 |
6 | type UserRow = {
7 | firstName: string;
8 | lastName: string;
9 | };
10 |
11 | type TransformedUserRow = UserRow & {
12 | properName: string;
13 | };
14 |
15 | const stream = parse({ headers: true })
16 | .transform((data, cb): void => {
17 | setImmediate(() => {
18 | return cb(null, {
19 | firstName: data.firstName.toUpperCase(),
20 | lastName: data.lastName.toUpperCase(),
21 | properName: `${data.firstName} ${data.lastName}`,
22 | });
23 | });
24 | })
25 | .on('error', (error) => {
26 | return console.error(error);
27 | })
28 | .on('data', (row) => {
29 | return console.log(JSON.stringify(row));
30 | })
31 | .on('end', (rowCount: number) => {
32 | return console.log(`Parsed ${rowCount} rows`);
33 | });
34 |
35 | stream.write(CSV_STRING);
36 | stream.end();
37 |
38 | // Output:
39 | // {"firstName":"BOB","lastName":"YUKON","properName":"bob yukon"}
40 | // {"firstName":"SALLY","lastName":"YUKON","properName":"sally yukon"}
41 | // {"firstName":"TIMMY","lastName":"YUKON","properName":"timmy yukon"}
42 | // Parsed 3 rows
43 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/transform_headers.example.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parse } from '@fast-csv/parse';
3 |
4 | const CSV_STRING = ['header1,header2', 'a1,b1', 'a2,b2'].join(EOL);
5 |
6 | const stream = parse({
7 | headers: (headers) => {
8 | return headers.map((h) => {
9 | return h?.toUpperCase();
10 | });
11 | },
12 | })
13 | .on('error', (error) => {
14 | return console.error(error);
15 | })
16 | .on('data', (row) => {
17 | return console.log(row);
18 | })
19 | .on('end', (rowCount: number) => {
20 | return console.log(`Parsed ${rowCount} rows`);
21 | });
22 |
23 | stream.write(CSV_STRING);
24 | stream.end();
25 |
26 | // Output:
27 | // { HEADER1: 'a1', HEADER2: 'b1' }
28 | // { HEADER1: 'a2', HEADER2: 'b2' }
29 | // Parsed 2 rows
30 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/validate.example.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parse } from '@fast-csv/parse';
3 |
4 | const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL);
5 | type UserRow = {
6 | firstName: string;
7 | lastName: string;
8 | };
9 | const stream = parse({ headers: true })
10 | .validate((data: UserRow): boolean => {
11 | return data.firstName !== 'bob';
12 | })
13 | .on('error', (error) => {
14 | return console.error(error);
15 | })
16 | .on('data', (row: UserRow) => {
17 | return console.log(`Valid [row=${JSON.stringify(row)}]`);
18 | })
19 | .on('data-invalid', (row, rowNumber: number) => {
20 | return console.log(`Invalid [rowNumber=${rowNumber}] [row=${JSON.stringify(row)}]`);
21 | })
22 | .on('end', (rowCount: number) => {
23 | return console.log(`Parsed ${rowCount} rows`);
24 | });
25 |
26 | stream.write(CSV_STRING);
27 | stream.end();
28 |
29 | // Output:
30 | // Invalid [rowNumber=1] [row={"firstName":"bob","lastName":"yukon"}]
31 | // Valid [row={"firstName":"sally","lastName":"yukon"}]
32 | // Valid [row={"firstName":"timmy","lastName":"yukon"}]
33 | // Parsed 3 rows
34 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/validate_async.example.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parse } from '@fast-csv/parse';
3 |
4 | const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL);
5 |
6 | type UserRow = {
7 | firstName: string;
8 | lastName: string;
9 | };
10 |
11 | const stream = parse({ headers: true })
12 | .validate((row, cb): void => {
13 | setImmediate(() => {
14 | return cb(null, row.firstName !== 'bob');
15 | });
16 | })
17 | .on('error', (error) => {
18 | return console.error(error);
19 | })
20 | .on('data', (row) => {
21 | return console.log(`Valid [row=${JSON.stringify(row)}]`);
22 | })
23 | .on('data-invalid', (row) => {
24 | return console.log(`Invalid [row=${JSON.stringify(row)}]`);
25 | })
26 | .on('end', (rowCount: number) => {
27 | return console.log(`Parsed ${rowCount} rows`);
28 | });
29 |
30 | stream.write(CSV_STRING);
31 | stream.end();
32 |
33 | // Output:
34 | // Invalid [row={"firstName":"bob","lastName":"yukon"}]
35 | // Valid [row={"firstName":"sally","lastName":"yukon"}]
36 | // Valid [row={"firstName":"timmy","lastName":"yukon"}]
37 | // Parsed 3 rows
38 |
--------------------------------------------------------------------------------
/examples/parsing-ts/examples/validate_with_reason.example.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parse } from '@fast-csv/parse';
3 |
4 | const CSV_STRING = ['firstName,lastName', 'bob,yukon', 'sally,yukon', 'timmy,yukon'].join(EOL);
5 |
6 | type UserRow = {
7 | firstName: string;
8 | lastName: string;
9 | };
10 |
11 | const stream = parse({ headers: true })
12 | .validate((row, cb): void => {
13 | const isValid = row.firstName !== 'bob';
14 | if (!isValid) {
15 | return cb(null, false, 'Name is bob');
16 | }
17 | return cb(null, true);
18 | })
19 | .on('error', (error) => {
20 | return console.error(error);
21 | })
22 | .on('data', (row) => {
23 | return console.log(`Valid [row=${JSON.stringify(row)}]`);
24 | })
25 | .on('data-invalid', (row, rowNumber: number, reason: string) => {
26 | console.log(`Invalid [rowNumber=${rowNumber}] [row=${JSON.stringify(row)}] [reason=${reason}]`);
27 | })
28 | .on('end', (rowCount: number) => {
29 | return console.log(`Parsed ${rowCount} rows`);
30 | });
31 |
32 | stream.write(CSV_STRING);
33 | stream.end();
34 |
35 | // Output:
36 | // Invalid [rowNumber=1] [row={"firstName":"bob","lastName":"yukon"}] [reason=Name is bob]
37 | // Valid [row={"firstName":"sally","lastName":"yukon"}]
38 | // Valid [row={"firstName":"timmy","lastName":"yukon"}]
39 | // Parsed 3 rows
40 |
--------------------------------------------------------------------------------
/examples/parsing-ts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fast-csv/parse-ts-examples",
3 | "version": "5.0.2",
4 | "private": true,
5 | "description": "fast-csv parsing typescript examples",
6 | "scripts": {
7 | "list": "run-examples --dir=build list",
8 | "all-examples": "run-examples --dir=build all",
9 | "example": "run-examples --dir=build run",
10 | "build": "npm run clean && npm run compile",
11 | "clean": "rm -rf ./build && rm -rf tsconfig.tsbuildinfo",
12 | "compile": "tsc"
13 | },
14 | "dependencies": {
15 | "@fast-csv/parse": "5.0.2",
16 | "example-runner": "5.0.0",
17 | "typescript": "5.6.3"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/parsing-ts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.build.json",
3 | "compilerOptions": {
4 | "outDir": "./build",
5 | "rootDir": "./examples"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | // jest.config.js
2 | module.exports = {
3 | // [...]
4 | // Replace `ts-jest` with the preset you want to use
5 | // from the above list
6 | preset: 'ts-jest',
7 | collectCoverageFrom: ['packages/**/*.ts', '!**/__tests__/**', '!**/build/**', '!**/node_modules/**'],
8 | testMatch: ['**/__tests__/**/*.spec.ts'],
9 | };
10 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "tagVersionPrefix": "v",
3 | "command": {
4 | "version": {
5 | "message": "chore(release): publish %s",
6 | "allowBranch": "main",
7 | "exact": true,
8 | "createRelease": "github",
9 | "conventionalCommits": true
10 | },
11 | "bootstrap": {
12 | "hoist": true
13 | }
14 | },
15 | "version": "5.0.2"
16 | }
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fast-csv",
3 | "private": true,
4 | "scripts": {
5 | "clean": "lerna run clean",
6 | "build": "lerna run build",
7 | "lerna:pub": "lerna publish from-git",
8 | "lerna:version": "lerna version",
9 | "release": "npm run build && npm run lerna:version && npm run lerna:pub",
10 | "test": "npm run lint && npm run jest && npm run examples",
11 | "lint": "npm run lint:ts && npm run lint:js",
12 | "lint:fix": "npm run lint:ts -- --fix && npm run lint:js -- --fix",
13 | "lint:ts": "eslint --ext=.ts .",
14 | "lint:js": "eslint --ext=.js ./examples/**/examples/**/*.js",
15 | "jest": "jest --runInBand --coverage",
16 | "examples": "npm run all-examples --ws",
17 | "benchmarks": "npm run benchmarks --ws"
18 | },
19 | "repository": {
20 | "type": "git",
21 | "url": "git@github.com:C2FO/fast-csv.git"
22 | },
23 | "workspaces": [
24 | "packages/*",
25 | "examples/*",
26 | "documentation"
27 | ],
28 | "devDependencies": {
29 | "@commitlint/cli": "19.7.1",
30 | "@commitlint/config-angular": "19.7.1",
31 | "@types/jest": "29.5.14",
32 | "@typescript-eslint/eslint-plugin": "6.21.0",
33 | "@typescript-eslint/parser": "6.21.0",
34 | "eslint": "8.57.1",
35 | "eslint-config-airbnb-typescript": "17.1.0",
36 | "eslint-config-prettier": "10.0.2",
37 | "eslint-plugin-import": "2.31.0",
38 | "eslint-plugin-jest": "28.11.0",
39 | "eslint-plugin-prettier": "5.2.3",
40 | "eslint-plugin-tsdoc": "0.4.0",
41 | "husky": "9.1.7",
42 | "jest": "29.7.0",
43 | "lerna": "8.2.2",
44 | "prettier": "3.5.3",
45 | "ts-jest": "29.2.6",
46 | "typescript": "5.6.3"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/packages/fast-csv/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {};
2 |
--------------------------------------------------------------------------------
/packages/fast-csv/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [](https://www.npmjs.org/package/fast-csv)
6 | [](https://travis-ci.org/C2FO/fast-csv)
7 | [](https://coveralls.io/github/C2FO/fast-csv?branch=master)
8 | [](https://snyk.io/test/github/C2FO/fast-csv?targetFile=package.json)
9 |
10 | # `fast-csv`
11 |
12 | Package that combines both [`@fast-csv/format`](https://c2fo.github.io/fast-csv/docs/formatting/getting-started) and [`@fast-csv/parse`](https://c2fo.github.io/fast-csv/docs/parsing/getting-started) into a single package.
13 |
14 | ## Installation
15 |
16 | [Install Guide](https://c2fo.github.io/fast-csv/docs/introduction/install)
17 |
18 | ## Usage
19 |
20 | To get started with `fast-csv` [check out the docs](https://c2fo.github.io/fast-csv/docs/introduction/getting-started)
21 |
--------------------------------------------------------------------------------
/packages/fast-csv/__tests__/fast-csv.spec.ts:
--------------------------------------------------------------------------------
1 | import * as csvFormat from '@fast-csv/format';
2 | import * as csv from '../src';
3 |
4 | describe('formatting function', () => {
5 | describe('format', () => {
6 | it('should expose the format function', () => {
7 | expect(csv.format).toBe(csvFormat.format);
8 | });
9 | });
10 | });
11 |
--------------------------------------------------------------------------------
/packages/fast-csv/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fast-csv",
3 | "version": "5.0.2",
4 | "description": "CSV parser and writer",
5 | "main": "./build/src/index.js",
6 | "types": "./build/src/index.d.ts",
7 | "scripts": {
8 | "prepublishOnly": "npm run build",
9 | "build": "npm run clean && npm run compile",
10 | "clean": "rm -rf ./build && rm -rf tsconfig.tsbuildinfo",
11 | "compile": "tsc"
12 | },
13 | "directories": {
14 | "lib": "src",
15 | "test": "__tests__"
16 | },
17 | "files": [
18 | "build/src/**"
19 | ],
20 | "repository": {
21 | "type": "git",
22 | "url": "git+https://github.com/C2FO/fast-csv.git",
23 | "directory": "packages/fast-csv"
24 | },
25 | "keywords": [
26 | "csv",
27 | "parser",
28 | "fast",
29 | "writer",
30 | "csv writer",
31 | "CSV"
32 | ],
33 | "homepage": "https://c2fo.github.io/fast-csv",
34 | "author": "Doug Martin",
35 | "license": "MIT",
36 | "engines": {
37 | "node": ">=10.0.0"
38 | },
39 | "dependencies": {
40 | "@fast-csv/format": "5.0.2",
41 | "@fast-csv/parse": "5.0.2"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/packages/fast-csv/src/index.ts:
--------------------------------------------------------------------------------
1 | export {
2 | format,
3 | write,
4 | writeToStream,
5 | writeToBuffer,
6 | writeToString,
7 | writeToPath,
8 | CsvFormatterStream,
9 | FormatterOptions,
10 | FormatterOptionsArgs,
11 | Row as FormatterRow,
12 | RowMap as FormatterRowMap,
13 | RowArray as FormatterRowArray,
14 | RowHashArray as FormatterRowHashArray,
15 | RowTransformCallback as FormatterRowTransformCallback,
16 | RowTransformFunction as FormatterRowTransformFunction,
17 | } from '@fast-csv/format';
18 |
19 | export {
20 | parse,
21 | parseString,
22 | parseStream,
23 | parseFile,
24 | ParserOptions,
25 | CsvParserStream,
26 | ParserOptionsArgs,
27 | Row as ParserRow,
28 | RowMap as ParserRowMap,
29 | RowArray as ParserRowArray,
30 | RowValidateCallback as ParserRowValidateCallback,
31 | SyncRowValidate as ParserSyncRowValidate,
32 | AsyncRowValidate as ParserAsyncRowValidate,
33 | RowValidate as ParserRowValidate,
34 | RowTransformCallback as ParserRowTransformCallback,
35 | SyncRowTransform as ParserSyncRowTransform,
36 | AsyncRowTransform as ParserAsyncRowTransform,
37 | RowTransformFunction as ParserRowTransformFunction,
38 | HeaderArray as ParserHeaderArray,
39 | HeaderTransformFunction as ParserHeaderTransformFunction,
40 | } from '@fast-csv/parse';
41 |
--------------------------------------------------------------------------------
/packages/fast-csv/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.build.json",
3 | "compilerOptions": {
4 | "outDir": "./build",
5 | "rootDir": ".",
6 | "composite": true
7 | },
8 | "include": [
9 | "./src",
10 | "./__tests__"
11 | ],
12 | "exclude": [
13 | "node_modules",
14 | "dist"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/packages/format/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {};
2 |
--------------------------------------------------------------------------------
/packages/format/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [](https://www.npmjs.org/package/@fast-csv/format)
6 | [](https://travis-ci.org/C2FO/fast-csv)
7 | [](https://coveralls.io/github/C2FO/fast-csv?branch=master)
8 | [](https://snyk.io/test/github/C2FO/fast-csv?targetFile=packages/format/package.json)
9 |
10 | # `@fast-csv/format`
11 |
12 | `fast-csv` package to format CSVs.
13 |
14 | ## Installation
15 |
16 | [Install Guide](https://c2fo.github.io/fast-csv/docs/introduction/install)
17 |
18 | ## Usage
19 |
20 | To get started with `@fast-csv/format` [check out the docs](https://c2fo.github.io/fast-csv/docs/formatting/getting-started)
21 |
--------------------------------------------------------------------------------
/packages/format/__tests__/__fixtures__/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/C2FO/fast-csv/44272f806d122b96a6fe0a7202d4695de943f18a/packages/format/__tests__/__fixtures__/.gitkeep
--------------------------------------------------------------------------------
/packages/format/__tests__/__fixtures__/RecordingStream.ts:
--------------------------------------------------------------------------------
1 | import { Writable } from 'stream';
2 |
3 | export class RecordingStream extends Writable {
4 | public readonly data: string[] = [];
5 |
6 | public constructor() {
7 | super({
8 | write: (data: Buffer, enc, cb): void => {
9 | this.data.push(data.toString());
10 | cb();
11 | },
12 | });
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/packages/format/__tests__/__fixtures__/index.ts:
--------------------------------------------------------------------------------
1 | export { RecordingStream } from './RecordingStream';
2 | export const objectRows = [
3 | { a: 'a1', b: 'b1' },
4 | { a: 'a2', b: 'b2' },
5 | ];
6 |
7 | export const arrayRows = [
8 | ['a', 'b'],
9 | ['a1', 'b1'],
10 | ['a2', 'b2'],
11 | ];
12 |
13 | export const multiDimensionalRows = [
14 | [
15 | ['a', 'a1'],
16 | ['b', 'b1'],
17 | ],
18 | [
19 | ['a', 'a2'],
20 | ['b', 'b2'],
21 | ],
22 | ];
23 |
--------------------------------------------------------------------------------
/packages/format/__tests__/issues/__fixtures__/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/C2FO/fast-csv/44272f806d122b96a6fe0a7202d4695de943f18a/packages/format/__tests__/issues/__fixtures__/.gitkeep
--------------------------------------------------------------------------------
/packages/format/__tests__/issues/issue158.spec.ts:
--------------------------------------------------------------------------------
1 | import * as csv from '../../src';
2 | import { RecordingStream } from '../__fixtures__';
3 |
4 | describe('Issue #158 - https://github.com/C2FO/fast-csv/issues/158', () => {
5 | class Place {
6 | public readonly id: number;
7 |
8 | public readonly name: string;
9 |
10 | public calculatedValue: number;
11 |
12 | public constructor(id: number, name: string) {
13 | this.id = id;
14 | this.name = name;
15 | this.calculatedValue = 0;
16 | }
17 |
18 | public calculateSomething() {
19 | this.calculatedValue = this.id * 2;
20 | return this;
21 | }
22 | }
23 |
24 | it('should not write prototype methods in csv', () => {
25 | return new Promise((res, rej) => {
26 | const rs = new RecordingStream();
27 | csv.write(
28 | [
29 | new Place(1, 'a').calculateSomething(),
30 | new Place(2, 'b').calculateSomething(),
31 | new Place(3, 'c').calculateSomething(),
32 | ],
33 | { headers: true },
34 | )
35 | .pipe(rs)
36 | .on('error', rej)
37 | .on('finish', () => {
38 | expect(rs.data.join('')).toBe('id,name,calculatedValue\n1,a,2\n2,b,4\n3,c,6');
39 | res(() => {});
40 | });
41 | });
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/packages/format/__tests__/issues/issue252.spec.ts:
--------------------------------------------------------------------------------
1 | import * as csv from '../../src';
2 | import { RecordingStream } from '../__fixtures__';
3 |
4 | describe('Issue #252 - https://github.com/C2FO/fast-csv/issues/252', () => {
5 | it('should keep the original row', () => {
6 | return new Promise((res, rej) => {
7 | const rs = new RecordingStream();
8 | const data: csv.RowArray[] = [
9 | ['a', 'b', 'c'],
10 | ['d', 'e', 'f'],
11 | ];
12 |
13 | csv.write(data, {
14 | headers: ['header1', 'header2', 'header3'],
15 | })
16 | .pipe(rs)
17 | .on('error', rej)
18 | .on('finish', () => {
19 | expect(rs.data.join('')).toBe('header1,header2,header3\na,b,c\nd,e,f');
20 | res(() => {});
21 | });
22 | });
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/packages/format/__tests__/issues/issue446.spec.ts:
--------------------------------------------------------------------------------
1 | import * as csv from '../../src';
2 | import { RecordingStream } from '../__fixtures__';
3 |
4 | describe('Issue #446 - https://github.com/C2FO/fast-csv/issues/446', () => {
5 | it('should not quote a field that contains a single quote if it is not the quote character', () => {
6 | return new Promise((res, rej) => {
7 | const rs = new RecordingStream();
8 | const data: csv.RowArray[] = [["a quick' brown fox", 'jumped', 'over the lazy brown "dog"']];
9 |
10 | csv.write(data, {
11 | headers: ['header1', 'header2', 'header3'],
12 | })
13 | .pipe(rs)
14 | .on('error', rej)
15 | .on('finish', () => {
16 | expect(rs.data).toEqual([
17 | 'header1,header2,header3',
18 | `\na quick' brown fox,jumped,"over the lazy brown ""dog"""`,
19 | ]);
20 | res(() => {});
21 | });
22 | });
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/packages/format/__tests__/issues/issue503.spec.ts:
--------------------------------------------------------------------------------
1 | import { RecordingStream } from '../__fixtures__';
2 | import { RowArray, write } from '../../src';
3 |
4 | describe('Issue #503 - https://github.com/C2FO/fast-csv/issues/503', () => {
5 | it('should emit all columns after an empty row', () => {
6 | return new Promise((res, rej) => {
7 | const rs = new RecordingStream();
8 | const data: RowArray[] = [[], ['something']];
9 |
10 | write(data, { quote: false, headers: false, writeHeaders: false })
11 | .pipe(rs)
12 | .on('error', rej)
13 | .on('finish', () => {
14 | expect(rs.data).toEqual(['\nsomething']);
15 | res(() => {});
16 | });
17 | });
18 | });
19 |
20 | it('should not assume first row is a header if header = false', () => {
21 | return new Promise((res, rej) => {
22 | const rs = new RecordingStream();
23 | const data: RowArray[] = [['1'], [], ['1', '2', '3']];
24 |
25 | write(data, { quote: false, headers: false, writeHeaders: false })
26 | .pipe(rs)
27 | .on('error', rej)
28 | .on('finish', () => {
29 | expect(rs.data).toEqual(['1', '\n', '\n1,2,3']);
30 | res(() => {});
31 | });
32 | });
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/packages/format/__tests__/issues/issue77.spec.ts:
--------------------------------------------------------------------------------
1 | import * as fs from 'fs';
2 | import * as path from 'path';
3 | import * as csv from '../../src';
4 |
5 | describe('Issue #77 - https://github.com/C2FO/fast-csv/issues/77', () => {
6 | it('should sort columns by order of headers defined when formatting a csv', () => {
7 | return new Promise((res, rej) => {
8 | const writable = fs.createWriteStream(path.resolve(__dirname, '__fixtures__/test.csv'), {
9 | encoding: 'utf8',
10 | });
11 | const csvStream = csv.format({ headers: ['second', 'first'] }).on('error', rej);
12 |
13 | writable.on('finish', () => {
14 | expect(fs.readFileSync(path.resolve(__dirname, '__fixtures__', 'test.csv'))).toEqual(
15 | Buffer.from('second,first\n2,1'),
16 | );
17 | fs.unlinkSync(path.resolve(__dirname, '__fixtures__', 'test.csv'));
18 | res(() => {});
19 | });
20 |
21 | csvStream.pipe(writable);
22 |
23 | [{ first: '1', second: '2' }].forEach((item) => {
24 | return csvStream.write(item);
25 | });
26 |
27 | csvStream.end();
28 | });
29 | });
30 |
31 | it('should write headers even with no data when formatting a csv', () => {
32 | return new Promise((res, rej) => {
33 | const writable = fs.createWriteStream(path.resolve(__dirname, '__fixtures__/test.csv'), {
34 | encoding: 'utf8',
35 | });
36 | const csvStream = csv.format({ headers: ['first', 'second'] }).on('error', rej);
37 |
38 | writable.on('finish', () => {
39 | expect(fs.readFileSync(path.resolve(__dirname, '__fixtures__/test.csv'))).toEqual(
40 | Buffer.from('first,second\n,'),
41 | );
42 | fs.unlinkSync(path.resolve(__dirname, '__fixtures__/test.csv'));
43 | res(() => {});
44 | });
45 |
46 | csvStream.pipe(writable);
47 |
48 | [{}].forEach((item) => {
49 | return csvStream.write(item);
50 | });
51 |
52 | csvStream.end();
53 | });
54 | });
55 | });
56 |
--------------------------------------------------------------------------------
/packages/format/__tests__/issues/issue97.spec.ts:
--------------------------------------------------------------------------------
1 | import { RecordingStream } from '../__fixtures__';
2 | import { RowMap, write } from '../../src';
3 |
4 | describe('Issue #97 - https://github.com/C2FO/fast-csv/issues/97', () => {
5 | it('should keep the original row', () => {
6 | return new Promise((res, rej) => {
7 | const rs = new RecordingStream();
8 | const data: RowMap[] = [
9 | { field1: 'a1"a', field2: 'b1"b' },
10 | { field1: 'a2"a', field2: 'b2"b' },
11 | ];
12 |
13 | write(data, { quote: false, headers: true })
14 | .pipe(rs)
15 | .on('error', rej)
16 | .on('finish', () => {
17 | expect(rs.data.join('')).toBe('field1,field2\na1"a,b1"b\na2"a,b2"b');
18 | res(() => {});
19 | });
20 | });
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/packages/format/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fast-csv/format",
3 | "version": "5.0.2",
4 | "description": "fast-csv formatting module",
5 | "keywords": [
6 | "csv",
7 | "format",
8 | "write"
9 | ],
10 | "author": "doug-martin ",
11 | "homepage": "https://c2fo.github.io/fast-csv/docs/formatting/getting-started/",
12 | "license": "MIT",
13 | "main": "build/src/index.js",
14 | "types": "build/src/index.d.ts",
15 | "directories": {
16 | "lib": "src",
17 | "test": "__tests__"
18 | },
19 | "files": [
20 | "build/src/**"
21 | ],
22 | "publishConfig": {
23 | "access": "public"
24 | },
25 | "repository": {
26 | "type": "git",
27 | "url": "git+https://github.com/C2FO/fast-csv.git",
28 | "directory": "packages/format"
29 | },
30 | "scripts": {
31 | "prepublishOnly": "npm run build",
32 | "build": "npm run clean && npm run compile",
33 | "clean": "rm -rf ./build && rm -rf tsconfig.tsbuildinfo",
34 | "compile": "tsc"
35 | },
36 | "bugs": {
37 | "url": "https://github.com/C2FO/fast-csv/issues"
38 | },
39 | "dependencies": {
40 | "lodash.escaperegexp": "^4.1.2",
41 | "lodash.isboolean": "^3.0.3",
42 | "lodash.isfunction": "^3.0.9",
43 | "lodash.isnil": "^4.0.0"
44 | },
45 | "devDependencies": {
46 | "@types/lodash.escaperegexp": "4.1.9",
47 | "@types/lodash.isboolean": "3.0.9",
48 | "@types/lodash.isfunction": "3.0.9",
49 | "@types/lodash.isnil": "4.0.9",
50 | "@types/node": "^22.7.8"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/packages/format/src/formatter/index.ts:
--------------------------------------------------------------------------------
1 | export { RowFormatter } from './RowFormatter';
2 | export { FieldFormatter } from './FieldFormatter';
3 |
--------------------------------------------------------------------------------
/packages/format/src/types.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-explicit-any */
2 |
3 | export type RowMap = Record;
4 | export type RowHashArray = [string, V][];
5 | export type RowArray = string[];
6 | export type Row = RowArray | RowHashArray | RowMap;
7 |
8 | export type RowTransformCallback = (error?: Error | null, row?: R) => void;
9 | export type SyncRowTransform = (row: I) => O;
10 | export type AsyncRowTransform = (row: I, cb: RowTransformCallback) => void;
11 | export type RowTransformFunction = SyncRowTransform | AsyncRowTransform;
12 |
13 | export const isSyncTransform = (
14 | transform: RowTransformFunction,
15 | ): transform is SyncRowTransform => {
16 | return transform.length === 1;
17 | };
18 |
--------------------------------------------------------------------------------
/packages/format/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.build.json",
3 | "compilerOptions": {
4 | "skipLibCheck": true,
5 | "outDir": "./build",
6 | "rootDir": ".",
7 | "composite": true
8 | },
9 | "include": [
10 | "./src",
11 | "./__tests__"
12 | ],
13 | "exclude": [
14 | "node_modules",
15 | "dist"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/packages/parse/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | rules: {
3 | 'jest/expect-expect': [
4 | 'error',
5 | {
6 | assertFunctionNames: ['expect', 'expectParsed', 'expectErrorEvent', 'expectTokenContent'],
7 | },
8 | ],
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/packages/parse/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [](https://www.npmjs.org/package/@fast-csv/parse)
6 | [](https://travis-ci.org/C2FO/fast-csv)
7 | [](https://coveralls.io/github/C2FO/fast-csv?branch=master)
8 | [](https://snyk.io/test/github/C2FO/fast-csv?targetFile=packages/parse/package.json)
9 |
10 | # `@fast-csv/parse`
11 |
12 | `fast-csv` package to parse CSVs.
13 |
14 | ## Installation
15 |
16 | [Install Guide](https://c2fo.github.io/fast-csv/docs/introduction/install)
17 |
18 | ## Usage
19 |
20 | To get started with `@fast-csv/parse` [check out the docs](https://c2fo.github.io/fast-csv/docs/parsing/getting-started)
21 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/__fixtures__/RecordingStream.ts:
--------------------------------------------------------------------------------
1 | import { Writable } from 'stream';
2 |
3 | export class RecordingStream extends Writable {
4 | public readonly data: string[] = [];
5 |
6 | public constructor() {
7 | super({
8 | write: (data: Buffer, enc, cb): void => {
9 | this.data.push(data.toString());
10 | cb();
11 | },
12 | });
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/__fixtures__/alternateEncoding.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import { EOL } from 'os';
3 | import { PathAndContent } from './helpers';
4 | import { RowMap } from '../../src';
5 |
6 | export const alternateEncoding: PathAndContent = {
7 | path: resolve(__dirname, 'tmp', 'alternate_encoding.csv'),
8 |
9 | content: Buffer.from(
10 | [
11 | 'first_name,last_name,email_address',
12 | 'First1,Last1,email1@email.com',
13 | 'First2,Last2,email2@email.com',
14 | 'First3,Last3,email3@email.com',
15 | ].join(EOL),
16 | 'utf16le',
17 | ),
18 |
19 | parsed: [
20 | {
21 | first_name: 'First1',
22 | last_name: 'Last1',
23 | email_address: 'email1@email.com',
24 | },
25 | {
26 | first_name: 'First2',
27 | last_name: 'Last2',
28 | email_address: 'email2@email.com',
29 | },
30 | {
31 | first_name: 'First3',
32 | last_name: 'Last3',
33 | email_address: 'email3@email.com',
34 | },
35 | ],
36 | };
37 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/__fixtures__/duplicateHeaders.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import { EOL } from 'os';
3 | import { PathAndContent } from './helpers';
4 | import { RowMap } from '../../src';
5 |
6 | export const duplicateHeaders: PathAndContent = {
7 | path: resolve(__dirname, 'tmp', 'duplicate_header.csv'),
8 |
9 | content: [
10 | 'first_name,first_name,email_address,address',
11 | 'First1,First1,email1@email.com,"1 Street St, State ST, 88888"',
12 | ].join(EOL),
13 |
14 | parsed: [],
15 | };
16 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/__fixtures__/emptyRows.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import { EOL } from 'os';
3 | import { PathAndContent } from './helpers';
4 | import { RowMap } from '../../src';
5 |
6 | export const emptyRows: PathAndContent = {
7 | path: resolve(__dirname, 'tmp', 'empty_rows.csv'),
8 |
9 | content: ['first_name,last_name,email_address', '"","",""', '"","",""', '"","",', '"",,""', ',,', ''].join(EOL),
10 |
11 | parsed: [
12 | {
13 | first_name: '',
14 | last_name: '',
15 | email_address: '',
16 | },
17 | {
18 | first_name: '',
19 | last_name: '',
20 | email_address: '',
21 | },
22 | {
23 | first_name: '',
24 | last_name: '',
25 | email_address: '',
26 | },
27 | {
28 | first_name: '',
29 | last_name: '',
30 | email_address: '',
31 | },
32 | {
33 | first_name: '',
34 | last_name: '',
35 | email_address: '',
36 | },
37 | ],
38 | };
39 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/__fixtures__/headerColumnMismatch.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import { EOL } from 'os';
3 | import { PathAndContent } from './helpers';
4 | import { RowMap } from '../../src';
5 |
6 | export const headerColumnMismatch: PathAndContent = {
7 | path: resolve(__dirname, 'tmp', 'header_column_mismatch.csv'),
8 |
9 | content: [
10 | 'first_name,last_name,email_address,address',
11 | 'First1,Last1,email1@email.com,"1 Street St, State ST, 88888", extra column',
12 | ].join(EOL),
13 |
14 | parsed: [
15 | {
16 | first_name: 'First1',
17 | last_name: 'Last1',
18 | email_address: 'email1@email.com',
19 | address: '1 Street St, State ST, 88888',
20 | },
21 | ],
22 | };
23 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/__fixtures__/index.ts:
--------------------------------------------------------------------------------
1 | import { existsSync, mkdirSync, writeFileSync } from 'fs';
2 | import * as path from 'path';
3 | import { PathAndContent } from './helpers';
4 | import { Row } from '../../src';
5 |
6 | export * from './alternateEncoding';
7 | export * from './noHeadersAndQuotes';
8 | export * from './skipLines';
9 | export * from './withHeaders';
10 | export * from './withHeadersAndQuotes';
11 | export * from './withHeadersAndAlternateQuote';
12 | export * from './withHeadersAndMissingColumns';
13 | export * from './withHeadersAlternateDelimiter';
14 | export * from './withHeadersAndSkippedLines';
15 | export * from './headerColumnMismatch';
16 | export * from './malformed';
17 | export * from './trailingComma';
18 | export * from './emptyRows';
19 | export * from './duplicateHeaders';
20 | export * from './RecordingStream';
21 | export * from './helpers';
22 |
23 | const mkDirIfNotExists = (filePath: string): void => {
24 | const dir = path.dirname(filePath);
25 | if (!existsSync(dir)) {
26 | mkdirSync(dir);
27 | }
28 | };
29 |
30 | export const write = (opts: PathAndContent): void => {
31 | mkDirIfNotExists(opts.path);
32 | writeFileSync(opts.path, opts.content);
33 | };
34 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/__fixtures__/malformed.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import { EOL } from 'os';
3 | import { PathAndContent } from './helpers';
4 |
5 | export const malformed: PathAndContent = {
6 | path: resolve(__dirname, 'tmp', 'malformed.csv'),
7 |
8 | content: [
9 | 'first_name,last_name,email_address,address',
10 | '"First1"a ", Last1 ,email1@email.com,"1 Street St, State ST, 88888"',
11 | 'First2,Last2,email2@email.com,"2 Street St, State ST, 88888"',
12 | ].join(EOL),
13 |
14 | parsed: [],
15 | };
16 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/__fixtures__/noHeadersAndQuotes.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import { EOL } from 'os';
3 | import { PathAndContent } from './helpers';
4 | import { RowArray } from '../../src';
5 |
6 | export const noHeadersAndQuotes: PathAndContent> = {
7 | path: resolve(__dirname, 'tmp', 'no_headers_and_quotes.csv'),
8 |
9 | content: [
10 | 'First1,Last1,email1@email.com,"1 Street St, State ST, 88888"',
11 | 'First2,Last2,email2@email.com,"2 Street St, State ST, 88888"',
12 | 'First3,Last3,email3@email.com,"3 Street St, State ST, 88888"',
13 | 'First4,Last4,email4@email.com,"4 Street St, State ST, 88888"',
14 | 'First5,Last5,email5@email.com,"5 Street St, State ST, 88888"',
15 | 'First6,Last6,email6@email.com,"6 Street St, State ST, 88888"',
16 | 'First7,Last7,email7@email.com,"7 Street St, State ST, 88888"',
17 | 'First8,Last8,email8@email.com,"8 Street St, State ST, 88888"',
18 | 'First9,Last9,email9@email.com,"9 Street St, State ST, 88888"',
19 | ].join(EOL),
20 |
21 | parsed: [
22 | ['First1', 'Last1', 'email1@email.com', '1 Street St, State ST, 88888'],
23 | ['First2', 'Last2', 'email2@email.com', '2 Street St, State ST, 88888'],
24 | ['First3', 'Last3', 'email3@email.com', '3 Street St, State ST, 88888'],
25 | ['First4', 'Last4', 'email4@email.com', '4 Street St, State ST, 88888'],
26 | ['First5', 'Last5', 'email5@email.com', '5 Street St, State ST, 88888'],
27 | ['First6', 'Last6', 'email6@email.com', '6 Street St, State ST, 88888'],
28 | ['First7', 'Last7', 'email7@email.com', '7 Street St, State ST, 88888'],
29 | ['First8', 'Last8', 'email8@email.com', '8 Street St, State ST, 88888'],
30 | ['First9', 'Last9', 'email9@email.com', '9 Street St, State ST, 88888'],
31 | ],
32 | };
33 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/__fixtures__/skipLines.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import { EOL } from 'os';
3 | import { PathAndContent } from './helpers';
4 | import { RowArray } from '../../src';
5 |
6 | export const skipLines: PathAndContent = {
7 | path: resolve(__dirname, 'tmp', 'skip_lines.csv'),
8 |
9 | content: [
10 | 'Skip First1,Last1,skip.email2@email.com',
11 | 'Skip First2,Skip Last2,skip.email2@email.com',
12 | 'First1,Last1,email1@email.com',
13 | 'First2,Last2,email2@email.com',
14 | 'First3,Last3,email3@email.com',
15 | 'First4,Last4,email4@email.com',
16 | 'First5,Last5,email5@email.com',
17 | 'First6,Last6,email6@email.com',
18 | 'First7,Last7,email7@email.com',
19 | 'First8,Last8,email8@email.com',
20 | 'First9,Last9,email9@email.com',
21 | ].join(EOL),
22 |
23 | parsed: [
24 | ['First1', 'Last1', 'email1@email.com'],
25 | ['First2', 'Last2', 'email2@email.com'],
26 | ['First3', 'Last3', 'email3@email.com'],
27 | ['First4', 'Last4', 'email4@email.com'],
28 | ['First5', 'Last5', 'email5@email.com'],
29 | ['First6', 'Last6', 'email6@email.com'],
30 | ['First7', 'Last7', 'email7@email.com'],
31 | ['First8', 'Last8', 'email8@email.com'],
32 | ['First9', 'Last9', 'email9@email.com'],
33 | ],
34 | };
35 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/__fixtures__/tmp/malformed.csv:
--------------------------------------------------------------------------------
1 | first_name,last_name,email_address,address
2 | "First1"a ", Last1 ,email1@email.com,"1 Street St, State ST, 88888"
3 | First2,Last2,email2@email.com,"2 Street St, State ST, 88888"
--------------------------------------------------------------------------------
/packages/parse/__tests__/__fixtures__/tmp/with_headers.csv:
--------------------------------------------------------------------------------
1 | first_name,last_name,email_address
2 | First1,Last1,email1@email.com
3 | First2,Last2,email2@email.com
4 | First3,Last3,email3@email.com
5 | First4,Last4,email4@email.com
6 | First5,Last5,email5@email.com
7 | First6,Last6,email6@email.com
8 | First7,Last7,email7@email.com
9 | First8,Last8,email8@email.com
10 | First9,Last9,email9@email.com
--------------------------------------------------------------------------------
/packages/parse/__tests__/__fixtures__/withHeaders.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import { EOL } from 'os';
3 | import { PathAndContent } from './helpers';
4 | import { RowMap } from '../../src';
5 |
6 | export const withHeaders: PathAndContent> = {
7 | path: resolve(__dirname, 'tmp', 'with_headers.csv'),
8 |
9 | content: [
10 | 'first_name,last_name,email_address',
11 | 'First1,Last1,email1@email.com',
12 | 'First2,Last2,email2@email.com',
13 | 'First3,Last3,email3@email.com',
14 | 'First4,Last4,email4@email.com',
15 | 'First5,Last5,email5@email.com',
16 | 'First6,Last6,email6@email.com',
17 | 'First7,Last7,email7@email.com',
18 | 'First8,Last8,email8@email.com',
19 | 'First9,Last9,email9@email.com',
20 | ].join(EOL),
21 |
22 | parsed: [
23 | {
24 | first_name: 'First1',
25 | last_name: 'Last1',
26 | email_address: 'email1@email.com',
27 | },
28 | {
29 | first_name: 'First2',
30 | last_name: 'Last2',
31 | email_address: 'email2@email.com',
32 | },
33 | {
34 | first_name: 'First3',
35 | last_name: 'Last3',
36 | email_address: 'email3@email.com',
37 | },
38 | {
39 | first_name: 'First4',
40 | last_name: 'Last4',
41 | email_address: 'email4@email.com',
42 | },
43 | {
44 | first_name: 'First5',
45 | last_name: 'Last5',
46 | email_address: 'email5@email.com',
47 | },
48 | {
49 | first_name: 'First6',
50 | last_name: 'Last6',
51 | email_address: 'email6@email.com',
52 | },
53 | {
54 | first_name: 'First7',
55 | last_name: 'Last7',
56 | email_address: 'email7@email.com',
57 | },
58 | {
59 | first_name: 'First8',
60 | last_name: 'Last8',
61 | email_address: 'email8@email.com',
62 | },
63 | {
64 | first_name: 'First9',
65 | last_name: 'Last9',
66 | email_address: 'email9@email.com',
67 | },
68 | ],
69 | };
70 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/__fixtures__/withHeadersAndMissingColumns.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import { EOL } from 'os';
3 | import { PathAndContent } from './helpers';
4 | import { RowMap } from '../../src';
5 |
6 | export const withHeadersAndMissingColumns: PathAndContent> = {
7 | path: resolve(__dirname, 'tmp', 'with_headers_and_missing_columns.csv'),
8 |
9 | content: [
10 | 'first_name,last_name,email_address,address',
11 | 'First1,Last1,email1@email.com,address1',
12 | 'First2,Last2,email2@email.com',
13 | 'First3,Last3,email3@email.com,address2',
14 | ].join(EOL),
15 |
16 | parsed: [
17 | {
18 | first_name: 'First1',
19 | last_name: 'Last1',
20 | email_address: 'email1@email.com',
21 | address: 'address1',
22 | },
23 | {
24 | first_name: 'First2',
25 | last_name: 'Last2',
26 | email_address: 'email2@email.com',
27 | address: null,
28 | },
29 | {
30 | first_name: 'First3',
31 | last_name: 'Last3',
32 | email_address: 'email3@email.com',
33 | address: 'address2',
34 | },
35 | ],
36 | };
37 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/issues/__fixtures__/issue87.csv:
--------------------------------------------------------------------------------
1 | a,b
2 | XXXXXX,XXXXXX
3 | XXXXXX,XXXXXX
4 | XXXXXX,XXXXXX
5 | XXXXXX,XXXXXX
6 | XXXXXX,XXXXXX
7 | XXXXXX,XXXXXX
8 | XXXXXX,XXXXXX
9 | XXXXXX,XXXXXX
10 | XXXXXX,XXXXXX
11 | XXXXXX,XXXXXX
12 | XXXXXX,XXXXXX
13 | XXXXXX,XXXXXX
14 | XXXXXX,XXXXXX
15 | XXXXXX,XXXXXX
16 | XXXXXX,XXXXXX
17 | XXXXXX,XXXXXX
18 | XXXXXX,XXXXXX
19 | XXXXXX,XXXXXX
20 | XXXXXX,XXXXXX
21 | XXXXXX,XXXXXX
22 | XXXXXX,XXXXXX
23 | XXXXXX,XXXXXX
24 | XXXXXX,XXXXXX
25 | XXXXXX,XXXXXX
26 | XXXXXX,XXXXXX
27 | XXXXXX,XXXXXX
28 | XXXXXX,XXXXXX
29 | XXXXXX,XXXXXX
30 | XXXXXX,XXXXXX
31 | XXXXXX,XXXXXX
32 | XXXXXX,XXXXXX
33 | XXXXXX,XXXXXX
34 | XXXXXX,XXXXXX
35 | XXXXXX,XXXXXX
36 | XXXXXX,XXXXXX
37 | XXXXXX,XXXXXX
38 | XXXXXX,XXXXXX
39 | XXXXXX,XXXXXX
40 | XXXXXX,XXXXXX
41 | XXXXXX,XXXXXX
42 | XXXXXX,XXXXXX
43 | XXXXXX,XXXXXX
44 | XXXXXX,XXXXXX
45 | XXXXXX,XXXXXX
46 | XXXXXX,XXXXXX
47 | XXXXXX,XXXXXX
48 | XXXXXX,XXXXXX
49 | XXXXXX,XXXXXX
50 | XXXXXX,XXXXXX
51 | XXXXXX,XXXXXX
52 | XXXXXX,XXXXXX
53 | XXXXXX,XXXXXX
54 | XXXXXX,XXXXXX
55 | XXXXXX,XXXXXX
56 | XXXXXX,XXXXXX
57 | XXXXXX,XXXXXX
58 | XXXXXX,XXXXXX
59 | XXXXXX,XXXXXX
60 | XXXXXX,XXXXXX
61 | XXXXXX,XXXXXX
62 | XXXXXX,XXXXXX
63 | XXXXXX,XXXXXX
64 | XXXXXX,XXXXXX
65 | XXXXXX,XXXXXX
66 | XXXXXX,XXXXXX
67 | XXXXXX,XXXXXX
68 | XXXXXX,XXXXXX
69 | XXXXXX,XXXXXX
70 | XXXXXX,XXXXXX
71 | XXXXXX,XXXXXX
72 | XXXXXX,XXXXXX
73 | XXXXXX,XXXXXX
74 | XXXXXX,XXXXXX
75 | XXXXXX,XXXXXX
76 | XXXXXX,XXXXXX
77 | XXXXXX,XXXXXX
78 | XXXXXX,XXXXXX
79 | XXXXXX,XXXXXX
80 | XXXXXX,XXXXXX
81 | XXXXXX,XXXXXX
82 | XXXXXX,XXXXXX
83 | XXXXXX,XXXXXX
84 | XXXXXX,XXXXXX
85 | XXXXXX,XXXXXX
86 | XXXXXX,XXXXXX
87 | XXXXXX,XXXXXX
88 | XXXXXX,XXXXXX
89 | XXXXXX,XXXXXX
90 | XXXXXX,XXXXXX
91 | XXXXXX,XXXXXX
92 | XXXXXX,XXXXXX
93 | XXXXXX,XXXXXX
94 | XXXXXX,XXXXXX
95 | XXXXXX,XXXXXX
96 | XXXXXX,XXXXXX
97 | XXXXXX,XXXXXX
98 | XXXXXX,XXXXXX
99 | XXXXXX,XXXXXX
100 | XXXXXX,XXXXXX
--------------------------------------------------------------------------------
/packages/parse/__tests__/issues/issue102.spec.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import { parseFile } from '../../src';
3 |
4 | describe('Issue #102 - https://github.com/C2FO/fast-csv/issues/102', () => {
5 | const row = [
6 | '123456',
7 | '123456',
8 | '2018-02-01T16:05:16Z',
9 | '7',
10 | '80428',
11 | '65756',
12 | 'Unquoted_String_With_Underscores_Hypens And_Spaces And-Numbers 1',
13 | '{"JSON":"DATA"}',
14 | ];
15 |
16 | it('parse all rows', () => {
17 | return new Promise((res, rej) => {
18 | let receivedRows = 0;
19 | parseFile(resolve(__dirname, '__fixtures__', 'issue102.csv'))
20 | .on('data-invalid', () => {
21 | return rej(new Error('Should not have received data-invalid event'));
22 | })
23 | .on('data', (r) => {
24 | receivedRows += 1;
25 | if (receivedRows % 1000 !== 0) {
26 | return;
27 | }
28 | expect(r).toEqual(row);
29 | })
30 | .on('error', (err) => {
31 | return rej(err);
32 | })
33 | .on('end', (rowCount: number) => {
34 | expect(rowCount).toBe(100000);
35 | expect(receivedRows).toBe(rowCount);
36 | res(() => {});
37 | });
38 | });
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/issues/issue131.spec.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import * as csv from '../../src';
3 |
4 | describe('Issue #131 - https://github.com/C2FO/fast-csv/issues/131', () => {
5 | const csvWithBom = [
6 | '\ufefffirst_name,last_name,email_address,address',
7 | 'First1,Last1,email1@email.com,"1 Street St, State ST, 88888"',
8 | ].join(EOL);
9 |
10 | it('should parse a csv with a UTF-8 Byte Order Mark', () => {
11 | return new Promise((res, rej) => {
12 | const actual: csv.RowMap[] = [];
13 | csv.parseString(csvWithBom, { headers: true })
14 | .on('error', rej)
15 | .on('data', (data) => {
16 | return actual.push(data);
17 | })
18 | .on('end', (count: number) => {
19 | expect(actual[0].first_name).toBe('First1');
20 | expect(count).toBe(actual.length);
21 | res(() => {});
22 | });
23 | });
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/issues/issue150.spec.ts:
--------------------------------------------------------------------------------
1 | import { Parser } from '../../src/parser';
2 | import { ParserOptions } from '../../src/ParserOptions';
3 |
4 | describe('Issue #150 - https://github.com/C2FO/fast-csv/issues/150', () => {
5 | const createParser = (parserOptions = {}) => {
6 | return new Parser(new ParserOptions(parserOptions));
7 | };
8 | const runParser = (data: string, hasMoreData: boolean, parser: Parser) => {
9 | return parser.parse(data, hasMoreData);
10 | };
11 |
12 | it('should not parse a row if a new line is a CR and there is more data', () => {
13 | const data = 'first_name,last_name,email_address\r';
14 | const myParser = createParser({});
15 | const parsedData = runParser(data, true, myParser);
16 | expect(parsedData).toEqual({
17 | line: 'first_name,last_name,email_address\r',
18 | rows: [],
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/issues/issue174.spec.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { ParserOptionsArgs } from '../../src';
3 | import { Parser } from '../../src/parser';
4 | import { ParserOptions } from '../../src/ParserOptions';
5 |
6 | describe('Issue #174 - https://github.com/C2FO/fast-csv/issues/174', () => {
7 | const createParser = (parserOptions: ParserOptionsArgs = {}) => {
8 | return new Parser(new ParserOptions(parserOptions));
9 | };
10 | const runParser = (data: string, hasMoreData: boolean, parser: Parser) => {
11 | return parser.parse(data, hasMoreData);
12 | };
13 |
14 | const CSV_CONTENT = ['f1,f2,f3', '1,text, a1', '2,text, a2 '].join(EOL);
15 |
16 | it('skip trailing whitespace after a quoted field', () => {
17 | const parser = createParser({ headers: true });
18 | const parsedData = runParser(CSV_CONTENT, false, parser);
19 | expect(parsedData).toEqual({
20 | line: '',
21 | rows: [
22 | ['f1', 'f2', 'f3'],
23 | ['1', 'text', ' a1'],
24 | ['2', 'text', ' a2 '],
25 | ],
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/issues/issue214.spec.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import * as csv from '../../src';
3 |
4 | describe('Issue #214 - https://github.com/C2FO/fast-csv/issues/214', () => {
5 | const CSV_CONTENT = [
6 | 'firstName,lastName,emailAddress',
7 | 'First1,Last1,email1@email.com',
8 | 'First2,Last2,email2@email.com',
9 | 'First3,Last3,email3@email.com',
10 | 'First4,Last4,email4@email.com',
11 | ].join(EOL);
12 |
13 | const expectedRows = [
14 | { firstName: 'First1', lastName: 'Last1', emailAddress: 'email1@email.com' },
15 | { firstName: 'First2', lastName: 'Last2', emailAddress: 'email2@email.com' },
16 | { firstName: 'First3', lastName: 'Last3', emailAddress: 'email3@email.com' },
17 | { firstName: 'First4', lastName: 'Last4', emailAddress: 'email4@email.com' },
18 | ];
19 |
20 | it('should emit data when using the on method', () => {
21 | return new Promise((res, rej) => {
22 | const rows: csv.RowMap[] = [];
23 | csv.parseString(CSV_CONTENT, { headers: true })
24 | .on('data', (r: csv.RowMap) => {
25 | return rows.push(r);
26 | })
27 | .on('error', rej)
28 | .on('end', (count: number) => {
29 | expect(rows).toEqual(expectedRows);
30 | expect(count).toBe(expectedRows.length);
31 | res(() => {});
32 | });
33 | });
34 | });
35 |
36 | it('should emit data when using the addListener method', () => {
37 | return new Promise((res, rej) => {
38 | const rows: csv.RowMap[] = [];
39 | csv.parseString(CSV_CONTENT, { headers: true })
40 | .addListener('data', (r: csv.RowMap) => {
41 | return rows.push(r);
42 | })
43 | .on('error', rej)
44 | .on('end', (count: number) => {
45 | expect(rows).toEqual(expectedRows);
46 | expect(count).toBe(expectedRows.length);
47 | res(() => {});
48 | });
49 | });
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/issues/issue223.spec.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { Parser } from '../../src/parser';
3 | import { ParserOptions } from '../../src/ParserOptions';
4 |
5 | describe('Issue #223 - https://github.com/C2FO/fast-csv/issues/223', () => {
6 | const createParser = (parserOptions = {}) => {
7 | return new Parser(new ParserOptions(parserOptions));
8 | };
9 | const runParser = (data: string, hasMoreData: boolean, parser: Parser) => {
10 | return parser.parse(data, hasMoreData);
11 | };
12 |
13 | it('skip trailing whitespace after a quoted field', () => {
14 | const CSV_CONTENT = ['"ABC" ,"DEFG" ,12345,"HI"', '"JKLM" ,"NOP" ,67890,"QR" '].join(EOL);
15 | const parser = createParser();
16 | const parsedData = runParser(CSV_CONTENT, false, parser);
17 | expect(parsedData).toEqual({
18 | line: '',
19 | rows: [
20 | ['ABC', 'DEFG', '12345', 'HI'],
21 | ['JKLM', 'NOP', '67890', 'QR'],
22 | ],
23 | });
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/issues/issue317.spec.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parseString, RowMap, RowArray } from '../../src';
3 |
4 | describe('Issue #317 - https://github.com/C2FO/fast-csv/issues/317', () => {
5 | const CSV_CONTENT = ['header1,header2', 'col1', 'col2,col2', 'col3', 'col4,col4', 'col5,col5', 'col6,col6'].join(
6 | EOL,
7 | );
8 | const expectedInvalidRows = [['col3']];
9 | const expectedRows = [
10 | { header1: 'col4', header2: 'col4' },
11 | { header1: 'col5', header2: 'col5' },
12 | { header1: 'col6', header2: 'col6' },
13 | ];
14 |
15 | it('skip trailing whitespace after a quoted field', () => {
16 | return new Promise((res, rej) => {
17 | const invalid: RowArray[] = [];
18 | const rows: RowMap[] = [];
19 | parseString(CSV_CONTENT, { headers: true, skipRows: 2, strictColumnHandling: true, maxRows: 4 })
20 | .on('data-invalid', (row: RowArray) => {
21 | return invalid.push(row);
22 | })
23 | .on('data', (r: RowMap) => {
24 | return rows.push(r);
25 | })
26 | .on('error', rej)
27 | .on('end', (count: number) => {
28 | expect(rows).toEqual(expectedRows);
29 | expect(invalid).toEqual(expectedInvalidRows);
30 | expect(count).toBe(expectedRows.length + invalid.length);
31 | res(() => {});
32 | });
33 | });
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/issues/issue340.spec.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parseString, RowMap, RowArray } from '../../src';
3 |
4 | describe('Issue #340 - https://github.com/C2FO/fast-csv/issues/340', () => {
5 | const CSV_CONTENT = ['Col1', `"A '"Good'" row''"`, 'Row 2'].join(EOL);
6 | const expectedRows = [{ Col1: `A "Good" row'` }, { Col1: 'Row 2' }];
7 |
8 | it('handle a trailing escape', () => {
9 | return new Promise((res, rej) => {
10 | const invalid: RowArray[] = [];
11 | const rows: RowMap[] = [];
12 | parseString(CSV_CONTENT, { headers: true, escape: "'" })
13 | .on('data-invalid', (row: RowArray) => {
14 | return invalid.push(row);
15 | })
16 | .on('data', (r: RowMap) => {
17 | return rows.push(r);
18 | })
19 | .on('error', rej)
20 | .on('end', (count: number) => {
21 | expect(rows).toEqual(expectedRows);
22 | expect(invalid).toHaveLength(0);
23 | expect(count).toBe(expectedRows.length + invalid.length);
24 | res(() => {});
25 | });
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/issues/issue356.spec.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parseString, RowMap, RowArray } from '../../src';
3 |
4 | describe('Issue #356 - https://github.com/C2FO/fast-csv/issues/356', () => {
5 | interface InputRow {
6 | clicks: string;
7 | }
8 |
9 | interface ClicksRow {
10 | clicks?: number;
11 | }
12 |
13 | const CSV_CONTENT = ['clicks', `1`, '2', 'a'].join(EOL);
14 | const expectedRows = [{ clicks: 1 }, { clicks: 2 }, {}];
15 |
16 | it('allow transforming to any object shape', () => {
17 | return new Promise((res, rej) => {
18 | const invalid: RowArray[] = [];
19 | const rows: RowMap[] = [];
20 | parseString(CSV_CONTENT, { headers: true, escape: "'" })
21 | .transform((row: InputRow) => {
22 | const clicks = parseInt(row.clicks, 10);
23 | if (Number.isInteger(clicks)) {
24 | return { clicks };
25 | }
26 | return {};
27 | })
28 | .on('data-invalid', (row: RowArray) => {
29 | return invalid.push(row);
30 | })
31 | .on('data', (r: ClicksRow) => {
32 | return rows.push(r);
33 | })
34 | .on('error', rej)
35 | .on('end', (count: number) => {
36 | expect(rows).toEqual(expectedRows);
37 | expect(invalid).toHaveLength(0);
38 | expect(count).toBe(expectedRows.length + invalid.length);
39 | res(() => {});
40 | });
41 | });
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/issues/issue540.spec.ts:
--------------------------------------------------------------------------------
1 | import { EOL } from 'os';
2 | import { parseString, RowMap, RowArray } from '../../src';
3 |
4 | describe('Issue #540 - https://github.com/C2FO/fast-csv/issues/540', () => {
5 | const CSV_CONTENT = [
6 | ' , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -',
7 | ].join(EOL);
8 |
9 | const expectedRows = [
10 | [
11 | ' , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,' +
12 | ' , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,' +
13 | ' , , , , , , , , , , , , , , -',
14 | ],
15 | ];
16 |
17 | it('allow transforming to any object shape', () => {
18 | return new Promise((res, rej) => {
19 | const invalid: RowArray[] = [];
20 | const rows: RowMap[] = [];
21 | parseString(CSV_CONTENT, { ignoreEmpty: true, delimiter: '\t' })
22 | .on('data-invalid', (row: RowArray) => {
23 | return invalid.push(row);
24 | })
25 | .on('data', (r) => {
26 | return rows.push(r);
27 | })
28 | .on('error', rej)
29 | .on('end', (count: number) => {
30 | expect(rows).toEqual(expectedRows);
31 | expect(invalid).toHaveLength(0);
32 | expect(count).toBe(expectedRows.length + invalid.length);
33 | res(() => {});
34 | });
35 | });
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/issues/issue68.spec.ts:
--------------------------------------------------------------------------------
1 | import * as path from 'path';
2 | import * as domain from 'domain';
3 | import * as csv from '../../src';
4 |
5 | describe('Issue #68 - https://github.com/C2FO/fast-csv/issues/68', () => {
6 | it('should handle bubble up parse errors properly', () => {
7 | return new Promise((res) => {
8 | const d = domain.create();
9 | let called = false;
10 | d.on('error', (err: Error) => {
11 | d.exit();
12 | if (called) {
13 | return;
14 | }
15 | called = true;
16 | expect(err.message).toMatch(/^Parse Error/);
17 | res(() => {});
18 | });
19 | d.run(() => {
20 | return csv
21 | .parseFile(path.resolve(__dirname, '__fixtures__', 'issue68-invalid.tsv'), {
22 | headers: true,
23 | delimiter: '\t',
24 | })
25 | .on('data', () => {
26 | return null;
27 | });
28 | });
29 | });
30 | });
31 |
32 | it('should handle bubble up data errors properly', () => {
33 | return new Promise((res) => {
34 | const d = domain.create();
35 | let called = false;
36 | d.on('error', (err: Error) => {
37 | d.exit();
38 | if (called) {
39 | throw err;
40 | }
41 | called = true;
42 | expect(err.message).toBe('Data error');
43 | res(() => {});
44 | });
45 | d.run(() => {
46 | let count = 0;
47 | csv.parseFile(path.resolve(__dirname, '__fixtures__', 'issue68.tsv'), {
48 | headers: true,
49 | delimiter: '\t',
50 | }).on('data', () => {
51 | count += 1;
52 | if (count % 1001 === 0) {
53 | throw new Error('Data error');
54 | }
55 | });
56 | });
57 | });
58 | });
59 | });
60 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/issues/issue87.spec.ts:
--------------------------------------------------------------------------------
1 | import * as fs from 'fs';
2 | import * as path from 'path';
3 | import { Transform, TransformCallback } from 'stream';
4 | import * as csv from '../../src';
5 |
6 | describe('Issue #87 - https://github.com/C2FO/fast-csv/issues/87', () => {
7 | class MyStream extends Transform {
8 | public rowCount: number;
9 |
10 | public constructor() {
11 | super({
12 | objectMode: true,
13 | highWaterMark: 16,
14 | transform: (...args) => {
15 | return this.transform(...args);
16 | },
17 | flush: (done) => {
18 | return done();
19 | },
20 | });
21 | this.rowCount = 0;
22 | }
23 |
24 | private transform(data: csv.Row, encoding: string, done: TransformCallback) {
25 | this.rowCount += 1;
26 | if (this.rowCount % 2 === 0) {
27 | setTimeout(() => {
28 | return done();
29 | }, 10);
30 | } else {
31 | done();
32 | }
33 | }
34 | }
35 |
36 | it('should not emit end until data is flushed from source', () => {
37 | return new Promise((res, rej) => {
38 | const myStream = new MyStream();
39 |
40 | fs.createReadStream(path.resolve(__dirname, '__fixtures__', 'issue87.csv'))
41 | .pipe(csv.parse({ headers: true }))
42 | .on('error', rej)
43 | .pipe(myStream)
44 | .on('error', rej)
45 | .on('finish', () => {
46 | expect(myStream.rowCount).toBe(99);
47 | res(() => {});
48 | });
49 | });
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/parse.spec.ts:
--------------------------------------------------------------------------------
1 | import * as fs from 'fs';
2 | import { collectData, expectParsed, withHeaders, write } from './__fixtures__';
3 | import { CsvParserStream, parse, parseFile, parseStream, parseString } from '../src';
4 |
5 | describe('.parse', () => {
6 | it('should accept a stream', () => {
7 | expect(parse({ headers: true })).toBeInstanceOf(CsvParserStream);
8 | });
9 | });
10 |
11 | describe('.parseStream', () => {
12 | it('should accept a stream', async () => {
13 | write(withHeaders);
14 | const stream = parseStream(fs.createReadStream(withHeaders.path), { headers: true });
15 | await expectParsed(collectData(stream), withHeaders.parsed);
16 | });
17 | });
18 |
19 | describe('.parseFile', () => {
20 | it('parse a csv from the given path', async () => {
21 | write(withHeaders);
22 | const stream = parseFile(withHeaders.path, { headers: true });
23 | await expectParsed(collectData(stream), withHeaders.parsed);
24 | });
25 | });
26 |
27 | describe('.parseString', () => {
28 | it('should accept a csv string', () => {
29 | return expectParsed(
30 | collectData(parseString(withHeaders.content as string, { headers: true })),
31 | withHeaders.parsed,
32 | );
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/packages/parse/__tests__/parser/column/ColumnParser.spec.ts:
--------------------------------------------------------------------------------
1 | import * as sinon from 'sinon';
2 | import { ParserOptions } from '../../../src';
3 | import { ColumnParser } from '../../../src/parser/column';
4 | import { Scanner } from '../../../src/parser';
5 |
6 | describe('ColumnParser', () => {
7 | describe('#parse', () => {
8 | describe('with un-quoted data', () => {
9 | it('should call the nonQuotedColumnParser', () => {
10 | const line = 'HELLO';
11 | const parserOptions = new ParserOptions({});
12 | const lineParser = new ColumnParser(parserOptions);
13 | const scanner = new Scanner({ line, parserOptions, hasMoreData: true });
14 | const expectedResult = { scanner, items: [] };
15 | const mock = sinon.mock(lineParser.nonQuotedColumnParser);
16 | mock.expects('parse').once().withArgs(scanner).returns(expectedResult);
17 | expect(lineParser.parse(scanner)).toEqual(expectedResult);
18 | mock.verify();
19 | });
20 | });
21 | describe('with quoted data', () => {
22 | it('should call the quotedColumnParser', () => {
23 | const line = '"HELLO"';
24 | const parserOptions = new ParserOptions({});
25 | const lineParser = new ColumnParser(parserOptions);
26 | const scanner = new Scanner({ line, parserOptions, hasMoreData: true });
27 | const expectedResult = { scanner, items: [] };
28 | const mock = sinon.mock(lineParser.quotedColumnParser);
29 | mock.expects('parse').once().withArgs(scanner).returns(expectedResult);
30 | expect(lineParser.parse(scanner)).toEqual(expectedResult);
31 | mock.verify();
32 | });
33 | });
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/packages/parse/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fast-csv/parse",
3 | "version": "5.0.2",
4 | "description": "fast-csv parsing package",
5 | "keywords": [
6 | "csv",
7 | "parse",
8 | "fast-csv",
9 | "parser"
10 | ],
11 | "author": "doug-martin ",
12 | "homepage": "https://c2fo.github.io/fast-csv/docs/parsing/getting-started",
13 | "license": "MIT",
14 | "main": "build/src/index.js",
15 | "types": "build/src/index.d.ts",
16 | "directories": {
17 | "lib": "src",
18 | "test": "__tests__"
19 | },
20 | "files": [
21 | "build/src/**"
22 | ],
23 | "publishConfig": {
24 | "access": "public"
25 | },
26 | "repository": {
27 | "type": "git",
28 | "url": "git+https://github.com/C2FO/fast-csv.git",
29 | "directory": "packages/parse"
30 | },
31 | "scripts": {
32 | "prepublishOnly": "npm run build",
33 | "build": "npm run clean && npm run compile",
34 | "clean": "rm -rf ./build && rm -rf tsconfig.tsbuildinfo",
35 | "compile": "tsc"
36 | },
37 | "bugs": {
38 | "url": "https://github.com/C2FO/fast-csv/issues"
39 | },
40 | "dependencies": {
41 | "lodash.escaperegexp": "^4.1.2",
42 | "lodash.groupby": "^4.6.0",
43 | "lodash.isfunction": "^3.0.9",
44 | "lodash.isnil": "^4.0.0",
45 | "lodash.isundefined": "^3.0.1",
46 | "lodash.uniq": "^4.5.0"
47 | },
48 | "devDependencies": {
49 | "@types/lodash.escaperegexp": "4.1.9",
50 | "@types/lodash.groupby": "4.6.9",
51 | "@types/lodash.isfunction": "3.0.9",
52 | "@types/lodash.isnil": "4.0.9",
53 | "@types/lodash.isundefined": "3.0.9",
54 | "@types/lodash.partition": "4.6.9",
55 | "@types/lodash.uniq": "4.5.9",
56 | "@types/node": "^22.7.8",
57 | "@types/sinon": "17.0.4",
58 | "lodash.partition": "^4.6.0",
59 | "sinon": "19.0.2"
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/packages/parse/src/index.ts:
--------------------------------------------------------------------------------
1 | import * as fs from 'fs';
2 | import { Readable } from 'stream';
3 | import { ParserOptions, ParserOptionsArgs } from './ParserOptions';
4 | import { CsvParserStream } from './CsvParserStream';
5 | import { Row } from './types';
6 |
7 | export * from './types';
8 | export { CsvParserStream } from './CsvParserStream';
9 | export { ParserOptions, ParserOptionsArgs } from './ParserOptions';
10 |
11 | export const parse = (args?: ParserOptionsArgs): CsvParserStream => {
12 | return new CsvParserStream(new ParserOptions(args));
13 | };
14 |
15 | export const parseStream = (
16 | stream: NodeJS.ReadableStream,
17 | options?: ParserOptionsArgs,
18 | ): CsvParserStream => {
19 | return stream.pipe(new CsvParserStream(new ParserOptions(options)));
20 | };
21 |
22 | export const parseFile = (
23 | location: string,
24 | options: ParserOptionsArgs = {},
25 | ): CsvParserStream => {
26 | return fs.createReadStream(location).pipe(new CsvParserStream(new ParserOptions(options)));
27 | };
28 |
29 | export const parseString = (
30 | string: string,
31 | options?: ParserOptionsArgs,
32 | ): CsvParserStream => {
33 | const rs = new Readable();
34 | rs.push(string);
35 | rs.push(null);
36 | return rs.pipe(new CsvParserStream(new ParserOptions(options)));
37 | };
38 |
--------------------------------------------------------------------------------
/packages/parse/src/parser/Token.ts:
--------------------------------------------------------------------------------
1 | import { ParserOptions } from '../ParserOptions';
2 |
3 | export type MaybeToken = Token | null;
4 |
5 | export interface TokenArgs {
6 | token: string;
7 | startCursor: number;
8 | endCursor: number;
9 | }
10 |
11 | export class Token {
12 | public static isTokenRowDelimiter(token: Token): boolean {
13 | const content = token.token;
14 | return content === '\r' || content === '\n' || content === '\r\n';
15 | }
16 |
17 | public static isTokenCarriageReturn(token: Token, parserOptions: ParserOptions): boolean {
18 | return token.token === parserOptions.carriageReturn;
19 | }
20 |
21 | public static isTokenComment(token: Token, parserOptions: ParserOptions): boolean {
22 | return parserOptions.supportsComments && !!token && token.token === parserOptions.comment;
23 | }
24 |
25 | public static isTokenEscapeCharacter(token: Token, parserOptions: ParserOptions): boolean {
26 | return token.token === parserOptions.escapeChar;
27 | }
28 |
29 | public static isTokenQuote(token: Token, parserOptions: ParserOptions): boolean {
30 | return token.token === parserOptions.quote;
31 | }
32 |
33 | public static isTokenDelimiter(token: Token, parserOptions: ParserOptions): boolean {
34 | return token.token === parserOptions.delimiter;
35 | }
36 |
37 | public readonly token: string;
38 |
39 | public readonly startCursor: number;
40 |
41 | public readonly endCursor: number;
42 |
43 | public constructor(tokenArgs: TokenArgs) {
44 | this.token = tokenArgs.token;
45 | this.startCursor = tokenArgs.startCursor;
46 | this.endCursor = tokenArgs.endCursor;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/packages/parse/src/parser/column/ColumnFormatter.ts:
--------------------------------------------------------------------------------
1 | import { ParserOptions } from '../../ParserOptions';
2 |
3 | export class ColumnFormatter {
4 | public readonly format: (col: string) => string;
5 |
6 | public constructor(parserOptions: ParserOptions) {
7 | if (parserOptions.trim) {
8 | this.format = (col: string): string => {
9 | return col.trim();
10 | };
11 | } else if (parserOptions.ltrim) {
12 | this.format = (col: string): string => {
13 | return col.trimLeft();
14 | };
15 | } else if (parserOptions.rtrim) {
16 | this.format = (col: string): string => {
17 | return col.trimRight();
18 | };
19 | } else {
20 | this.format = (col: string): string => {
21 | return col;
22 | };
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/packages/parse/src/parser/column/ColumnParser.ts:
--------------------------------------------------------------------------------
1 | import { ParserOptions } from '../../ParserOptions';
2 | import { NonQuotedColumnParser } from './NonQuotedColumnParser';
3 | import { QuotedColumnParser } from './QuotedColumnParser';
4 | import { Scanner } from '../Scanner';
5 | import { Token } from '../Token';
6 |
7 | export class ColumnParser {
8 | private readonly parserOptions: ParserOptions;
9 |
10 | public readonly nonQuotedColumnParser: NonQuotedColumnParser;
11 |
12 | public readonly quotedColumnParser: QuotedColumnParser;
13 |
14 | public constructor(parserOptions: ParserOptions) {
15 | this.parserOptions = parserOptions;
16 | this.quotedColumnParser = new QuotedColumnParser(parserOptions);
17 | this.nonQuotedColumnParser = new NonQuotedColumnParser(parserOptions);
18 | }
19 |
20 | public parse(scanner: Scanner): string | null {
21 | const { nextNonSpaceToken } = scanner;
22 | if (nextNonSpaceToken !== null && Token.isTokenQuote(nextNonSpaceToken, this.parserOptions)) {
23 | scanner.advanceToToken(nextNonSpaceToken);
24 | return this.quotedColumnParser.parse(scanner);
25 | }
26 | return this.nonQuotedColumnParser.parse(scanner);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/packages/parse/src/parser/column/NonQuotedColumnParser.ts:
--------------------------------------------------------------------------------
1 | import { ParserOptions } from '../../ParserOptions';
2 | import { ColumnFormatter } from './ColumnFormatter';
3 | import { Scanner } from '../Scanner';
4 | import { Token } from '../Token';
5 |
6 | export class NonQuotedColumnParser {
7 | private readonly parserOptions: ParserOptions;
8 |
9 | private readonly columnFormatter: ColumnFormatter;
10 |
11 | public constructor(parserOptions: ParserOptions) {
12 | this.parserOptions = parserOptions;
13 | this.columnFormatter = new ColumnFormatter(parserOptions);
14 | }
15 |
16 | public parse(scanner: Scanner): string | null {
17 | if (!scanner.hasMoreCharacters) {
18 | return null;
19 | }
20 | const { parserOptions } = this;
21 | const characters = [];
22 | let nextToken = scanner.nextCharacterToken;
23 | for (; nextToken; nextToken = scanner.nextCharacterToken) {
24 | if (Token.isTokenDelimiter(nextToken, parserOptions) || Token.isTokenRowDelimiter(nextToken)) {
25 | break;
26 | }
27 | characters.push(nextToken.token);
28 | scanner.advancePastToken(nextToken);
29 | }
30 | return this.columnFormatter.format(characters.join(''));
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/packages/parse/src/parser/column/index.ts:
--------------------------------------------------------------------------------
1 | export { ColumnParser } from './ColumnParser';
2 | export { NonQuotedColumnParser } from './NonQuotedColumnParser';
3 | export { QuotedColumnParser } from './QuotedColumnParser';
4 | export { ColumnFormatter } from './ColumnFormatter';
5 |
--------------------------------------------------------------------------------
/packages/parse/src/parser/index.ts:
--------------------------------------------------------------------------------
1 | export { Parser } from './Parser';
2 | export { RowParser } from './RowParser';
3 | export { Scanner } from './Scanner';
4 | export { Token, MaybeToken } from './Token';
5 | export { ColumnParser, NonQuotedColumnParser, QuotedColumnParser } from './column';
6 |
--------------------------------------------------------------------------------
/packages/parse/src/transforms/index.ts:
--------------------------------------------------------------------------------
1 | export { RowTransformerValidator } from './RowTransformerValidator';
2 | export { HeaderTransformer } from './HeaderTransformer';
3 |
--------------------------------------------------------------------------------
/packages/parse/src/types.ts:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
2 | export type RowMap = Record;
3 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
4 | export type RowArray = V[];
5 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
6 | export type Row = RowMap | RowArray;
7 |
8 | export interface RowValidationResult {
9 | row: R | null;
10 | isValid: boolean;
11 | reason?: string;
12 | }
13 |
14 | export type RowValidatorCallback = (error: Error | null, result?: RowValidationResult) => void;
15 |
16 | export type RowTransformCallback = (error?: Error | null, row?: R) => void;
17 | export type SyncRowTransform = (row: I) => O;
18 | export type AsyncRowTransform = (row: I, cb: RowTransformCallback) => void;
19 | export type RowTransformFunction = SyncRowTransform | AsyncRowTransform;
20 |
21 | export const isSyncTransform = (
22 | transform: RowTransformFunction,
23 | ): transform is SyncRowTransform => {
24 | return transform.length === 1;
25 | };
26 |
27 | export type RowValidateCallback = (error?: Error | null, isValid?: boolean, reason?: string) => void;
28 |
29 | export type SyncRowValidate = (row: R) => boolean;
30 | export type AsyncRowValidate = (row: R, cb: RowValidateCallback) => void;
31 | export type RowValidate = AsyncRowValidate | SyncRowValidate;
32 |
33 | export const isSyncValidate = (validate: RowValidate): validate is SyncRowValidate => {
34 | return validate.length === 1;
35 | };
36 |
37 | export type HeaderArray = (string | undefined | null)[];
38 | export type HeaderTransformFunction = (headers: HeaderArray) => HeaderArray;
39 |
--------------------------------------------------------------------------------
/packages/parse/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.build.json",
3 | "compilerOptions": {
4 | "outDir": "./build",
5 | "rootDir": ".",
6 | "composite": true
7 | },
8 | "include": [
9 | "./src",
10 | "./__tests__"
11 | ],
12 | "exclude": [
13 | "node_modules",
14 | "dist"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base"
4 | ],
5 | "packageRules": [{
6 | "depTypeList": ["devDependencies"],
7 | "automerge": true
8 | }],
9 | "ignorePaths": [
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowUnreachableCode": false,
4 | "allowUnusedLabels": false,
5 | "declaration": true,
6 | "esModuleInterop": true,
7 | "forceConsistentCasingInFileNames": true,
8 | "lib": [
9 | "es2022"
10 | ],
11 | "module": "commonjs",
12 | "skipLibCheck": true,
13 | "noEmitOnError": true,
14 | "noFallthroughCasesInSwitch": true,
15 | "useUnknownInCatchVariables": false,
16 | "noImplicitReturns": true,
17 | "pretty": true,
18 | "sourceMap": true,
19 | "strict": true,
20 | "target": "es2022"
21 | },
22 | "exclude": [
23 | "node_modules",
24 | "documentation"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.build.json",
3 | "compilerOptions": {
4 | "baseUrl": ".",
5 | "paths": {
6 | "fast-csv": ["packages/fast-csv/src"],
7 | "@fast-csv/format": ["packages/format/src"],
8 | "@fast-csv/parse": ["packages/parse/src"]
9 | }
10 | },
11 | "references": [
12 | {"path": "./packages/fast-csv"},
13 | {"path": "./packages/format"},
14 | {"path": "./packages/parse"}
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------