{"_id":"3dcsv","_rev":"3-aa3bb4abfd9572289a3ef46ddac871e6","name":"3dcsv","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.1":{"name":"3dcsv","version":"0.1.1","_id":"3dcsv@0.1.1","maintainers":[{"name":"ealexhaywood","email":"ealexhaywood@gmail.com"}],"dist":{"shasum":"755b1e1db5f6e0fc622f226dee1b05d42a3a7a2c","tarball":"https://registry.npmjs.org/3dcsv/-/3dcsv-0.1.1.tgz","fileCount":15,"integrity":"sha512-0feLXgzEG7EfytNLKrfhZ9kpkI2H8PspKoinxKz0tUOxXEfQNxCmkmQqesieNQJ2Ogtcyt9tki334I6UX0RoGg==","signatures":[{"sig":"MEUCIEyFPIyQ0rdESJPQpFW3jCAUjf7Cc082WdlqSTcGIL1QAiEA8qdXQyEDJCwx/U90GGDsOHm/o+fe8sGGM6IdINuQ4jc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":18339},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"gitHead":"952a2a8d340ec2eaa430841eb8ce9e5ff2910614","scripts":{"test":"bun test","build":"bun run build:tsc && bun run build:bun","release":"bun run build && npm publish","version":"changeset version","build:bun":"bun build ./src/index.ts --target=node --format=esm --minify --outfile=dist/index.mjs && bun build ./src/index.ts --target=node --format=cjs --minify --outfile=dist/index.cjs","build:tsc":"bunx tsc --noEmit && bunx tsc -p tsconfig.build.json","changeset":"changeset","prepublishOnly":"bun run build"},"_npmUser":{"name":"ealexhaywood","email":"ealexhaywood@gmail.com"},"_npmVersion":"10.8.2","description":"Pipe-separated comma-separated values — infinitely dimensional data in a 2D CSV.","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"devDependencies":{"bun-types":"latest","typescript":"^5.3.0","@changesets/cli":"^2.27.0"},"peerDependencies":{"zod":">=3.0.0"},"peerDependenciesMeta":{"zod":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/3dcsv_0.1.1_1769877070265_0.35943461643568764","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"3dcsv","version":"0.2.0","_id":"3dcsv@0.2.0","maintainers":[{"name":"ealexhaywood","email":"ealexhaywood@gmail.com"}],"dist":{"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},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"gitHead":"90440e1a9d58aec92044dc9b44c0b87ce51eea76","scripts":{"test":"bun test","build":"bun run build:tsc && bun run build:bun","release":"bun run build && npm publish","version":"changeset version","build:bun":"bun build ./src/index.ts --target=node --format=esm --minify --outfile=dist/index.mjs && bun build ./src/index.ts --target=node --format=cjs --minify --outfile=dist/index.cjs","build:tsc":"bunx tsc --noEmit && bunx tsc -p tsconfig.build.json","changeset":"changeset","prepublishOnly":"bun run build"},"_npmUser":{"name":"ealexhaywood","email":"ealexhaywood@gmail.com"},"_npmVersion":"10.8.2","description":"Pipe-separated comma-separated values — infinitely dimensional data in a 2D CSV.","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"devDependencies":{"bun-types":"latest","typescript":"^5.3.0","@changesets/cli":"^2.27.0"},"peerDependencies":{"zod":">=3.0.0"},"peerDependenciesMeta":{"zod":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/3dcsv_0.2.0_1769879440773_0.5418497686040873","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"3dcsv","version":"0.3.0","description":"Pipe-separated comma-separated values — infinitely dimensional data in a 2D CSV.","type":"module","main":"dist/index.cjs","module":"dist/index.mjs","types":"dist/index.d.ts","bin":{"3dcsv":"dist/cli.js"},"exports":{".":{"import":"./dist/index.mjs","require":"./dist/index.cjs","types":"./dist/index.d.ts"}},"scripts":{"build":"bun run build:tsc && bun run build:bun && bun run build:visualize","build:tsc":"bunx tsc --noEmit && bunx tsc -p tsconfig.build.json","build:bun":"bun build ./src/index.ts --target=node --format=esm --minify --outfile=dist/index.mjs && bun build ./src/index.ts --target=node --format=cjs --minify --outfile=dist/index.cjs && bun build ./src/cli.ts --target=node --format=esm --outfile=dist/cli.js","build:visualize":"mkdir -p dist/visualize && bun build ./visualize-app/src/main.tsx --target=browser --outdir=dist/visualize && cp visualize-app/index.html dist/visualize/","test":"bun test","dev:ui":"bun build ./visualize-app/src/main.tsx --target=browser --outdir=dist/visualize --watch","dev:server":"bun dist/cli.js visualize example.csv","dev":"bun run dev:ui & bun run dev:server","changeset":"changeset","version":"changeset version","release":"bun run build && npm publish","prepublishOnly":"bun run build"},"devDependencies":{"@changesets/cli":"^2.27.0","@types/react":"^18.3.0","@types/react-dom":"^18.3.0","bun-types":"latest","react":"^18.3.0","react-dom":"^18.3.0","typescript":"^5.3.0"},"peerDependencies":{"zod":">=3.0.0"},"peerDependenciesMeta":{"zod":{"optional":true}},"engines":{"node":">=18"},"_id":"3dcsv@0.3.0","gitHead":"7939b93fac49c053c12792e3e5768f3269e7fd3f","_nodeVersion":"20.20.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-uzGsyCF3H8hsM9j8j4Yo8sneBvOLMKPK7NqvOV18a2PHqIBeA8oo7ZaySs/z8U10S9Hwpaxs0o7AMdSwNJeAsw==","shasum":"ef6d2574b8c37a7f923e37d7bfd54e1400366792","tarball":"https://registry.npmjs.org/3dcsv/-/3dcsv-0.3.0.tgz","fileCount":23,"unpackedSize":1007901,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDhExdHaay1F4ZwK6b8e9C/Kj9GYJ9M+2T/KXKS+q7l9gIgG4pC8gy/W/1BBiIpb/+eDPaRyM3x+u4XzwGiQ3wBZFw="}]},"_npmUser":{"name":"ealexhaywood","email":"ealexhaywood@gmail.com"},"directories":{},"maintainers":[{"name":"ealexhaywood","email":"ealexhaywood@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/3dcsv_0.3.0_1769880851838_0.30640544949602266"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-31T16:31:10.264Z","modified":"2026-01-31T17:34:12.198Z","0.1.1":"2026-01-31T16:31:10.408Z","0.2.0":"2026-01-31T17:10:40.916Z","0.3.0":"2026-01-31T17:34:12.063Z"},"description":"Pipe-separated comma-separated values — infinitely dimensional data in a 2D CSV.","maintainers":[{"name":"ealexhaywood","email":"ealexhaywood@gmail.com"}],"readme":"# 3D CSV\n\n**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 `|`).\n\n_Yes, it’s still a 2D grid. The “3D” is aspirational._\n\n## Install\n\n```bash\nbun add 3dcsv\n# or\nnpm install 3dcsv\n```\n\nFor typed rows with runtime validation (recommended):\n\n```bash\nbun add 3dcsv zod\n```\n\n## Usage\n\n### Parse and stringify\n\n```ts\nimport { parse, stringify } from \"3dcsv\";\n\nconst csv = `name,age,tags\nAlice,30,\"js|ts|rust\"\nBob,25,\"hiking|photography\"`;\n\nconst { headers, rows } = parse(csv);\n// headers: ['name', 'age', 'tags']\n// rows: [\n//   { name: 'Alice', age: '30', tags: ['js', 'ts', 'rust'] },\n//   { name: 'Bob', age: '25', tags: ['hiking', 'photography'] }\n// ]\n\nconst back = stringify({ headers, rows });\n// roundtrip: back === csv\n```\n\n### Typed rows (Zod, recommended)\n\nPass a Zod schema; return type is inferred. No type assertions.\n\n```ts\nimport { parse } from \"3dcsv\";\nimport { z } from \"zod\";\n\nconst personSchema = z.object({\n  name: z.string(),\n  age: z.coerce.number(),\n  tags: z.array(z.string()),\n});\n\nconst result = parse(csv, { schema: personSchema });\n// result.rows is { name: string; age: number; tags: string[] }[]\n\n// Optional runtime validation\nconst validated = parse(csv, { schema: personSchema, validate: true });\n```\n\n### Typed rows (generic, no Zod)\n\n```ts\ntype Person = { name: string; age: number; tags: string[] };\nconst result = parse<Person>(csv);\n// result.rows is Person[]\n```\n\n### Convenience views\n\n```ts\nconst result = parse(csv);\n\nresult.rows; // default: array of row objects\nresult.toRows(); // always: Cell[][] (array of arrays)\nresult.toObjects(); // always: Record<string, Cell>[]\n```\n\n### Flatten back to regular CSV\n\nCome 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.\n\n```ts\nconst csv = `name,tags\nAlice,\"js|ts|rust\"`;\nconst flat = parse(csv).flatten();\n// flat.rows: [{ name: \"Alice\", tags: \"js\" }, { name: \"Alice\", tags: \"ts\" }, ...]\nconst regularCsv = stringify(flat); // no pipes\n```\n\nOptional: `parse(csv).flatten({ columns: [\"tags\"] })` to expand only specific columns.\n\n### Visualize (CLI)\n\nRun a local server and open a React table view in the browser:\n\n```bash\nbunx 3dcsv visualize\n# or with a file (relative to cwd):\nbunx 3dcsv visualize example.csv\n```\n\nOpens `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.\n\n### No schema, no generic\n\nIf you do nothing, you get `{ headers: string[]; rows: unknown[] }`. Typed rows are opt-in via schema or generic.\n\n## API\n\n- **`parse(input, options?)`** — Parse 3D CSV. Options: `dimensionDelimiters`, `header`, `columns`, `asObjects`, `schema`, `validate`.\n- **`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[]`.\n- **`stringify(data, options?)`** — Stringify to 3D CSV. Accepts `{ headers, rows }` or array of row objects (headers inferred).\n- **`bunx 3dcsv visualize [file.csv]`** — Start a local server and open a table UI; optional file path (relative to cwd).\n\n_It’s just CSV with pipes in the cells. Sometimes that’s all you need. Sometimes._\n\n## Format\n\n- Rows and columns as usual; cells can contain a **dimension delimiter** (default `|`).\n- A cell like `\"a|b|c\"` is one cell whose value is the list `[\"a\", \"b\", \"c\"]`.\n- Quoting and escaping follow standard CSV (e.g. `\"\"` inside quoted fields).\n\n## Contributing\n\nChangesets for versioning: run `bun run changeset` when you change the package. Merge the “Version Packages” PR to publish. See [.changeset/README.md](.changeset/README.md).\n\n## License\n\nMIT\n\n---\n\n_3D CSV: because one dimension was never enough. We’re not saying it’s a good idea — we’re just saying it works._\n","readmeFilename":"README.md"}