@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.
Maintainers
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-litePublished 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, andCRLFare literal data inside the quotes. - Embedded delimiters —
a,"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 ascsv-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.
parsein 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 inheader: truemode 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.jsIt 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.
