Docs
/
adapter system

spreadsheet

Spreadsheet domain adapter — real XLSX (Excel) create/read/convert/append/style via exceljs. exceljs is lazy-guarded so the pack always loads; XLSX tools return { ok:false, unavailable:true } when...

spreadsheet (adapter system)

Real XLSX / Excel spreadsheet capability pack, backed by the exceljs npm dependency. This produces and parses the actual Office Open XML (.xlsx) binary — not delimited text. Workbooks travel as base64 so an entire binary workbook fits in one JSON POST body (in and out).

Dependency & lazy guard

exceljs is installed at the workspace root. It is lazy-guarded (imported on first use, never at module load): the pack always loads, and if exceljs cannot be imported, every XLSX-backed tool returns { ok:false, unavailable:true, error:'exceljs not installed' } instead of throwing. The pure helpers (row normalization, CSV split/join used by the bridge tools) keep working regardless.

Tools (adapters)

Each tool takes ONE args object (an HTTP POST body maps 1:1) and is async.

toolargsresult
create{ sheets:[{name,rows}], options?:{headerStyle,autoWidth} }{ base64, bytes, sheets[] }
read{ base64 }{ sheetNames[], sheets:{ <name>: matrix } }
csvToXlsx{ csv, delimiter?, name?, options? }{ base64, bytes, sheet }
xlsxToCsv{ base64, sheet?, delimiter? }{ csv, rows, columns }
appendRows{ base64, rows, sheet? }{ base64, bytes, appended, totalRows }
addSheet{ base64, name, rows? }{ base64, bytes, sheetNames[] }
styleHeader{ base64, sheet?, options?:{bold,fill,color,freeze} }{ base64, bytes, styledCells }
autoWidth{ base64, sheet?, options?:{min,max,padding} }{ base64, bytes, widths[] }
toBase64`{ sheets? } \{ base64 }`{ base64, bytes, sheets[] }
getSheetNames{ base64 }{ sheetNames[], count }
info{ base64 }{ sheetCount, sheets[], creator, totalRows }

Row shapes

Every tool that takes rows accepts two shapes:

  • array-of-arrays[["name","age"],["Ada",36]] — written verbatim, you manage the header row.
  • array-of-objects[{name:"Ada",age:36}] — the union of keys becomes the header row and each

object is mapped to columns.

Cell values may be string / number / boolean / date. Dates read back as ISO strings; stored formula cells read back as { formula, result }.

Usage example

import pack from './index.js';

// Build a 2-sheet workbook with a styled, auto-fit header, then read it back.
const built = await pack.adapters.create({
  sheets: [
    { name: 'People', rows: [{ name: 'Ada', role: 'Engineer' }, { name: 'Alan', role: 'Logician' }] },
    { name: 'Totals', rows: [['metric', 'value'], ['count', 2]] },
  ],
  options: { headerStyle: true, autoWidth: true },
});
// built.base64 is a real .xlsx you can save or send.

const back = await pack.adapters.read({ base64: built.base64 });
// back.sheetNames -> ["People","Totals"]; back.sheets.People -> [["name","role"],["Ada","Engineer"],...]

// CSV <-> XLSX bridge:
const xlsx = await pack.adapters.csvToXlsx({ csv: 'a,b\n1,2\n3,4', options: { headerStyle: true } });
const csv  = await pack.adapters.xlsxToCsv({ base64: xlsx.base64 });

DRY boundary

  • a-csv owns pure CSV — parsing/writing RFC-4180 delimited text. This pack does NOT

re-implement general CSV manipulation.

  • This pack owns the real binary .xlsx format (workbooks, worksheets, cells, styling, column

widths). csvToXlsx / xlsxToCsv are the bridge between the two formats — they necessarily touch the xlsx binary (only exceljs can), so they belong here. The small CSV split/join inside is a local convenience for that bridge, not a competing CSV toolkit.

Out of scope: formula evaluation

exceljs stores formula strings (e.g. =SUM(A1:A3)) but does not evaluate them — it has no calc engine. This pack reads and writes formula text as-is and never computes formula results. For live formula calculation, use a real spreadsheet application or a dedicated calc engine.

Source shared/engines/adapters/domain/spreadsheet/README.md (no-git)markdownjson
Generated from the Leumas repository. Every page cites the file it came from.leumas.techllms.txt