Catalog npm
Back to packageRELEASE DETAILS

0.2.0

npm

3dcsv

Pipe-separated comma-separated values — infinitely dimensional data in a 2D CSV.

Published31 Jan 2026
Direct dependencies4
Transitive dependenciesNot calculated

README

Current package documentation

3D CSV

Pipe-separated comma-separated values — represent complex, multi-valued data in a single 2D CSV. One table, one header row, list-valued cells via a dimension delimiter (default |).

Yes, it’s still a 2D grid. The “3D” is aspirational.

Install

bun add 3dcsv
# or
npm install 3dcsv

For typed rows with runtime validation (recommended):

bun add 3dcsv zod

Usage

Parse and stringify

import { parse, stringify } from "3dcsv";

const csv = `name,age,tags
Alice,30,"js|ts|rust"
Bob,25,"hiking|photography"`;

const { headers, rows } = parse(csv);
// headers: ['name', 'age', 'tags']
// rows: [
//   { name: 'Alice', age: '30', tags: ['js', 'ts', 'rust'] },
//   { name: 'Bob', age: '25', tags: ['hiking', 'photography'] }
// ]

const back = stringify({ headers, rows });
// roundtrip: back === csv

Pass a Zod schema; return type is inferred. No type assertions.

import { parse } from "3dcsv";
import { z } from "zod";

const personSchema = z.object({
  name: z.string(),
  age: z.coerce.number(),
  tags: z.array(z.string()),
});

const result = parse(csv, { schema: personSchema });
// result.rows is { name: string; age: number; tags: string[] }[]

// Optional runtime validation
const validated = parse(csv, { schema: personSchema, validate: true });

Typed rows (generic, no Zod)

type Person = { name: string; age: number; tags: string[] };
const result = parse<Person>(csv);
// result.rows is Person[]

Convenience views

const result = parse(csv);

result.rows; // default: array of row objects
result.toRows(); // always: Cell[][] (array of arrays)
result.toObjects(); // always: Record<string, Cell>[]

Flatten back to regular CSV

Come back down to earth and expand list-valued cells into one row per element (join-table style). Then stringify to get plain CSV with no pipes.

const csv = `name,tags
Alice,"js|ts|rust"`;
const flat = parse(csv).flatten();
// flat.rows: [{ name: "Alice", tags: "js" }, { name: "Alice", tags: "ts" }, ...]
const regularCsv = stringify(flat); // no pipes

Optional: parse(csv).flatten({ columns: ["tags"] }) to expand only specific columns.

Visualize (CLI)

Run a local server and open a React table view in the browser:

bunx 3dcsv visualize
# or with a file (relative to cwd):
bunx 3dcsv visualize example.csv

Opens http://localhost:3847 (or PORT env). List-valued cells render as badges. The UI is built with React and bundled with Bun; run bun run dev:ui to watch for changes and bun run dev:server to run the server.

No schema, no generic

If you do nothing, you get { headers: string[]; rows: unknown[] }. Typed rows are opt-in via schema or generic.

API

  • parse(input, options?) — Parse 3D CSV. Options: dimensionDelimiters, header, columns, asObjects, schema, validate.
  • parse(csv).flatten(options?) — Expand array cells into one row per element (Cartesian product when multiple columns); returns Parsed3DCSV with all scalar rows. Options: columns?: string[].
  • stringify(data, options?) — Stringify to 3D CSV. Accepts { headers, rows } or array of row objects (headers inferred).
  • bunx 3dcsv visualize [file.csv] — Start a local server and open a table UI; optional file path (relative to cwd).

It’s just CSV with pipes in the cells. Sometimes that’s all you need. Sometimes.

Format

  • Rows and columns as usual; cells can contain a dimension delimiter (default |).
  • A cell like "a|b|c" is one cell whose value is the list ["a", "b", "c"].
  • Quoting and escaping follow standard CSV (e.g. "" inside quoted fields).

Contributing

Changesets for versioning: run bun run changeset when you change the package. Merge the “Version Packages” PR to publish. See .changeset/README.md.

License

MIT


3D CSV: because one dimension was never enough. We’re not saying it’s a good idea — we’re just saying it works.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 4

Native requirements
4 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
bun-types
Environment
{
  "local_name": "bun-types",
  "alias": false,
  "peer_metadata": null
}
latestdevelopment
typescript
Environment
{
  "local_name": "typescript",
  "alias": false,
  "peer_metadata": null
}
^5.3.0development
@changesets/cli
Environment
{
  "local_name": "@changesets/cli",
  "alias": false,
  "peer_metadata": null
}
^2.27.0development
zod
Environment
{
  "local_name": "zod",
  "alias": false,
  "peer_metadata": {
    "optional": true
  }
}
>=3.0.0peer

Distribution files

1 collected
Distribution 1

Source distribution

Source file
Checksums from source
{
  "shasum": "d0ee40fdc727355017a73ebbdf59994b18f7d162",
  "tarball": "https://registry.npmjs.org/3dcsv/-/3dcsv-0.2.0.tgz",
  "fileCount": 17,
  "integrity": "sha512-3P2CK+1hW5lIPjwpVsQnoPzGrGDNNOv2sCW1Rzhwc9E6Cw/38vqctN3Lv6UsmlhkpI/aCpNNLm0PwEdVIziUIQ==",
  "signatures": [
    {
      "sig": "MEQCIGvORyswlWKlwrK3OeDMHGDxjdTwKc0n4q98Q26pK2KqAiBKPZzqWByZtN9PHXbnKyxMqbhwMLzZRwhVO7aOV8mykw==",
      "keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"
    }
  ],
  "unpackedSize": 23088
}

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 19:39 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:aec89701d2f00f8c8dfc326468f3f6cf67499192556e715a970a59e3fbd00f4e

Other collected versions

0.3.031 Jan0.1.131 JanView all collected versions →