npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@verifyhash/csv-lite

v0.1.1

Published

Zero-dependency RFC 4180 CSV parser and stringifier for Node.js: quoted fields, embedded delimiters/newlines, doubled-quote escapes, header-object mode, custom delimiters.

Readme

csv-lite

A tiny, zero-dependency, zero-network Node.js library for RFC 4180 CSV: parse a CSV string into rows (or objects), and turn rows back into CSV text with minimal, correct quoting. One CommonJS file (index.js), no install step, no I/O — drop it into any project and require it.

Spec reference: https://www.rfc-editor.org/rfc/rfc4180

Install

npm install @verifyhash/csv-lite

Published as @verifyhash/csv-lite; source lives in the verifyhash/libs monorepo. Zero runtime dependencies — you can also vendor the folder directly.

Who it's for

JavaScript/Node developers who need to read or write CSV correctly — quoted fields, commas and newlines inside quotes, "" escapes, ;/tab delimiters, CRLF vs LF — without pulling in a larger parser like csv-parse or papaparse and their footprint. Good for build scripts, CLIs, small ETL glue, tests, config import/export, and anywhere you want auditable, single-file CSV handling.

If you need to stream gigabyte files, sniff the delimiter automatically, coerce types, or handle malformed-quote recovery, use one of the full packages above. This library deliberately covers the well-formed RFC 4180 common case.

Install / use

No install — copy index.js, or require it directly:

const csv = require('./index.js');

// parse -> 2D array of strings
csv.parse('a,"b,c",d');
// [['a', 'b,c', 'd']]

// parse with header -> array of objects keyed by the first row
csv.parse('name,age\nAlice,30\nBob,25', { header: true });
// [{ name: 'Alice', age: '30' }, { name: 'Bob', age: '25' }]

// stringify a 2D array (quotes only where required)
csv.stringify([['x', 'y,z', 'q"1']]);
// 'x,"y,z","q""1"'

// stringify array-of-objects with an explicit column order
csv.stringify(
  [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }],
  { columns: ['name', 'age'] }
);
// 'name,age\nAlice,30\nBob,25'

// custom delimiter (semicolon, tab, pipe, ...)
csv.parse('a;b;c', { delimiter: ';' });   // [['a', 'b', 'c']]

Complements the browser-based /csv-to-json/ hub tool: same RFC 4180 rules, but as a reusable Node module.

API

parse(text, options) → string[][] | object[]

Parse CSV text into rows. Every value is returned as a string — no type coercion.

Options:

| option | default | meaning | | ----------- | ------- | -------------------------------------------------------------- | | delimiter | ',' | Single-character field separator (e.g. ';', '\t', '\|'). | | header | false | When true, use the first row as keys and return objects. |

What it handles per RFC 4180:

  • Quoted fields — a field wrapped in "..."; the delimiter, CR, LF, and CRLF are literal data inside the quotes.
  • Embedded delimitersa,"b,c",d['a', 'b,c', 'd'].
  • Embedded newlines"line1\nline2" stays one field; the row is not split.
  • Doubled-quote escapes"" inside a quoted field is one literal ".
  • CRLF and LF record separators, including mixed within one document.
  • A single trailing newline is ignored — it does not produce an extra empty record. (A blank line in the middle of the data is a real one-field row [''].)
  • Empty input ('') returns [].

With header: true, the first row becomes the object keys and the remaining rows become objects. A header-only document returns [].

stringify(rows, options) → string

Serialize rows to CSV text. Output uses LF (\n) record separators and has no trailing newline.

Options:

| option | default | meaning | | ----------- | ------- | ------------------------------------------------------------------------- | | delimiter | ',' | Single-character field separator. | | columns | — | When given, rows is an array of objects; emits a header row of these names first, then projects each object onto them in order. |

Quoting rule: a field is quoted only when it must be — it contains the delimiter, a double-quote, CR, or LF. Embedded double-quotes are escaped by doubling ("""). Non-string values are coerced with String(); null/undefined become an empty, unquoted field.

parse and stringify are exact inverses for well-formed data — see the parse -> stringify -> parse stability test in test/index.test.js.

Limits (please read)

This is an honest, deliberately small library. It does not do everything a full CSV package does:

  • No streaming. parse(text) takes a complete string and returns the fully materialized result in memory; stringify(rows) builds the whole output string. This is explicitly out of scope — for files too large to fit in memory, use a streaming parser such as csv-parse. As a rough guide, keep inputs to something comfortably under available RAM (tens of MB is fine; multi- gigabyte files are not what this is for).
  • RFC 4180 subset. It targets well-formed RFC 4180. It does not attempt recovery from malformed quoting (e.g. a " in the middle of an unquoted field, or an unterminated quote — an unterminated quoted field simply runs to end-of-input). There is no automatic delimiter detection, no comment-line (#) skipping, no BOM stripping, and no quote/escape-character customization (the quote character is always ").
  • Ragged rows are preserved, not normalized, in array mode. parse in the default (non-header) mode returns each row exactly as many fields as it had — it does not pad or truncate rows to a uniform width, so different rows may have different lengths. Only in header: true mode are objects shaped by the header: rows with fewer cells than the header get '' for the missing keys, and any extra cells beyond the header width are dropped.
  • Strings only, no type coercion. "30" stays the string "30"; there is no number/boolean/date inference. Convert types yourself after parsing.

Running the tests

One command, Node's built-in assert only — no test runner, no dependencies:

node test/index.test.js

It prints csv-lite: all N tests passed. and exits 0 on success. Fixtures cover embedded delimiters, embedded newlines inside quotes, doubled-quote escapes, header-mode object round-trip, custom delimiters (; and tab), CRLF vs LF, and a parse -> stringify -> parse round-trip that is byte-stable.

License

MIT — see LICENSE.