tabulate-export
v1.0.2
Published
Export tabular data (header + rows) to CSV, JSON, XLSX, or PDF through one unified, extensible API.
Maintainers
Readme
export-lib
Export tabular data (header + data) to CSV, JSON, XLSX, or PDF through one unified API.
const { exportData } = require('export-lib');
const buffer = await exportData({
header: ['Name', 'Role', 'Years'],
data: [
['Ada Lovelace', 'Mathematician', 3],
['Grace Hopper', 'Computer Scientist', 44],
],
type: 'pdf', // 'csv' | 'json' | 'xlsx' | 'pdf'
});
// buffer is a Buffer — write it to disk, stream it in an HTTP response,
// or turn it into a Blob in the browser. This library doesn't force any I/O.Why
Most projects end up writing the same "export as CSV / export as PDF" logic over and over, each format pulling in a different library with a different API. This wraps them behind one consistent interface so callers don't need to care what's underneath.
Install
npm install tabulate-exportUsage
Write directly to a file (Node)
const { exportToFile } = require('export-lib');
await exportToFile(
{ header: ['Name', 'Age'], data: [['Ada', 28]], type: 'xlsx' },
'./report.xlsx'
);Rows as objects instead of arrays
await exportData({
header: ['Name', 'Age'],
data: [{ Name: 'Ada', Age: 28 }], // keyed by header name — order doesn't matter
type: 'csv',
});Serve as an HTTP download (Express example)
app.get('/export.pdf', async (req, res) => {
const buffer = await exportData({ header, data, type: 'pdf' });
res.set('Content-Type', 'application/pdf');
res.set('Content-Disposition', 'attachment; filename="report.pdf"');
res.send(buffer);
});API
exportData({ header, data, type, options }) => Promise<Buffer>
| Param | Type | Description |
|---------|--------------------------|----------------------------------------------------------------------|
| header | string[] | Column names, in order. |
| data | Array<Array \| Object> | Rows. Arrays are positional; objects are matched by header name. |
| type | string | 'csv', 'json', 'xlsx', 'pdf' (leading . is optional). |
| options | object | Format-specific, see below. |
exportToFile(params, filePath) => Promise<string>
Same as exportData, but writes the result straight to disk and returns the path. Node-only.
registerFormat(name, adapter)
Add support for a new format without touching library internals:
const { registerFormat } = require('export-lib');
registerFormat('txt', {
generate: async (header, rows, options) =>
Buffer.from(rows.map((r) => r.join('\t')).join('\n')),
});Any adapter just needs to implement generate(header, rows, options) => Buffer | Promise<Buffer>.
Format-specific options
| Type | Option | Default | Notes |
|------|---------------|-----------|-----------------------------------------|
| csv | delimiter | , | Change to ; for European locale CSVs |
| json | pretty | true | Set false for minified output |
| xlsx | sheetName | Sheet1 | |
| pdf | title | none | Optional heading above the table |
| pdf | pageSize | A4 | Any pdfkit page size |
Architecture
Each format is an isolated adapter behind a shared interface
(generate(header, rows, options) => Buffer). The core (exportData)
only validates input and dispatches to the right adapter via a registry —
it has no format-specific logic itself. This keeps formats swappable and
makes it trivial to add new ones (see registerFormat above) without
touching existing code.
src/
├── index.js # public API
├── registry.js # format name -> adapter lookup
├── adapters/
│ ├── csv.js # hand-rolled, RFC-4180-style escaping
│ ├── json.js # rows -> array of keyed objects
│ ├── xlsx.js # wraps exceljs
│ └── pdf.js # wraps pdfkit, hand-laid-out table w/ pagination
└── utils/
└── validate.js # shape validation + array/object row normalizationDevelopment
npm install
npm testLicense
MIT
