A while back I wrote about the one-line fix for CSV formula injection. That fix ships in csv-pipe. Here is the rest of it.
csv-pipe is a typed, zero-dependency CSV library for TypeScript. It is one import for both directions, about 2 kB each way, and runs on Node, the browser, Deno, Bun, and edge.
Encode and parse are mirror images, so your rows round-trip:
import { stringify, parse } from 'csv-pipe';
type User = { name: string; age: number };
const users: User[] = [
{ name: 'Alex', age: 29 },
{ name: 'Carlos', age: 24 }
];
const csv = stringify(users);
// name,age
// Alex,29
// Carlos,24
parse<User>(csv, { dynamicTyping: true });
// [{ name: 'Alex', age: 29 }, { name: 'Carlos', age: 24 }]
Columns are checked against your type, so a typo is a compile error, not a broken export you find in production:
stringify(users, { columns: ['name', 'age'] }); // ok
stringify(users, { columns: ['naem'] }); // compile error: not a key of User
Parsing is the standout. On a 50,000-row dataset, in operations per second (higher is better):
| Library | parse ops/sec |
|---|---|
| csv-pipe | 201 |
| papaparse | 61 |
| csv-parse | 32 |
| fast-csv | 16 |
That is roughly 3x to 13x faster than papaparse, csv-parse, and fast-csv, with encoding about 1.5x ahead. These are indicative numbers from one machine, and the benchmark is in the repo, so you can reproduce them with npm run bench.
papaparse, csv-parse with csv-stringify, and fast-csv are all solid and worth knowing. Reach for csv-pipe when you want all of that in one small, typed package.
The real test is your own data, so paste a CSV into the playground:
https://martsinlabs.github.io/csv-pipe/playground
It is open source and still growing. If it is useful to you, a star helps others find it, and issues, ideas, and pull requests are all welcome.
Top comments (0)