@dipanshuhandoo/excelio 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -1
- package/README.md +218 -22
- package/dist/cjs/index.cjs +329 -52
- package/dist/cjs/index.cjs.map +4 -4
- package/dist/cjs/index.d.cts +23 -4
- package/dist/cjs/workers/reader.worker.cjs.map +2 -2
- package/dist/cjs/workers/writer.worker.cjs +318 -49
- package/dist/cjs/workers/writer.worker.cjs.map +4 -4
- package/dist/cjs-min/index.cjs +1 -1
- package/dist/cjs-min/index.cjs.map +4 -4
- package/dist/cjs-min/index.d.cts +23 -4
- package/dist/cjs-min/workers/reader.worker.cjs.map +2 -2
- package/dist/cjs-min/workers/writer.worker.cjs +1 -1
- package/dist/cjs-min/workers/writer.worker.cjs.map +4 -4
- package/dist/esm/index.d.ts +23 -4
- package/dist/esm/index.js +330 -53
- package/dist/esm/index.js.map +3 -3
- package/dist/esm/workers/reader.worker.js.map +2 -2
- package/dist/esm/workers/writer.worker.js +319 -50
- package/dist/esm/workers/writer.worker.js.map +3 -3
- package/dist/esm-min/index.d.ts +23 -4
- package/dist/esm-min/index.js +1 -1
- package/dist/esm-min/index.js.map +4 -4
- package/dist/esm-min/workers/reader.worker.js.map +2 -2
- package/dist/esm-min/workers/writer.worker.js +1 -1
- package/dist/esm-min/workers/writer.worker.js.map +4 -4
- package/package.json +3 -2
package/dist/esm/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/writer.js", "../../src/errors.js", "../../src/columns.js", "../../src/coerce.js", "../../src/reader.js", "../../src/workerPool.js", "../../src/index.js"],
|
|
4
|
-
"sourcesContent": ["import { Readable, PassThrough } from 'node:stream';\r\nimport { createWriteStream } from 'node:fs';\r\nimport { pipeline } from 'node:stream/promises';\r\nimport path from 'node:path';\r\nimport ExcelJS from 'exceljs';\r\n\r\nimport { ExcelIoError } from './errors.js';\r\nimport { resolveColumns } from './columns.js';\r\nimport { valueForWrite } from './coerce.js';\r\n\r\nconst DEFAULT_BATCH = 5000;\r\nconst SHEET_NAME_MAX = 31;\r\n\r\n/**\r\n * Write one or more workbooks from a spec.\r\n *\r\n * Returns:\r\n * - When `to` is omitted: an array of Buffers, one per workbook (single-element\r\n * array when spec has one workbook).\r\n * - When `to` is a file path: writes the file, returns the path. Supported only\r\n * when spec has exactly one workbook.\r\n * - When `to` is a Writable stream: pipes the workbook into it. Single workbook only.\r\n *\r\n * Multi-workbook with a single `to` target isn't supported (no zip semantics here).\r\n * For multi-workbook output, omit `to` and get buffers back.\r\n */\r\nexport async function writeSpec(spec, options = {}) {\r\n validateSpec(spec);\r\n\r\n const { to } = options;\r\n if (to !== undefined && spec.length > 1) {\r\n throw new ExcelIoError(\r\n `Multi-workbook output requires omitting \"to\" \u2014 caller writes each buffer itself.`,\r\n { code: 'INVALID_SPEC' }\r\n );\r\n }\r\n\r\n if (to !== undefined) {\r\n await writeOneWorkbook(spec[0], 0, to, options);\r\n return to;\r\n }\r\n\r\n const buffers = [];\r\n for (let wbIndex = 0; wbIndex < spec.length; wbIndex++) {\r\n const buf = await writeOneWorkbookToBuffer(spec[wbIndex], wbIndex, options);\r\n buffers.push(buf);\r\n }\r\n // Ergonomic: single-workbook spec returns a single Buffer; multi returns Buffer[]\r\n return buffers.length === 1 ? buffers[0] : buffers;\r\n}\r\n\r\n/**\r\n * Returns a Readable stream containing the first workbook's bytes. If the spec has\r\n * multiple workbooks, only the first is streamed (callers wanting multi should\r\n * call writeSpec without `to` to get buffers).\r\n */\r\nexport function writeSpecStream(spec, options = {}) {\r\n validateSpec(spec);\r\n const passthrough = new PassThrough();\r\n writeOneWorkbook(spec[0], 0, passthrough, options).catch(err => passthrough.destroy(err));\r\n return passthrough;\r\n}\r\n\r\n/* \u2500\u2500\u2500\u2500\u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\r\n\r\nasync function writeOneWorkbookToBuffer(workbookSpec, wbIndex, options) {\r\n const chunks = [];\r\n const collector = new PassThrough();\r\n collector.on('data', (chunk) => chunks.push(chunk));\r\n await writeOneWorkbook(workbookSpec, wbIndex, collector, options);\r\n return Buffer.concat(chunks);\r\n}\r\n\r\nasync function writeOneWorkbook(workbookSpec, wbIndex, target, options) {\r\n const { signal, onProgress, beforeWrite, batchSize = DEFAULT_BATCH, logger } = options;\r\n\r\n const sink = resolveSink(target);\r\n\r\n const wb = new ExcelJS.stream.xlsx.WorkbookWriter({\r\n stream: sink.writable,\r\n useStyles: true,\r\n useSharedStrings: true\r\n });\r\n\r\n applyWorkbookProperties(wb, workbookSpec.properties);\r\n\r\n const usedNames = new Set();\r\n const sheets = workbookSpec.sheets || [];\r\n let totalRows = sheets.reduce((n, s) => n + (s.data?.length || 0), 0);\r\n let rowsProcessed = 0;\r\n\r\n for (let sIndex = 0; sIndex < sheets.length; sIndex++) {\r\n if (signal?.aborted) throw new ExcelIoError('Aborted', { code: 'ABORTED' });\r\n\r\n const sheetSpec = sheets[sIndex];\r\n const sheetName = sanitiseSheetName(sheetSpec.sheet || `Sheet ${sIndex + 1}`, usedNames, logger);\r\n\r\n // Pass styling-related options at creation time \u2014 WorksheetWriter (streaming)\r\n // doesn't allow setting `views` after the fact.\r\n const wsOptions = {};\r\n if (sheetSpec.styling?.freezeHeader) {\r\n wsOptions.views = [{ state: 'frozen', ySplit: 1 }];\r\n }\r\n const ws = wb.addWorksheet(sheetName, wsOptions);\r\n\r\n const cols = resolveColumns(sheetSpec.columns, sheetSpec.data);\r\n if (cols.length) {\r\n ws.columns = cols.map(c => ({\r\n key: c.key,\r\n header: c.header,\r\n width: c.width,\r\n style: c.format ? { numFmt: c.format } : undefined\r\n }));\r\n }\r\n\r\n applyStylingPostColumns(ws, sheetSpec.styling, cols.length);\r\n\r\n const data = sheetSpec.data || [];\r\n for (let i = 0; i < data.length; i++) {\r\n if (signal?.aborted) throw new ExcelIoError('Aborted', { code: 'ABORTED' });\r\n\r\n let row = data[i];\r\n if (beforeWrite) {\r\n row = beforeWrite(row, {\r\n workbookIndex: wbIndex,\r\n workbookName: workbookSpec.workbook,\r\n sheetIndex: sIndex,\r\n sheetName,\r\n rowNumber: i + 2 // header is row 1\r\n }) ?? row;\r\n }\r\n\r\n const rowValues = cols.length\r\n ? cols.reduce((acc, c) => { acc[c.key] = valueForWrite(row[c.key], c.type); return acc; }, {})\r\n : row;\r\n ws.addRow(rowValues).commit();\r\n\r\n rowsProcessed++;\r\n if (onProgress && rowsProcessed % batchSize === 0) {\r\n onProgress({ phase: 'write', workbookIndex: wbIndex, sheetIndex: sIndex, rowsProcessed, totalRows });\r\n }\r\n }\r\n\r\n ws.commit();\r\n }\r\n\r\n await wb.commit();\r\n if (sink.cleanup) await sink.cleanup();\r\n\r\n if (onProgress) {\r\n onProgress({ phase: 'write', workbookIndex: wbIndex, sheetIndex: sheets.length - 1, rowsProcessed, totalRows });\r\n }\r\n}\r\n\r\nfunction resolveSink(target) {\r\n // File path \u2014 register the close promise immediately so we don't miss the\r\n // 'finish' event if it fires before cleanup() is awaited.\r\n if (typeof target === 'string') {\r\n const fileStream = createWriteStream(target);\r\n const closed = new Promise((resolve, reject) => {\r\n fileStream.once('finish', resolve);\r\n fileStream.once('error', reject);\r\n });\r\n return { writable: fileStream, cleanup: () => closed };\r\n }\r\n // Writable stream supplied by caller \u2014 they own its lifecycle.\r\n if (target && typeof target.write === 'function') {\r\n return { writable: target, cleanup: null };\r\n }\r\n throw new ExcelIoError(`Invalid write target \u2014 expected file path or writable stream`, { code: 'INVALID_SPEC' });\r\n}\r\n\r\nfunction applyWorkbookProperties(wb, props) {\r\n if (!props) return;\r\n if (props.author) wb.creator = props.author;\r\n if (props.created) wb.created = props.created instanceof Date ? props.created : new Date(props.created);\r\n if (props.modified) wb.modified = props.modified instanceof Date ? props.modified : new Date(props.modified);\r\n if (props.company) wb.company = props.company;\r\n if (props.title) wb.title = props.title;\r\n}\r\n\r\nfunction applyStylingPostColumns(ws, styling, colCount) {\r\n if (!styling) return;\r\n if (styling.headerBold) {\r\n ws.getRow(1).font = { bold: true };\r\n }\r\n if (styling.autoFilter && colCount > 0) {\r\n ws.autoFilter = { from: { row: 1, column: 1 }, to: { row: 1, column: colCount } };\r\n }\r\n // freezeHeader is applied at addWorksheet time (see wsOptions in writeOneWorkbook).\r\n}\r\n\r\nconst FORBIDDEN_SHEET_CHARS = /[\\\\/?*[\\]:]/g;\r\n\r\nfunction sanitiseSheetName(raw, used, logger) {\r\n let name = String(raw).replace(FORBIDDEN_SHEET_CHARS, '_');\r\n if (name.length > SHEET_NAME_MAX) {\r\n if (logger?.warn) logger.warn(`excelio: sheet name \"${raw}\" truncated to ${SHEET_NAME_MAX} chars`);\r\n name = name.slice(0, SHEET_NAME_MAX);\r\n }\r\n if (!used.has(name)) { used.add(name); return name; }\r\n let i = 2;\r\n while (true) {\r\n const suffix = ` (${i})`;\r\n const candidate = (name.length + suffix.length > SHEET_NAME_MAX\r\n ? name.slice(0, SHEET_NAME_MAX - suffix.length)\r\n : name) + suffix;\r\n if (!used.has(candidate)) { used.add(candidate); return candidate; }\r\n i++;\r\n }\r\n}\r\n\r\nfunction validateSpec(spec) {\r\n if (!Array.isArray(spec) || spec.length === 0) {\r\n throw new ExcelIoError('Spec must be a non-empty array of workbooks', { code: 'INVALID_SPEC' });\r\n }\r\n for (const wb of spec) {\r\n if (!wb || typeof wb !== 'object') {\r\n throw new ExcelIoError('Workbook entries must be objects', { code: 'INVALID_SPEC' });\r\n }\r\n if (!Array.isArray(wb.sheets) || wb.sheets.length === 0) {\r\n throw new ExcelIoError('Workbook must have at least one sheet', { code: 'INVALID_SPEC' });\r\n }\r\n }\r\n}\r\n\r\n// Helpers exported for tests\r\nexport const __test = { sanitiseSheetName };\r\n", "/**\r\n * Custom error type for excelio. No external dependencies \u2014 keeps the package\r\n * portable to any Node project.\r\n *\r\n * Codes:\r\n * INVALID_SPEC \u2014 caller passed a malformed spec\r\n * IO_ERROR \u2014 corrupt input file, write failure, etc.\r\n * ABORTED \u2014 operation cancelled via AbortController\r\n * WORKER_ERROR \u2014 worker thread crashed or returned an error\r\n * ROW_VALIDATION \u2014 a row failed validation (only thrown when onRowError === 'fail')\r\n */\r\nexport class ExcelIoError extends Error {\r\n constructor(message, { code = 'IO_ERROR', cause, details } = {}) {\r\n super(message);\r\n this.name = 'ExcelIoError';\r\n this.code = code;\r\n if (cause !== undefined) this.cause = cause;\r\n if (details !== undefined) this.details = details;\r\n }\r\n}\r\n", "/**\r\n * Column metadata helpers.\r\n *\r\n * A column entry shape:\r\n * { key, header?, type?, format?, width? }\r\n *\r\n * key : property name on each data row (required)\r\n * header : displayed in the first row (defaults to key)\r\n * type : 'string' | 'number' | 'boolean' | 'date' (informs cell formatting)\r\n * format : Excel number-format string (e.g. 'yyyy-mm-dd', '#,##0.00')\r\n * width : column width in Excel units (default 15)\r\n */\r\n\r\n/**\r\n * Resolve the columns for a sheet. If the caller provided columns, validate/normalise.\r\n * Otherwise infer from the first row's keys (preserving insertion order).\r\n */\r\nexport function resolveColumns(declaredColumns, data) {\r\n if (Array.isArray(declaredColumns) && declaredColumns.length) {\r\n return declaredColumns.map(normaliseColumn);\r\n }\r\n if (!data?.length) return [];\r\n const firstRow = data[0] || {};\r\n return Object.keys(firstRow).map(k => normaliseColumn({ key: k }));\r\n}\r\n\r\nfunction normaliseColumn(c) {\r\n if (!c || typeof c !== 'object' || !c.key) {\r\n throw new Error(`excelio: column entry must have a \"key\" property; got ${JSON.stringify(c)}`);\r\n }\r\n return {\r\n key: String(c.key),\r\n header: c.header ?? c.key,\r\n type: c.type ?? null,\r\n format: c.format ?? defaultFormatFor(c.type),\r\n width: c.width ?? 15\r\n };\r\n}\r\n\r\nfunction defaultFormatFor(type) {\r\n switch (type) {\r\n case 'date': return 'yyyy-mm-dd hh:mm:ss';\r\n case 'number': return null;\r\n default: return null;\r\n }\r\n}\r\n", "/**\r\n * Cell value coercion in both directions.\r\n *\r\n * Write side: accept a JS value + optional column type, normalise to what exceljs\r\n * expects. Excel-native types are Number, String, Boolean, Date, formula objects,\r\n * and null.\r\n *\r\n * Read side: take a cell from exceljs and turn it into a portable JS value. Dates\r\n * default to ISO 8601 strings; configurable via `dateFormat`.\r\n */\r\n\r\nconst ISO_DATE_PATTERN = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?)?$/;\r\n\r\n/**\r\n * Normalise a JS value for writing into a cell. Returns the value as-is for most\r\n * types; converts ISO date strings + epoch ms to Date when the column declares\r\n * `type: 'date'`.\r\n */\r\nexport function valueForWrite(value, columnType) {\r\n if (value === null || value === undefined) return null;\r\n\r\n if (columnType === 'date') {\r\n if (value instanceof Date) return value;\r\n if (typeof value === 'number') return new Date(value);\r\n if (typeof value === 'string' && ISO_DATE_PATTERN.test(value)) {\r\n const d = new Date(value);\r\n return isNaN(d.getTime()) ? value : d;\r\n }\r\n return value;\r\n }\r\n\r\n if (columnType === 'number' && typeof value === 'string' && value !== '') {\r\n const n = Number(value);\r\n return Number.isFinite(n) ? n : value;\r\n }\r\n\r\n if (columnType === 'boolean') {\r\n if (typeof value === 'boolean') return value;\r\n if (value === 'true' || value === 1) return true;\r\n if (value === 'false' || value === 0) return false;\r\n }\r\n\r\n return value;\r\n}\r\n\r\n/**\r\n * Convert an exceljs cell value into a portable JS value.\r\n *\r\n * options:\r\n * nullForBlank: boolean \u2014 empty cells become null (default true)\r\n * trimStrings: boolean \u2014 strip leading/trailing whitespace from strings\r\n * dateFormat: 'iso' | 'date' | 'epoch'\r\n */\r\nexport function valueForRead(cell, { nullForBlank = true, trimStrings = true, dateFormat = 'iso' } = {}) {\r\n if (cell === undefined || cell === null) return nullForBlank ? null : '';\r\n\r\n // exceljs returns CellValue which can be primitive or object; cell.value is the\r\n // canonical accessor. When called with a raw value (e.g. from streaming), it's\r\n // already the primitive.\r\n const raw = (cell && typeof cell === 'object' && 'value' in cell) ? cell.value : cell;\r\n\r\n if (raw === null || raw === undefined || raw === '') return nullForBlank ? null : '';\r\n\r\n // Date cells\r\n if (raw instanceof Date) return formatDate(raw, dateFormat);\r\n\r\n // Hyperlink object: { text, hyperlink, ... } \u2014 return the visible text\r\n if (typeof raw === 'object' && raw.text !== undefined && raw.hyperlink !== undefined) {\r\n return trimStrings ? String(raw.text).trim() : String(raw.text);\r\n }\r\n\r\n // Rich text object: { richText: [{ text, font }, ...] }\r\n if (typeof raw === 'object' && Array.isArray(raw.richText)) {\r\n const joined = raw.richText.map(r => r.text).join('');\r\n return trimStrings ? joined.trim() : joined;\r\n }\r\n\r\n // Formula object: { formula, result }\r\n if (typeof raw === 'object' && raw.formula !== undefined) {\r\n return raw.result !== undefined ? raw.result : null;\r\n }\r\n\r\n // Error cell: { error: '#N/A' }\r\n if (typeof raw === 'object' && raw.error !== undefined) return null;\r\n\r\n if (typeof raw === 'string') return trimStrings ? raw.trim() : raw;\r\n return raw;\r\n}\r\n\r\nfunction formatDate(d, fmt) {\r\n switch (fmt) {\r\n case 'date': return d;\r\n case 'epoch': return d.getTime();\r\n case 'iso':\r\n default: return d.toISOString();\r\n }\r\n}\r\n", "import { Readable } from 'node:stream';\r\nimport { Buffer } from 'node:buffer';\r\nimport { createReadStream } from 'node:fs';\r\nimport { stat } from 'node:fs/promises';\r\nimport ExcelJS from 'exceljs';\r\n\r\nimport { ExcelIoError } from './errors.js';\r\nimport { valueForRead } from './coerce.js';\r\n\r\nconst DEFAULT_BATCH = 5000;\r\n\r\n/**\r\n * Read a workbook from a Buffer, file path, or readable stream.\r\n *\r\n * Currently uses the non-streaming `xlsx.load` / `xlsx.read` API for reliability.\r\n * Large files may exceed available memory. Worker-thread offload keeps parsing\r\n * off the main thread, but does not reduce total process memory or isolate it.\r\n * A future optimisation can swap to `stream.xlsx.WorkbookReader` once exceljs\r\n * stabilises its async iterator semantics across versions.\r\n */\r\nexport async function readSource(input, options = {}) {\r\n const startedAt = Date.now();\r\n const stats = { totalRows: 0, totalSheets: 0, durationMs: 0 };\r\n const errors = [];\r\n\r\n const {\r\n headerRow = 1,\r\n nullForBlank = true,\r\n trimStrings = true,\r\n dateFormat = 'iso',\r\n validateRow,\r\n afterRead,\r\n onRowError = 'collect',\r\n batchSize = DEFAULT_BATCH,\r\n onProgress,\r\n signal\r\n } = options;\r\n\r\n const wb = new ExcelJS.Workbook();\r\n try {\r\n if (Buffer.isBuffer(input)) {\r\n await wb.xlsx.load(input);\r\n } else if (input instanceof Uint8Array) {\r\n // Worker boundary downgrades Buffer to Uint8Array; rewrap.\r\n await wb.xlsx.load(Buffer.from(input.buffer, input.byteOffset, input.byteLength));\r\n } else if (typeof input === 'string') {\r\n await wb.xlsx.readFile(input);\r\n } else if (input && typeof input.pipe === 'function') {\r\n await wb.xlsx.read(input);\r\n } else {\r\n throw new ExcelIoError('Invalid input \u2014 expected Buffer, file path, or readable stream', { code: 'INVALID_SPEC' });\r\n }\r\n } catch (err) {\r\n if (err instanceof ExcelIoError) throw err;\r\n throw new ExcelIoError(`Failed to parse workbook: ${err.message}`, { code: 'IO_ERROR', cause: err });\r\n }\r\n\r\n const sheets = [];\r\n\r\n for (let s = 0; s < wb.worksheets.length; s++) {\r\n if (signal?.aborted) throw new ExcelIoError('Aborted', { code: 'ABORTED' });\r\n\r\n const ws = wb.worksheets[s];\r\n stats.totalSheets++;\r\n\r\n const sheetMeta = { sheet: ws.name, columns: [], data: [] };\r\n let columnKeys = null;\r\n\r\n ws.eachRow({ includeEmpty: false }, (row, rowNumber) => {\r\n // Header row\r\n if (rowNumber === headerRow) {\r\n columnKeys = readHeaderRow(row);\r\n sheetMeta.columns = columnKeys\r\n .filter(Boolean)\r\n .map(k => ({ key: k, header: k }));\r\n return;\r\n }\r\n if (rowNumber < headerRow || !columnKeys) return;\r\n if (signal?.aborted) throw new ExcelIoError('Aborted', { code: 'ABORTED' });\r\n\r\n const obj = {};\r\n let isEmpty = true;\r\n for (let i = 0; i < columnKeys.length; i++) {\r\n const key = columnKeys[i];\r\n if (!key) continue;\r\n const cell = row.getCell(i + 1);\r\n const v = valueForRead(cell, { nullForBlank, trimStrings, dateFormat });\r\n if (v !== null && v !== '' && v !== undefined) isEmpty = false;\r\n obj[key] = v;\r\n }\r\n if (isEmpty) return;\r\n\r\n const ctx = {\r\n workbookIndex: 0,\r\n workbookName: undefined,\r\n sheetIndex: s,\r\n sheetName: ws.name,\r\n rowNumber\r\n };\r\n\r\n let outRow = obj;\r\n if (afterRead) {\r\n try {\r\n outRow = afterRead(obj, ctx) ?? obj;\r\n } catch (err) {\r\n const e = mkRowError(ctx, 'TRANSFORM_ERROR', err.message);\r\n if (onRowError === 'fail') throw new ExcelIoError(e.message, { code: 'ROW_VALIDATION', details: e });\r\n errors.push(e);\r\n return;\r\n }\r\n }\r\n\r\n if (validateRow) {\r\n const issue = validateRow(outRow, ctx);\r\n if (issue) {\r\n const e = mkRowError(ctx, issue.code || 'VALIDATION_FAILED', issue.message, issue.column);\r\n if (onRowError === 'fail') throw new ExcelIoError(e.message, { code: 'ROW_VALIDATION', details: e });\r\n errors.push(e);\r\n return;\r\n }\r\n }\r\n\r\n sheetMeta.data.push(outRow);\r\n stats.totalRows++;\r\n\r\n if (onProgress && stats.totalRows % batchSize === 0) {\r\n onProgress({ phase: 'read', sheetName: ws.name, rowsProcessed: stats.totalRows });\r\n }\r\n });\r\n\r\n sheets.push(sheetMeta);\r\n }\r\n\r\n stats.durationMs = Date.now() - startedAt;\r\n\r\n return {\r\n ok: errors.length === 0,\r\n data: [{ workbook: undefined, sheets }],\r\n errors,\r\n stats\r\n };\r\n}\r\n\r\n/* \u2500\u2500\u2500\u2500\u2500\u2500 helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\r\n\r\nfunction readHeaderRow(row) {\r\n const headers = [];\r\n // exceljs row.values is sparse: index 0 unused, headers start at 1\r\n const values = row.values;\r\n if (!Array.isArray(values)) return headers;\r\n for (let i = 1; i < values.length; i++) {\r\n const v = values[i];\r\n headers.push(v == null ? null : String(v).trim());\r\n }\r\n return headers;\r\n}\r\n\r\nfunction mkRowError(ctx, code, message, column) {\r\n return {\r\n workbook: ctx.workbookIndex,\r\n sheet: ctx.sheetName,\r\n row: ctx.rowNumber,\r\n column: column ?? null,\r\n code,\r\n message\r\n };\r\n}\r\n", "import { Worker } from 'node:worker_threads';\r\nimport { fileURLToPath } from 'node:url';\r\nimport { Buffer } from 'node:buffer';\r\nimport path from 'node:path';\r\nimport { statSync } from 'node:fs';\r\n\r\nimport { ExcelIoError } from './errors.js';\r\n\r\nconst DEFAULT_THRESHOLD = { rows: 50_000, bytes: 10 * 1024 * 1024 };\r\n\r\nconst moduleDirectory = typeof __EXCELIO_MODULE_DIR__ !== 'undefined'\r\n ? __EXCELIO_MODULE_DIR__\r\n : path.dirname(fileURLToPath(import.meta.url));\r\nconst workerExtension = typeof __EXCELIO_WORKER_EXT__ !== 'undefined'\r\n ? __EXCELIO_WORKER_EXT__\r\n : '.js';\r\nconst WORKER_PATHS = {\r\n write: path.join(moduleDirectory, 'workers', `writer.worker${workerExtension}`),\r\n read: path.join(moduleDirectory, 'workers', `reader.worker${workerExtension}`)\r\n};\r\n\r\n/**\r\n * Decide between inline execution and worker offload based on options.useWorker.\r\n *\r\n * 'auto' \u2192 estimate workload; offload if it exceeds threshold\r\n * true \u2192 always offload\r\n * false \u2192 always inline\r\n *\r\n * Hooks (validateRow, beforeWrite, afterRead, onProgress, signal, logger) are\r\n * NOT serializable, so they can't cross the worker boundary. If any hook is\r\n * provided, we run inline regardless. Workers are best for \"just transform a\r\n * spec/file\" jobs \u2014 typical bulk imports/exports.\r\n */\r\nexport async function maybeUseWorker(op, payload, options, inlineFn) {\r\n const decision = decideMode(op, payload, options);\r\n if (decision.mode === 'inline') return inlineFn();\r\n\r\n return runInWorker(op, payload, sanitiseOptions(options));\r\n}\r\n\r\nfunction decideMode(op, payload, options) {\r\n const useWorker = options.useWorker ?? 'auto';\r\n\r\n if (op === 'read' && payload && typeof payload.pipe === 'function') {\r\n return { mode: 'inline', reason: 'stream input' };\r\n }\r\n if (hasHook(options)) return { mode: 'inline', reason: 'hooks present' };\r\n if (useWorker === false) return { mode: 'inline', reason: 'disabled' };\r\n if (useWorker === true) return { mode: 'worker', reason: 'forced' };\r\n\r\n // auto: estimate\r\n const threshold = { ...DEFAULT_THRESHOLD, ...(options.workerThreshold || {}) };\r\n\r\n if (op === 'write') {\r\n const totalRows = estimateRows(payload);\r\n if (totalRows >= threshold.rows) return { mode: 'worker', reason: `rows ${totalRows} \u2265 ${threshold.rows}` };\r\n return { mode: 'inline', reason: 'below threshold' };\r\n }\r\n\r\n if (op === 'read') {\r\n const bytes = estimateBytes(payload);\r\n if (bytes !== null && bytes >= threshold.bytes) return { mode: 'worker', reason: `bytes ${bytes} \u2265 ${threshold.bytes}` };\r\n return { mode: 'inline', reason: 'below threshold or unknown size' };\r\n }\r\n\r\n return { mode: 'inline', reason: 'unknown op' };\r\n}\r\n\r\nfunction hasHook(options) {\r\n return Boolean(\r\n options.validateRow ||\r\n options.beforeWrite ||\r\n options.afterRead ||\r\n options.onProgress ||\r\n options.logger ||\r\n options.signal ||\r\n // streams can't cross thread boundaries via postMessage either\r\n (options.to && typeof options.to !== 'string')\r\n );\r\n}\r\n\r\nfunction estimateRows(spec) {\r\n if (!Array.isArray(spec)) return 0;\r\n let n = 0;\r\n for (const wb of spec) {\r\n for (const sheet of (wb?.sheets || [])) {\r\n n += (sheet.data?.length || 0);\r\n }\r\n }\r\n return n;\r\n}\r\n\r\nfunction estimateBytes(input) {\r\n if (typeof input === 'string') {\r\n try { return statSync(input).size; } catch { return null; }\r\n }\r\n if (Buffer.isBuffer(input)) return input.length;\r\n return null; // streams: unknown\r\n}\r\n\r\nfunction sanitiseOptions(options) {\r\n // Drop anything that can't cross the postMessage boundary.\r\n const { validateRow, beforeWrite, afterRead, onProgress, signal, logger, to, ...rest } = options;\r\n void validateRow; void beforeWrite; void afterRead; void onProgress; void signal; void logger;\r\n return { ...rest, ...(typeof to === 'string' ? { to } : {}) };\r\n}\r\n\r\nfunction runInWorker(op, payload, options) {\r\n return new Promise((resolve, reject) => {\r\n const workerPath = WORKER_PATHS[op];\r\n if (!workerPath) {\r\n reject(new ExcelIoError(`No worker for op \"${op}\"`, { code: 'WORKER_ERROR' }));\r\n return;\r\n }\r\n\r\n let worker;\r\n try {\r\n worker = new Worker(workerPath, { workerData: { op, payload, options } });\r\n } catch (err) {\r\n reject(new ExcelIoError(err.message, { code: 'WORKER_ERROR', cause: err }));\r\n return;\r\n }\r\n let settled = false;\r\n\r\n worker.once('message', (msg) => {\r\n settled = true;\r\n void worker.terminate().catch(() => {});\r\n if (msg.ok) {\r\n const result = op === 'write' && options.to === undefined\r\n ? (Array.isArray(msg.result) ? msg.result.map(value => Buffer.from(value)) : Buffer.from(msg.result))\r\n : msg.result;\r\n resolve(result);\r\n }\r\n else reject(new ExcelIoError(msg.error?.message || 'Worker error', {\r\n code: msg.error?.code || 'WORKER_ERROR',\r\n cause: msg.error,\r\n details: msg.error?.details\r\n }));\r\n });\r\n worker.once('error', (err) => {\r\n settled = true;\r\n void worker.terminate().catch(() => {});\r\n reject(new ExcelIoError(err.message, { code: 'WORKER_ERROR', cause: err }));\r\n });\r\n worker.once('exit', (code) => {\r\n if (!settled) {\r\n reject(new ExcelIoError(`Worker exited without a result (code ${code})`, { code: 'WORKER_ERROR' }));\r\n }\r\n });\r\n });\r\n}\r\n", "/**\r\n * excelio \u2014 Plug-and-Play Excel \u2194 JSON utility.\r\n *\r\n * Works on Buffers, file paths, or streams. Writes stream rows incrementally;\r\n * reads load complete workbooks. Worker-thread offload above a row/byte threshold\r\n * keeps supported operations off the main thread (auto by default).\r\n *\r\n * Runtime dependencies are `exceljs` and Node built-ins. Install the package\r\n * with npm; distribution files include worker entrypoints and declarations.\r\n *\r\n * Quick start:\r\n *\r\n * import { excelio } from '@dipanshuhandoo/excelio';\r\n *\r\n * // Write\r\n * const buf = await excelio.write([{\r\n * workbook: 'sales',\r\n * sheets: [{ sheet: 'Q1', data: [{ name: 'Alice', amount: 100 }] }]\r\n * }]);\r\n *\r\n * // Read\r\n * const result = await excelio.read(buf, {\r\n * validateRow: (row) => row.amount < 0 ? { message: 'negative amount' } : null\r\n * });\r\n *\r\n * See README.md for the full reference.\r\n */\r\n\r\nimport { writeSpec, writeSpecStream } from './writer.js';\r\nimport { readSource } from './reader.js';\r\nimport { ExcelIoError } from './errors.js';\r\nimport { maybeUseWorker } from './workerPool.js';\r\n\r\nexport const excelio = {\r\n /**\r\n * Write one or more workbooks. Returns a Buffer (or array of Buffers for\r\n * multi-workbook specs) when `to` is omitted; writes to file/stream when `to`\r\n * is provided and returns the target.\r\n */\r\n async write(spec, options = {}) {\r\n return maybeUseWorker('write', spec, options, () => writeSpec(spec, options));\r\n },\r\n\r\n /**\r\n * Returns a Readable stream for the first workbook. Synchronous return;\r\n * errors during the underlying write surface via the stream's 'error' event.\r\n */\r\n writeStream(spec, options = {}) {\r\n return writeSpecStream(spec, options);\r\n },\r\n\r\n /**\r\n * Read a workbook from a Buffer, file path, or Readable stream. Returns a\r\n * structured result with parsed data, per-row errors, and stats.\r\n */\r\n async read(input, options = {}) {\r\n return maybeUseWorker('read', input, options, () => readSource(input, options));\r\n }\r\n};\r\n\r\nexport { ExcelIoError };\r\nexport default excelio;\r\n"],
|
|
5
|
-
"mappings": "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",
|
|
3
|
+
"sources": ["../../src/writer.js", "../../src/errors.js", "../../src/columns.js", "../../src/coerce.js", "../../src/rowSource.js", "../../src/reader.js", "../../src/workerPool.js", "../../src/index.js"],
|
|
4
|
+
"sourcesContent": ["import { PassThrough } from 'node:stream';\r\nimport { createWriteStream } from 'node:fs';\r\nimport { rm } from 'node:fs/promises';\r\nimport { setImmediate as tick, setTimeout as sleep } from 'node:timers/promises';\r\nimport ExcelJS from 'exceljs';\r\n\r\nimport { ExcelIoError } from './errors.js';\r\nimport { resolveColumns } from './columns.js';\r\nimport { valueForWrite } from './coerce.js';\r\nimport { rowSourceKind, isIterableSource, closeIterator, sourceFailure } from './rowSource.js';\r\n\r\nconst DEFAULT_BATCH = 5000;\r\nconst SHEET_NAME_MAX = 31;\r\nexport const EXCEL_MAX_DATA_ROWS = 1_048_575;\r\n// Uncompressed bytes allowed to queue inside exceljs/archiver before an iterable sheet waits.\r\nconst OUTPUT_HIGH_WATER_MARK = 8 * 1024 * 1024;\r\nconst BACKLOG_POLL_MS = 5;\r\n\r\n/**\r\n * Write one or more workbooks from a spec.\r\n *\r\n * Returns:\r\n * - When `to` is omitted: a Buffer for a single-workbook spec, or an array of\r\n * Buffers (one per workbook) for a multi-workbook spec.\r\n * - When `to` is a file path: writes the file, returns the path. Supported only\r\n * when spec has exactly one workbook.\r\n * - When `to` is a Writable stream: pipes the workbook into it. Single workbook only.\r\n *\r\n * Multi-workbook with a single `to` target isn't supported (no zip semantics here).\r\n * For multi-workbook output, omit `to` and get buffers back.\r\n */\r\nexport async function writeSpec(spec, options = {}) {\r\n preflightWrite(spec, options);\r\n\r\n const { to } = options;\r\n if (to !== undefined && spec.length > 1) {\r\n throw new ExcelIoError(\r\n `Multi-workbook output requires omitting \"to\" \u2014 caller writes each buffer itself.`,\r\n { code: 'INVALID_SPEC' }\r\n );\r\n }\r\n\r\n if (to !== undefined) {\r\n await writeOneWorkbook(spec[0], 0, to, options);\r\n return to;\r\n }\r\n\r\n const buffers = [];\r\n for (let wbIndex = 0; wbIndex < spec.length; wbIndex++) {\r\n const buf = await writeOneWorkbookToBuffer(spec[wbIndex], wbIndex, options);\r\n buffers.push(buf);\r\n }\r\n // Ergonomic: single-workbook spec returns a single Buffer; multi returns Buffer[]\r\n return buffers.length === 1 ? buffers[0] : buffers;\r\n}\r\n\r\n/**\r\n * Returns a Readable stream containing the first workbook's bytes. If the spec has\r\n * multiple workbooks, only the first is streamed (callers wanting multi should\r\n * call writeSpec without `to` to get buffers).\r\n */\r\nexport function writeSpecStream(spec, options = {}) {\r\n preflightWrite(spec, options);\r\n const passthrough = new PassThrough();\r\n writeOneWorkbook(spec[0], 0, passthrough, options).catch(err => passthrough.destroy(err));\r\n return passthrough;\r\n}\r\n\r\n/** Validates the spec and write options. Runs before worker routing and again inside writeSpec. */\r\nexport function preflightWrite(spec, options = {}) {\r\n validateSpec(spec);\r\n validateWriteOptions(options);\r\n}\r\n\r\n/* \u2500\u2500\u2500\u2500\u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\r\n\r\nasync function writeOneWorkbookToBuffer(workbookSpec, wbIndex, options) {\r\n const chunks = [];\r\n const collector = new PassThrough();\r\n collector.on('data', (chunk) => chunks.push(chunk));\r\n await writeOneWorkbook(workbookSpec, wbIndex, collector, options, { owned: true });\r\n return Buffer.concat(chunks);\r\n}\r\n\r\nasync function writeOneWorkbook(workbookSpec, wbIndex, target, options, sinkOptions = {}) {\r\n const { signal, onProgress, beforeWrite, batchSize = DEFAULT_BATCH, logger } = options;\r\n const maxRowsPerSheet = options.maxRowsPerSheet ?? EXCEL_MAX_DATA_ROWS;\r\n const sheets = workbookSpec.sheets || [];\r\n const sink = resolveSink(target, sinkOptions);\r\n let wb = null;\r\n\r\n try {\r\n wb = new ExcelJS.stream.xlsx.WorkbookWriter({\r\n stream: sink.writable,\r\n useStyles: true,\r\n useSharedStrings: resolveSharedStrings(options.sharedStrings, sheets)\r\n });\r\n applyWorkbookProperties(wb, workbookSpec.properties);\r\n\r\n // Reserve every logical sheet's first-part name up front so array specs keep 1.0.0 names\r\n // and continuation sheets never take a name a later logical sheet expects.\r\n const used = new Set();\r\n const firstNames = sheets.map((s, i) => sanitiseSheetName(s.sheet || `Sheet ${i + 1}`, used, logger));\r\n const totalRows = computeTotalRows(sheets);\r\n const state = { rowsProcessed: 0, last: { sheetIndex: 0, sheetName: firstNames[0], sheetPart: 1 } };\r\n const emit = () => onProgress?.({\r\n phase: 'write', workbookIndex: wbIndex, ...state.last, rowsProcessed: state.rowsProcessed, totalRows\r\n });\r\n\r\n for (let sIndex = 0; sIndex < sheets.length; sIndex++) {\r\n throwIfAborted(signal);\r\n const sheetSpec = sheets[sIndex];\r\n const writer = createSheetWriter({\r\n wb, workbookSpec, wbIndex, sIndex, sheetSpec, firstName: firstNames[sIndex], used, beforeWrite, maxRowsPerSheet,\r\n onOpen: (sheetName, sheetPart) => { state.last = { sheetIndex: sIndex, sheetName, sheetPart }; },\r\n onRow: () => {\r\n state.rowsProcessed++;\r\n if (onProgress && state.rowsProcessed % batchSize === 0) emit();\r\n }\r\n });\r\n\r\n const kind = rowSourceKind(sheetSpec.data);\r\n if (kind === 'sync' || kind === 'async') {\r\n await writeIterableSheet({ writer, wb, sink, sheetSpec, kind, signal, batchSize, wbIndex, sIndex });\r\n } else {\r\n const data = sheetSpec.data || [];\r\n writer.start(resolveColumns(sheetSpec.columns, data));\r\n for (let i = 0; i < data.length; i++) {\r\n throwIfAborted(signal);\r\n writer.write(data[i]);\r\n }\r\n }\r\n writer.finish();\r\n }\r\n\r\n const committing = wb.commit();\r\n committing.catch(() => {}); // a late rejection after the sink failed is not unhandled\r\n await Promise.race([committing, sink.failed]);\r\n if (sink.cleanup) await Promise.race([sink.cleanup(), sink.failed]);\r\n sink.release();\r\n emit();\r\n } catch (err) {\r\n await abortWorkbook(wb, sink, err);\r\n throw err;\r\n }\r\n}\r\n\r\n/** Writes rows for one logical sheet, rolling over to \"<name> (n)\" worksheets at maxRowsPerSheet. */\r\nfunction createSheetWriter({ wb, workbookSpec, wbIndex, sIndex, sheetSpec, firstName, used, beforeWrite, maxRowsPerSheet, onOpen, onRow }) {\r\n const baseName = sheetSpec.sheet || `Sheet ${sIndex + 1}`;\r\n let cols = [];\r\n let ws = null;\r\n let sheetName = null;\r\n let part = 0;\r\n let rowsInPart = 0;\r\n\r\n const open = () => {\r\n part += 1;\r\n rowsInPart = 0;\r\n // The truncation warning was already logged when the first part's name was reserved.\r\n sheetName = part === 1 ? firstName : sanitiseSheetName(baseName, used, null);\r\n // WorksheetWriter (streaming) doesn't allow setting `views` after creation.\r\n const wsOptions = {};\r\n if (sheetSpec.styling?.freezeHeader) wsOptions.views = [{ state: 'frozen', ySplit: 1 }];\r\n ws = wb.addWorksheet(sheetName, wsOptions);\r\n if (cols.length) {\r\n ws.columns = cols.map(c => ({\r\n key: c.key,\r\n header: c.header,\r\n width: c.width,\r\n style: c.format ? { numFmt: c.format } : undefined\r\n }));\r\n }\r\n applyStylingPostColumns(ws, sheetSpec.styling, cols.length);\r\n onOpen(sheetName, part);\r\n };\r\n\r\n return {\r\n get sheetName() { return sheetName ?? firstName; },\r\n start(resolvedColumns) {\r\n cols = resolvedColumns;\r\n open();\r\n },\r\n write(row) {\r\n if (rowsInPart >= maxRowsPerSheet) {\r\n ws.commit();\r\n open();\r\n }\r\n let out = row;\r\n if (beforeWrite) {\r\n out = beforeWrite(row, {\r\n workbookIndex: wbIndex,\r\n workbookName: workbookSpec.workbook,\r\n sheetIndex: sIndex,\r\n sheetName,\r\n sheetPart: part,\r\n rowNumber: rowsInPart + 2 // header is row 1\r\n }) ?? row;\r\n }\r\n const values = cols.length\r\n ? cols.reduce((acc, c) => { acc[c.key] = valueForWrite(out[c.key], c.type); return acc; }, {})\r\n : out;\r\n ws.addRow(values).commit();\r\n rowsInPart++;\r\n onRow();\r\n },\r\n finish() { ws?.commit(); }\r\n };\r\n}\r\n\r\nasync function writeIterableSheet({ writer, wb, sink, sheetSpec, kind, signal, batchSize, wbIndex, sIndex }) {\r\n let rowsRead = 0;\r\n const details = () => ({ workbookIndex: wbIndex, sheetIndex: sIndex, sheetName: writer.sheetName, rowsRead });\r\n\r\n let iterator;\r\n try {\r\n iterator = kind === 'async' ? sheetSpec.data[Symbol.asyncIterator]() : sheetSpec.data[Symbol.iterator]();\r\n } catch (err) {\r\n throw sourceFailure(err, details(), signal);\r\n }\r\n\r\n const next = async () => {\r\n let step;\r\n try {\r\n step = await iterator.next();\r\n } catch (err) {\r\n throw sourceFailure(err, details(), signal);\r\n }\r\n if (step === null || typeof step !== 'object') {\r\n throw sourceFailure(new TypeError('Iterator result is not an object'), details(), signal);\r\n }\r\n return step;\r\n };\r\n\r\n let finished = false;\r\n try {\r\n let step = await next();\r\n // The peeked first row infers columns (when none are declared) and is then written normally.\r\n writer.start(resolveColumns(sheetSpec.columns, step.done ? [] : [step.value]));\r\n while (!step.done) {\r\n throwIfAborted(signal);\r\n writer.write(step.value);\r\n rowsRead++;\r\n if (rowsRead % batchSize === 0) await waitForCapacity({ wb, sink, signal });\r\n step = await next();\r\n }\r\n finished = true;\r\n } finally {\r\n if (!finished) await closeIterator(iterator);\r\n }\r\n}\r\n\r\nconst len = (n) => (Number.isFinite(n) ? n : 0);\r\n// readable-stream 2.x (archiver-utils' PassThrough around each worksheet) has no length getters.\r\nconst streamLen = (s) =>\r\n len(s?.writableLength ?? s?._writableState?.length) + len(s?.readableLength ?? s?._readableState?.length);\r\n\r\n/**\r\n * Bytes produced but not yet accepted by the sink. Reads exceljs 4.4 / archiver 5.3 internals; every\r\n * read defaults to 0 so an incompatible version degrades to \"yield only\" instead of crashing.\r\n */\r\nfunction backlogBytes(wb, sink) {\r\n let total = streamLen(wb?.zip) + streamLen(wb?.zip?._module) + streamLen(sink?.writable);\r\n for (const ws of wb?._worksheets ?? []) {\r\n const sb = ws?._stream; // not `ws.stream`: that getter opens a stream\r\n if (!sb) continue;\r\n for (const buf of sb.buffers ?? []) total += len(buf?.length);\r\n for (const p of sb.pipes ?? []) total += streamLen(p);\r\n }\r\n return total;\r\n}\r\n\r\nconst backlogStats = { peak: 0 };\r\n\r\nasync function waitForCapacity({ wb, sink, signal }) {\r\n const check = () => {\r\n throwIfAborted(signal);\r\n if (sink.failure) throw sink.failure;\r\n };\r\n for (;;) {\r\n check();\r\n const backlog = backlogBytes(wb, sink);\r\n if (backlog > backlogStats.peak) backlogStats.peak = backlog;\r\n if (backlog <= OUTPUT_HIGH_WATER_MARK) break;\r\n await sleep(BACKLOG_POLL_MS);\r\n }\r\n await tick();\r\n check();\r\n}\r\n\r\nfunction resolveSink(target, { owned = false } = {}) {\r\n const track = (writable, isOwned) => {\r\n const sink = { writable, owned: isOwned, failure: null };\r\n let onError;\r\n sink.failed = new Promise((_, reject) => {\r\n onError = (err) => {\r\n if (sink.failure) return;\r\n sink.failure = err;\r\n reject(err);\r\n };\r\n writable.on('error', onError);\r\n });\r\n sink.failed.catch(() => {});\r\n // Caller-owned streams get their error handling back once excelio is done with them.\r\n sink.release = () => { if (!isOwned) writable.removeListener('error', onError); };\r\n return sink;\r\n };\r\n\r\n if (typeof target === 'string') {\r\n const fileStream = createWriteStream(target);\r\n const sink = track(fileStream, true);\r\n // Register 'finish' and 'close' now so neither is missed before cleanup()/remove() awaits it.\r\n const finished = new Promise((resolve) => fileStream.once('finish', resolve));\r\n const closed = new Promise((resolve) => fileStream.once('close', resolve));\r\n sink.cleanup = () => finished;\r\n sink.remove = async () => {\r\n fileStream.destroy();\r\n await closed; // Windows: rm fails with EPERM while the handle is open\r\n await rm(target, { force: true });\r\n };\r\n return sink;\r\n }\r\n if (target && typeof target.write === 'function') {\r\n return track(target, owned);\r\n }\r\n throw new ExcelIoError(`Invalid write target \u2014 expected file path or writable stream`, { code: 'INVALID_SPEC' });\r\n}\r\n\r\nasync function abortWorkbook(wb, sink, err) {\r\n const quiet = (s) => s?.on?.('error', () => {});\r\n try {\r\n if (wb) {\r\n wb.zip?.unpipe?.(sink.writable); // a caller's stream must not be ended by the archive\r\n quiet(wb.zip);\r\n quiet(wb.zip?._module);\r\n for (const ws of wb._worksheets ?? []) (ws?._stream?.pipes ?? []).forEach(quiet);\r\n wb.zip?.abort?.();\r\n }\r\n if (sink.remove) await sink.remove();\r\n else if (sink.owned) sink.writable.destroy?.();\r\n sink.release();\r\n } catch (cleanupError) {\r\n try {\r\n if ((typeof err === 'object' && err !== null) || typeof err === 'function') err.cleanupError = cleanupError;\r\n } catch { /* frozen or exotic error object: keep the original as is */ }\r\n }\r\n}\r\n\r\nfunction resolveSharedStrings(option = 'auto', sheets) {\r\n if (typeof option === 'boolean') return option;\r\n return !sheets.some((s) => isIterableSource(s?.data));\r\n}\r\n\r\nfunction computeTotalRows(sheets) {\r\n let total = 0;\r\n for (const s of sheets) {\r\n const kind = rowSourceKind(s.data);\r\n if (kind === 'array') total += s.data.length;\r\n else if (kind === 'sync' || kind === 'async') {\r\n if (s.totalRows === undefined) return undefined;\r\n total += s.totalRows;\r\n }\r\n }\r\n return total;\r\n}\r\n\r\nfunction throwIfAborted(signal) {\r\n if (signal?.aborted) throw new ExcelIoError('Aborted', { code: 'ABORTED' });\r\n}\r\n\r\nfunction applyWorkbookProperties(wb, props) {\r\n if (!props) return;\r\n if (props.author) wb.creator = props.author;\r\n if (props.created) wb.created = props.created instanceof Date ? props.created : new Date(props.created);\r\n if (props.modified) wb.modified = props.modified instanceof Date ? props.modified : new Date(props.modified);\r\n if (props.company) wb.company = props.company;\r\n if (props.title) wb.title = props.title;\r\n}\r\n\r\nfunction applyStylingPostColumns(ws, styling, colCount) {\r\n if (!styling) return;\r\n if (styling.headerBold) {\r\n ws.getRow(1).font = { bold: true };\r\n }\r\n if (styling.autoFilter && colCount > 0) {\r\n ws.autoFilter = { from: { row: 1, column: 1 }, to: { row: 1, column: colCount } };\r\n }\r\n // freezeHeader is applied at addWorksheet time (see wsOptions in createSheetWriter).\r\n}\r\n\r\nconst FORBIDDEN_SHEET_CHARS = /[\\\\/?*[\\]:]/g;\r\n\r\nfunction sanitiseSheetName(raw, used, logger) {\r\n let name = String(raw).replace(FORBIDDEN_SHEET_CHARS, '_');\r\n if (name.length > SHEET_NAME_MAX) {\r\n if (logger?.warn) logger.warn(`excelio: sheet name \"${raw}\" truncated to ${SHEET_NAME_MAX} chars`);\r\n name = name.slice(0, SHEET_NAME_MAX);\r\n }\r\n if (!used.has(name)) { used.add(name); return name; }\r\n let i = 2;\r\n while (true) {\r\n const suffix = ` (${i})`;\r\n const candidate = (name.length + suffix.length > SHEET_NAME_MAX\r\n ? name.slice(0, SHEET_NAME_MAX - suffix.length)\r\n : name) + suffix;\r\n if (!used.has(candidate)) { used.add(candidate); return candidate; }\r\n i++;\r\n }\r\n}\r\n\r\nfunction validateSpec(spec) {\r\n if (!Array.isArray(spec) || spec.length === 0) {\r\n throw new ExcelIoError('Spec must be a non-empty array of workbooks', { code: 'INVALID_SPEC' });\r\n }\r\n const owners = new Map(); // iterable object \u2192 first sheet name using it\r\n spec.forEach((wb, wbIndex) => {\r\n if (!wb || typeof wb !== 'object') {\r\n throw new ExcelIoError('Workbook entries must be objects', { code: 'INVALID_SPEC' });\r\n }\r\n if (!Array.isArray(wb.sheets) || wb.sheets.length === 0) {\r\n throw new ExcelIoError('Workbook must have at least one sheet', { code: 'INVALID_SPEC' });\r\n }\r\n wb.sheets.forEach((s, i) => {\r\n if (!s || typeof s !== 'object') {\r\n throw new ExcelIoError(`Workbook ${wbIndex}: sheet entries must be objects`, { code: 'INVALID_SPEC' });\r\n }\r\n const name = s.sheet || `Sheet ${i + 1}`;\r\n const kind = rowSourceKind(s.data);\r\n if (kind === 'invalid') {\r\n throw new ExcelIoError(`Sheet \"${name}\": data must be an array or an iterable of row objects`, { code: 'INVALID_SPEC' });\r\n }\r\n if (kind === 'sync' || kind === 'async') {\r\n if (owners.has(s.data)) {\r\n throw new ExcelIoError(\r\n `Sheet \"${name}\": its data source is already used by sheet \"${owners.get(s.data)}\". Pass a separate iterable (or an array) per sheet.`,\r\n { code: 'INVALID_SPEC' });\r\n }\r\n owners.set(s.data, name);\r\n }\r\n if (s.totalRows !== undefined && !(Number.isInteger(s.totalRows) && s.totalRows >= 0)) {\r\n throw new ExcelIoError(`Sheet \"${name}\": totalRows must be a non-negative integer`, { code: 'INVALID_SPEC' });\r\n }\r\n });\r\n });\r\n}\r\n\r\nfunction validateWriteOptions({ maxRowsPerSheet, sharedStrings, batchSize } = {}) {\r\n if (maxRowsPerSheet !== undefined &&\r\n !(Number.isInteger(maxRowsPerSheet) && maxRowsPerSheet >= 1 && maxRowsPerSheet <= EXCEL_MAX_DATA_ROWS)) {\r\n throw new ExcelIoError(`maxRowsPerSheet must be an integer between 1 and ${EXCEL_MAX_DATA_ROWS}`, { code: 'INVALID_SPEC' });\r\n }\r\n if (sharedStrings !== undefined && sharedStrings !== 'auto' && typeof sharedStrings !== 'boolean') {\r\n throw new ExcelIoError(`sharedStrings must be 'auto', true or false`, { code: 'INVALID_SPEC' });\r\n }\r\n if (batchSize !== undefined && !(Number.isInteger(batchSize) && batchSize >= 1)) {\r\n throw new ExcelIoError('batchSize must be a positive integer', { code: 'INVALID_SPEC' });\r\n }\r\n}\r\n\r\n// Helpers exported for tests\r\nexport const __test = { sanitiseSheetName, backlogBytes, backlogStats, OUTPUT_HIGH_WATER_MARK };\r\n", "/**\r\n * Custom error type for excelio. No external dependencies \u2014 keeps the package\r\n * portable to any Node project.\r\n *\r\n * Codes:\r\n * INVALID_SPEC \u2014 caller passed a malformed spec\r\n * IO_ERROR \u2014 corrupt input file, write failure, etc.\r\n * ABORTED \u2014 operation cancelled via AbortController\r\n * WORKER_ERROR \u2014 worker thread crashed or returned an error\r\n * ROW_VALIDATION \u2014 a row failed validation (only thrown when onRowError === 'fail')\r\n * SOURCE_ERROR \u2014 an iterable sheet's row source threw or returned an invalid result\r\n */\r\nexport class ExcelIoError extends Error {\r\n constructor(message, { code = 'IO_ERROR', cause, details } = {}) {\r\n super(message);\r\n this.name = 'ExcelIoError';\r\n this.code = code;\r\n if (cause !== undefined) this.cause = cause;\r\n if (details !== undefined) this.details = details;\r\n }\r\n}\r\n", "/**\r\n * Column metadata helpers.\r\n *\r\n * A column entry shape:\r\n * { key, header?, type?, format?, width? }\r\n *\r\n * key : property name on each data row (required)\r\n * header : displayed in the first row (defaults to key)\r\n * type : 'string' | 'number' | 'boolean' | 'date' (informs cell formatting)\r\n * format : Excel number-format string (e.g. 'yyyy-mm-dd', '#,##0.00')\r\n * width : column width in Excel units (default 15)\r\n */\r\n\r\n/**\r\n * Resolve the columns for a sheet. If the caller provided columns, validate/normalise.\r\n * Otherwise infer from the first row's keys (preserving insertion order).\r\n */\r\nexport function resolveColumns(declaredColumns, data) {\r\n if (Array.isArray(declaredColumns) && declaredColumns.length) {\r\n return declaredColumns.map(normaliseColumn);\r\n }\r\n if (!data?.length) return [];\r\n const firstRow = data[0] || {};\r\n return Object.keys(firstRow).map(k => normaliseColumn({ key: k }));\r\n}\r\n\r\nfunction normaliseColumn(c) {\r\n if (!c || typeof c !== 'object' || !c.key) {\r\n throw new Error(`excelio: column entry must have a \"key\" property; got ${JSON.stringify(c)}`);\r\n }\r\n return {\r\n key: String(c.key),\r\n header: c.header ?? c.key,\r\n type: c.type ?? null,\r\n format: c.format ?? defaultFormatFor(c.type),\r\n width: c.width ?? 15\r\n };\r\n}\r\n\r\nfunction defaultFormatFor(type) {\r\n switch (type) {\r\n case 'date': return 'yyyy-mm-dd hh:mm:ss';\r\n case 'number': return null;\r\n default: return null;\r\n }\r\n}\r\n", "/**\r\n * Cell value coercion in both directions.\r\n *\r\n * Write side: accept a JS value + optional column type, normalise to what exceljs\r\n * expects. Excel-native types are Number, String, Boolean, Date, formula objects,\r\n * and null.\r\n *\r\n * Read side: take a cell from exceljs and turn it into a portable JS value. Dates\r\n * default to ISO 8601 strings; configurable via `dateFormat`.\r\n */\r\n\r\nconst ISO_DATE_PATTERN = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?)?$/;\r\n\r\n/**\r\n * Normalise a JS value for writing into a cell. Returns the value as-is for most\r\n * types; converts ISO date strings + epoch ms to Date when the column declares\r\n * `type: 'date'`.\r\n */\r\nexport function valueForWrite(value, columnType) {\r\n if (value === null || value === undefined) return null;\r\n\r\n if (columnType === 'date') {\r\n if (value instanceof Date) return value;\r\n if (typeof value === 'number') return new Date(value);\r\n if (typeof value === 'string' && ISO_DATE_PATTERN.test(value)) {\r\n const d = new Date(value);\r\n return isNaN(d.getTime()) ? value : d;\r\n }\r\n return value;\r\n }\r\n\r\n if (columnType === 'number' && typeof value === 'string' && value !== '') {\r\n const n = Number(value);\r\n return Number.isFinite(n) ? n : value;\r\n }\r\n\r\n if (columnType === 'boolean') {\r\n if (typeof value === 'boolean') return value;\r\n if (value === 'true' || value === 1) return true;\r\n if (value === 'false' || value === 0) return false;\r\n }\r\n\r\n return value;\r\n}\r\n\r\n/**\r\n * Convert an exceljs cell value into a portable JS value.\r\n *\r\n * options:\r\n * nullForBlank: boolean \u2014 empty cells become null (default true)\r\n * trimStrings: boolean \u2014 strip leading/trailing whitespace from strings\r\n * dateFormat: 'iso' | 'date' | 'epoch'\r\n */\r\nexport function valueForRead(cell, { nullForBlank = true, trimStrings = true, dateFormat = 'iso' } = {}) {\r\n if (cell === undefined || cell === null) return nullForBlank ? null : '';\r\n\r\n // exceljs returns CellValue which can be primitive or object; cell.value is the\r\n // canonical accessor. When called with a raw value (e.g. from streaming), it's\r\n // already the primitive.\r\n const raw = (cell && typeof cell === 'object' && 'value' in cell) ? cell.value : cell;\r\n\r\n if (raw === null || raw === undefined || raw === '') return nullForBlank ? null : '';\r\n\r\n // Date cells\r\n if (raw instanceof Date) return formatDate(raw, dateFormat);\r\n\r\n // Hyperlink object: { text, hyperlink, ... } \u2014 return the visible text\r\n if (typeof raw === 'object' && raw.text !== undefined && raw.hyperlink !== undefined) {\r\n return trimStrings ? String(raw.text).trim() : String(raw.text);\r\n }\r\n\r\n // Rich text object: { richText: [{ text, font }, ...] }\r\n if (typeof raw === 'object' && Array.isArray(raw.richText)) {\r\n const joined = raw.richText.map(r => r.text).join('');\r\n return trimStrings ? joined.trim() : joined;\r\n }\r\n\r\n // Formula object: { formula, result }\r\n if (typeof raw === 'object' && raw.formula !== undefined) {\r\n return raw.result !== undefined ? raw.result : null;\r\n }\r\n\r\n // Error cell: { error: '#N/A' }\r\n if (typeof raw === 'object' && raw.error !== undefined) return null;\r\n\r\n if (typeof raw === 'string') return trimStrings ? raw.trim() : raw;\r\n return raw;\r\n}\r\n\r\nfunction formatDate(d, fmt) {\r\n switch (fmt) {\r\n case 'date': return d;\r\n case 'epoch': return d.getTime();\r\n case 'iso':\r\n default: return d.toISOString();\r\n }\r\n}\r\n", "import { ExcelIoError } from './errors.js';\r\n\r\n/** 'empty' | 'array' | 'sync' | 'async' | 'invalid' */\r\nexport function rowSourceKind(data) {\r\n if (data === undefined || data === null) return 'empty';\r\n if (Array.isArray(data)) return 'array';\r\n if (typeof data !== 'object' && typeof data !== 'function') return 'invalid';\r\n if (typeof data[Symbol.asyncIterator] === 'function') return 'async';\r\n if (typeof data[Symbol.iterator] === 'function') return 'sync';\r\n return 'invalid';\r\n}\r\n\r\nexport const isIterableSource = (data) => {\r\n const kind = rowSourceKind(data);\r\n return kind === 'sync' || kind === 'async';\r\n};\r\n\r\nexport const specHasIterable = (spec) =>\r\n Array.isArray(spec) && spec.some((wb) => (Array.isArray(wb?.sheets) ? wb.sheets : []).some((s) => isIterableSource(s?.data)));\r\n\r\n/** Closes a partially consumed iterator (cursor, stream). Never throws. */\r\nexport async function closeIterator(iterator) {\r\n if (typeof iterator?.return !== 'function') return;\r\n try { await iterator.return(); } catch { /* the source is already failing or closed */ }\r\n}\r\n\r\n/** SOURCE_ERROR, or ABORTED when the caller's signal caused the failure. */\r\nexport function sourceFailure(err, details, signal) {\r\n if (signal?.aborted) return new ExcelIoError('Aborted', { code: 'ABORTED', cause: err, details });\r\n return new ExcelIoError(`Row source failed for sheet \"${details.sheetName}\": ${err?.message ?? err}`, {\r\n code: 'SOURCE_ERROR', cause: err, details\r\n });\r\n}\r\n", "import { Readable } from 'node:stream';\r\nimport { Buffer } from 'node:buffer';\r\nimport { createReadStream } from 'node:fs';\r\nimport { stat } from 'node:fs/promises';\r\nimport ExcelJS from 'exceljs';\r\n\r\nimport { ExcelIoError } from './errors.js';\r\nimport { valueForRead } from './coerce.js';\r\n\r\nconst DEFAULT_BATCH = 5000;\r\n\r\n/**\r\n * Read a workbook from a Buffer, file path, or readable stream.\r\n *\r\n * Currently uses the non-streaming `xlsx.load` / `xlsx.read` API for reliability.\r\n * Large files may exceed available memory. Worker-thread offload keeps parsing\r\n * off the main thread, but does not reduce total process memory or isolate it.\r\n * A future optimisation can swap to `stream.xlsx.WorkbookReader` once exceljs\r\n * stabilises its async iterator semantics across versions.\r\n */\r\nexport async function readSource(input, options = {}) {\r\n const startedAt = Date.now();\r\n const stats = { totalRows: 0, totalSheets: 0, durationMs: 0 };\r\n const errors = [];\r\n\r\n const {\r\n headerRow = 1,\r\n nullForBlank = true,\r\n trimStrings = true,\r\n dateFormat = 'iso',\r\n validateRow,\r\n afterRead,\r\n onRowError = 'collect',\r\n batchSize = DEFAULT_BATCH,\r\n onProgress,\r\n signal\r\n } = options;\r\n\r\n const wb = new ExcelJS.Workbook();\r\n try {\r\n if (Buffer.isBuffer(input)) {\r\n await wb.xlsx.load(input);\r\n } else if (input instanceof Uint8Array) {\r\n // Worker boundary downgrades Buffer to Uint8Array; rewrap.\r\n await wb.xlsx.load(Buffer.from(input.buffer, input.byteOffset, input.byteLength));\r\n } else if (typeof input === 'string') {\r\n await wb.xlsx.readFile(input);\r\n } else if (input && typeof input.pipe === 'function') {\r\n await wb.xlsx.read(input);\r\n } else {\r\n throw new ExcelIoError('Invalid input \u2014 expected Buffer, file path, or readable stream', { code: 'INVALID_SPEC' });\r\n }\r\n } catch (err) {\r\n if (err instanceof ExcelIoError) throw err;\r\n throw new ExcelIoError(`Failed to parse workbook: ${err.message}`, { code: 'IO_ERROR', cause: err });\r\n }\r\n\r\n const sheets = [];\r\n\r\n for (let s = 0; s < wb.worksheets.length; s++) {\r\n if (signal?.aborted) throw new ExcelIoError('Aborted', { code: 'ABORTED' });\r\n\r\n const ws = wb.worksheets[s];\r\n stats.totalSheets++;\r\n\r\n const sheetMeta = { sheet: ws.name, columns: [], data: [] };\r\n let columnKeys = null;\r\n\r\n ws.eachRow({ includeEmpty: false }, (row, rowNumber) => {\r\n // Header row\r\n if (rowNumber === headerRow) {\r\n columnKeys = readHeaderRow(row);\r\n sheetMeta.columns = columnKeys\r\n .filter(Boolean)\r\n .map(k => ({ key: k, header: k }));\r\n return;\r\n }\r\n if (rowNumber < headerRow || !columnKeys) return;\r\n if (signal?.aborted) throw new ExcelIoError('Aborted', { code: 'ABORTED' });\r\n\r\n const obj = {};\r\n let isEmpty = true;\r\n for (let i = 0; i < columnKeys.length; i++) {\r\n const key = columnKeys[i];\r\n if (!key) continue;\r\n const cell = row.getCell(i + 1);\r\n const v = valueForRead(cell, { nullForBlank, trimStrings, dateFormat });\r\n if (v !== null && v !== '' && v !== undefined) isEmpty = false;\r\n obj[key] = v;\r\n }\r\n if (isEmpty) return;\r\n\r\n const ctx = {\r\n workbookIndex: 0,\r\n workbookName: undefined,\r\n sheetIndex: s,\r\n sheetName: ws.name,\r\n rowNumber\r\n };\r\n\r\n let outRow = obj;\r\n if (afterRead) {\r\n try {\r\n outRow = afterRead(obj, ctx) ?? obj;\r\n } catch (err) {\r\n const e = mkRowError(ctx, 'TRANSFORM_ERROR', err.message);\r\n if (onRowError === 'fail') throw new ExcelIoError(e.message, { code: 'ROW_VALIDATION', details: e });\r\n errors.push(e);\r\n return;\r\n }\r\n }\r\n\r\n if (validateRow) {\r\n const issue = validateRow(outRow, ctx);\r\n if (issue) {\r\n const e = mkRowError(ctx, issue.code || 'VALIDATION_FAILED', issue.message, issue.column);\r\n if (onRowError === 'fail') throw new ExcelIoError(e.message, { code: 'ROW_VALIDATION', details: e });\r\n errors.push(e);\r\n return;\r\n }\r\n }\r\n\r\n sheetMeta.data.push(outRow);\r\n stats.totalRows++;\r\n\r\n if (onProgress && stats.totalRows % batchSize === 0) {\r\n onProgress({ phase: 'read', sheetName: ws.name, rowsProcessed: stats.totalRows });\r\n }\r\n });\r\n\r\n sheets.push(sheetMeta);\r\n }\r\n\r\n stats.durationMs = Date.now() - startedAt;\r\n\r\n return {\r\n ok: errors.length === 0,\r\n data: [{ workbook: undefined, sheets }],\r\n errors,\r\n stats\r\n };\r\n}\r\n\r\n/* \u2500\u2500\u2500\u2500\u2500\u2500 helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\r\n\r\nfunction readHeaderRow(row) {\r\n const headers = [];\r\n // exceljs row.values is sparse: index 0 unused, headers start at 1\r\n const values = row.values;\r\n if (!Array.isArray(values)) return headers;\r\n for (let i = 1; i < values.length; i++) {\r\n const v = values[i];\r\n headers.push(v == null ? null : String(v).trim());\r\n }\r\n return headers;\r\n}\r\n\r\nfunction mkRowError(ctx, code, message, column) {\r\n return {\r\n workbook: ctx.workbookIndex,\r\n sheet: ctx.sheetName,\r\n row: ctx.rowNumber,\r\n column: column ?? null,\r\n code,\r\n message\r\n };\r\n}\r\n", "import { Worker } from 'node:worker_threads';\r\nimport { fileURLToPath } from 'node:url';\r\nimport { Buffer } from 'node:buffer';\r\nimport path from 'node:path';\r\nimport { statSync } from 'node:fs';\r\n\r\nimport { ExcelIoError } from './errors.js';\r\nimport { specHasIterable } from './rowSource.js';\r\n\r\nconst DEFAULT_THRESHOLD = { rows: 50_000, bytes: 10 * 1024 * 1024 };\r\n\r\nconst moduleDirectory = typeof __EXCELIO_MODULE_DIR__ !== 'undefined'\r\n ? __EXCELIO_MODULE_DIR__\r\n : path.dirname(fileURLToPath(import.meta.url));\r\nconst workerExtension = typeof __EXCELIO_WORKER_EXT__ !== 'undefined'\r\n ? __EXCELIO_WORKER_EXT__\r\n : '.js';\r\nconst WORKER_PATHS = {\r\n write: path.join(moduleDirectory, 'workers', `writer.worker${workerExtension}`),\r\n read: path.join(moduleDirectory, 'workers', `reader.worker${workerExtension}`)\r\n};\r\n\r\n/**\r\n * Decide between inline execution and worker offload based on options.useWorker.\r\n *\r\n * 'auto' \u2192 estimate workload; offload if it exceeds threshold\r\n * true \u2192 always offload\r\n * false \u2192 always inline\r\n *\r\n * Hooks (validateRow, beforeWrite, afterRead, onProgress, signal, logger) are\r\n * NOT serializable, so they can't cross the worker boundary. If any hook is\r\n * provided, we run inline regardless. Workers are best for \"just transform a\r\n * spec/file\" jobs \u2014 typical bulk imports/exports.\r\n */\r\nexport async function maybeUseWorker(op, payload, options, inlineFn) {\r\n const decision = decideMode(op, payload, options);\r\n if (decision.mode === 'inline') return inlineFn();\r\n\r\n return runInWorker(op, payload, sanitiseOptions(options));\r\n}\r\n\r\nfunction decideMode(op, payload, options) {\r\n const useWorker = options.useWorker ?? 'auto';\r\n\r\n if (op === 'read' && payload && typeof payload.pipe === 'function') {\r\n return { mode: 'inline', reason: 'stream input' };\r\n }\r\n // Iterators cannot be structured-cloned into a worker.\r\n if (op === 'write' && specHasIterable(payload)) {\r\n if (useWorker === true) options.logger?.warn?.('excelio: iterable sheet data is written inline; useWorker ignored');\r\n return { mode: 'inline', reason: 'iterable sheet data' };\r\n }\r\n if (hasHook(options)) return { mode: 'inline', reason: 'hooks present' };\r\n if (useWorker === false) return { mode: 'inline', reason: 'disabled' };\r\n if (useWorker === true) return { mode: 'worker', reason: 'forced' };\r\n\r\n // auto: estimate\r\n const threshold = { ...DEFAULT_THRESHOLD, ...(options.workerThreshold || {}) };\r\n\r\n if (op === 'write') {\r\n const totalRows = estimateRows(payload);\r\n if (totalRows >= threshold.rows) return { mode: 'worker', reason: `rows ${totalRows} \u2265 ${threshold.rows}` };\r\n return { mode: 'inline', reason: 'below threshold' };\r\n }\r\n\r\n if (op === 'read') {\r\n const bytes = estimateBytes(payload);\r\n if (bytes !== null && bytes >= threshold.bytes) return { mode: 'worker', reason: `bytes ${bytes} \u2265 ${threshold.bytes}` };\r\n return { mode: 'inline', reason: 'below threshold or unknown size' };\r\n }\r\n\r\n return { mode: 'inline', reason: 'unknown op' };\r\n}\r\n\r\nfunction hasHook(options) {\r\n return Boolean(\r\n options.validateRow ||\r\n options.beforeWrite ||\r\n options.afterRead ||\r\n options.onProgress ||\r\n options.logger ||\r\n options.signal ||\r\n // streams can't cross thread boundaries via postMessage either\r\n (options.to && typeof options.to !== 'string')\r\n );\r\n}\r\n\r\nfunction estimateRows(spec) {\r\n if (!Array.isArray(spec)) return 0;\r\n let n = 0;\r\n for (const wb of spec) {\r\n for (const sheet of (wb?.sheets || [])) {\r\n n += Array.isArray(sheet?.data) ? sheet.data.length : 0;\r\n }\r\n }\r\n return n;\r\n}\r\n\r\nfunction estimateBytes(input) {\r\n if (typeof input === 'string') {\r\n try { return statSync(input).size; } catch { return null; }\r\n }\r\n if (Buffer.isBuffer(input)) return input.length;\r\n return null; // streams: unknown\r\n}\r\n\r\nfunction sanitiseOptions(options) {\r\n // Drop anything that can't cross the postMessage boundary.\r\n const { validateRow, beforeWrite, afterRead, onProgress, signal, logger, to, ...rest } = options;\r\n void validateRow; void beforeWrite; void afterRead; void onProgress; void signal; void logger;\r\n return { ...rest, ...(typeof to === 'string' ? { to } : {}) };\r\n}\r\n\r\nfunction runInWorker(op, payload, options) {\r\n return new Promise((resolve, reject) => {\r\n const workerPath = WORKER_PATHS[op];\r\n if (!workerPath) {\r\n reject(new ExcelIoError(`No worker for op \"${op}\"`, { code: 'WORKER_ERROR' }));\r\n return;\r\n }\r\n\r\n let worker;\r\n try {\r\n worker = new Worker(workerPath, { workerData: { op, payload, options } });\r\n } catch (err) {\r\n reject(new ExcelIoError(err.message, { code: 'WORKER_ERROR', cause: err }));\r\n return;\r\n }\r\n let settled = false;\r\n\r\n worker.once('message', (msg) => {\r\n settled = true;\r\n void worker.terminate().catch(() => {});\r\n if (msg.ok) {\r\n const result = op === 'write' && options.to === undefined\r\n ? (Array.isArray(msg.result) ? msg.result.map(value => Buffer.from(value)) : Buffer.from(msg.result))\r\n : msg.result;\r\n resolve(result);\r\n }\r\n else reject(new ExcelIoError(msg.error?.message || 'Worker error', {\r\n code: msg.error?.code || 'WORKER_ERROR',\r\n cause: msg.error,\r\n details: msg.error?.details\r\n }));\r\n });\r\n worker.once('error', (err) => {\r\n settled = true;\r\n void worker.terminate().catch(() => {});\r\n reject(new ExcelIoError(err.message, { code: 'WORKER_ERROR', cause: err }));\r\n });\r\n worker.once('exit', (code) => {\r\n if (!settled) {\r\n reject(new ExcelIoError(`Worker exited without a result (code ${code})`, { code: 'WORKER_ERROR' }));\r\n }\r\n });\r\n });\r\n}\r\n", "/**\r\n * excelio \u2014 Plug-and-Play Excel \u2194 JSON utility.\r\n *\r\n * Works on Buffers, file paths, or streams. Writes stream rows incrementally;\r\n * reads load complete workbooks. Worker-thread offload above a row/byte threshold\r\n * keeps supported operations off the main thread (auto by default).\r\n *\r\n * Runtime dependencies are `exceljs` and Node built-ins. Install the package\r\n * with npm; distribution files include worker entrypoints and declarations.\r\n *\r\n * Quick start:\r\n *\r\n * import { excelio } from '@dipanshuhandoo/excelio';\r\n *\r\n * // Write\r\n * const buf = await excelio.write([{\r\n * workbook: 'sales',\r\n * sheets: [{ sheet: 'Q1', data: [{ name: 'Alice', amount: 100 }] }]\r\n * }]);\r\n *\r\n * // Read\r\n * const result = await excelio.read(buf, {\r\n * validateRow: (row) => row.amount < 0 ? { message: 'negative amount' } : null\r\n * });\r\n *\r\n * See README.md for the full reference.\r\n */\r\n\r\nimport { writeSpec, writeSpecStream, preflightWrite } from './writer.js';\r\nimport { readSource } from './reader.js';\r\nimport { ExcelIoError } from './errors.js';\r\nimport { maybeUseWorker } from './workerPool.js';\r\n\r\nexport const excelio = {\r\n /**\r\n * Write one or more workbooks. Returns a Buffer (or array of Buffers for\r\n * multi-workbook specs) when `to` is omitted; writes to file/stream when `to`\r\n * is provided and returns the target.\r\n */\r\n async write(spec, options = {}) {\r\n // Validate before routing so invalid specs fail the same way inline and in a worker.\r\n preflightWrite(spec, options);\r\n return maybeUseWorker('write', spec, options, () => writeSpec(spec, options));\r\n },\r\n\r\n /**\r\n * Returns a Readable stream for the first workbook. Synchronous return;\r\n * spec errors throw immediately, errors during the underlying write surface\r\n * via the stream's 'error' event.\r\n */\r\n writeStream(spec, options = {}) {\r\n preflightWrite(spec, options);\r\n return writeSpecStream(spec, options);\r\n },\r\n\r\n /**\r\n * Read a workbook from a Buffer, file path, or Readable stream. Returns a\r\n * structured result with parsed data, per-row errors, and stats.\r\n */\r\n async read(input, options = {}) {\r\n return maybeUseWorker('read', input, options, () => readSource(input, options));\r\n }\r\n};\r\n\r\nexport { ExcelIoError };\r\nexport default excelio;\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["Buffer", "ExcelJS", "DEFAULT_BATCH", "ExcelJS", "Buffer", "Buffer", "Buffer"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/workers/reader.worker.js", "../../../src/reader.js", "../../../src/errors.js", "../../../src/coerce.js"],
|
|
4
|
-
"sourcesContent": ["import { parentPort, workerData } from 'node:worker_threads';\r\nimport { readSource } from '../reader.js';\r\n\r\n(async () => {\r\n try {\r\n const { payload, options } = workerData;\r\n const result = await readSource(payload, options);\r\n parentPort.postMessage({ ok: true, result });\r\n } catch (err) {\r\n parentPort.postMessage({\r\n ok: false,\r\n error: { message: err.message, code: err.code, stack: err.stack, details: err.details }\r\n });\r\n }\r\n})();\r\n", "import { Readable } from 'node:stream';\r\nimport { Buffer } from 'node:buffer';\r\nimport { createReadStream } from 'node:fs';\r\nimport { stat } from 'node:fs/promises';\r\nimport ExcelJS from 'exceljs';\r\n\r\nimport { ExcelIoError } from './errors.js';\r\nimport { valueForRead } from './coerce.js';\r\n\r\nconst DEFAULT_BATCH = 5000;\r\n\r\n/**\r\n * Read a workbook from a Buffer, file path, or readable stream.\r\n *\r\n * Currently uses the non-streaming `xlsx.load` / `xlsx.read` API for reliability.\r\n * Large files may exceed available memory. Worker-thread offload keeps parsing\r\n * off the main thread, but does not reduce total process memory or isolate it.\r\n * A future optimisation can swap to `stream.xlsx.WorkbookReader` once exceljs\r\n * stabilises its async iterator semantics across versions.\r\n */\r\nexport async function readSource(input, options = {}) {\r\n const startedAt = Date.now();\r\n const stats = { totalRows: 0, totalSheets: 0, durationMs: 0 };\r\n const errors = [];\r\n\r\n const {\r\n headerRow = 1,\r\n nullForBlank = true,\r\n trimStrings = true,\r\n dateFormat = 'iso',\r\n validateRow,\r\n afterRead,\r\n onRowError = 'collect',\r\n batchSize = DEFAULT_BATCH,\r\n onProgress,\r\n signal\r\n } = options;\r\n\r\n const wb = new ExcelJS.Workbook();\r\n try {\r\n if (Buffer.isBuffer(input)) {\r\n await wb.xlsx.load(input);\r\n } else if (input instanceof Uint8Array) {\r\n // Worker boundary downgrades Buffer to Uint8Array; rewrap.\r\n await wb.xlsx.load(Buffer.from(input.buffer, input.byteOffset, input.byteLength));\r\n } else if (typeof input === 'string') {\r\n await wb.xlsx.readFile(input);\r\n } else if (input && typeof input.pipe === 'function') {\r\n await wb.xlsx.read(input);\r\n } else {\r\n throw new ExcelIoError('Invalid input \u2014 expected Buffer, file path, or readable stream', { code: 'INVALID_SPEC' });\r\n }\r\n } catch (err) {\r\n if (err instanceof ExcelIoError) throw err;\r\n throw new ExcelIoError(`Failed to parse workbook: ${err.message}`, { code: 'IO_ERROR', cause: err });\r\n }\r\n\r\n const sheets = [];\r\n\r\n for (let s = 0; s < wb.worksheets.length; s++) {\r\n if (signal?.aborted) throw new ExcelIoError('Aborted', { code: 'ABORTED' });\r\n\r\n const ws = wb.worksheets[s];\r\n stats.totalSheets++;\r\n\r\n const sheetMeta = { sheet: ws.name, columns: [], data: [] };\r\n let columnKeys = null;\r\n\r\n ws.eachRow({ includeEmpty: false }, (row, rowNumber) => {\r\n // Header row\r\n if (rowNumber === headerRow) {\r\n columnKeys = readHeaderRow(row);\r\n sheetMeta.columns = columnKeys\r\n .filter(Boolean)\r\n .map(k => ({ key: k, header: k }));\r\n return;\r\n }\r\n if (rowNumber < headerRow || !columnKeys) return;\r\n if (signal?.aborted) throw new ExcelIoError('Aborted', { code: 'ABORTED' });\r\n\r\n const obj = {};\r\n let isEmpty = true;\r\n for (let i = 0; i < columnKeys.length; i++) {\r\n const key = columnKeys[i];\r\n if (!key) continue;\r\n const cell = row.getCell(i + 1);\r\n const v = valueForRead(cell, { nullForBlank, trimStrings, dateFormat });\r\n if (v !== null && v !== '' && v !== undefined) isEmpty = false;\r\n obj[key] = v;\r\n }\r\n if (isEmpty) return;\r\n\r\n const ctx = {\r\n workbookIndex: 0,\r\n workbookName: undefined,\r\n sheetIndex: s,\r\n sheetName: ws.name,\r\n rowNumber\r\n };\r\n\r\n let outRow = obj;\r\n if (afterRead) {\r\n try {\r\n outRow = afterRead(obj, ctx) ?? obj;\r\n } catch (err) {\r\n const e = mkRowError(ctx, 'TRANSFORM_ERROR', err.message);\r\n if (onRowError === 'fail') throw new ExcelIoError(e.message, { code: 'ROW_VALIDATION', details: e });\r\n errors.push(e);\r\n return;\r\n }\r\n }\r\n\r\n if (validateRow) {\r\n const issue = validateRow(outRow, ctx);\r\n if (issue) {\r\n const e = mkRowError(ctx, issue.code || 'VALIDATION_FAILED', issue.message, issue.column);\r\n if (onRowError === 'fail') throw new ExcelIoError(e.message, { code: 'ROW_VALIDATION', details: e });\r\n errors.push(e);\r\n return;\r\n }\r\n }\r\n\r\n sheetMeta.data.push(outRow);\r\n stats.totalRows++;\r\n\r\n if (onProgress && stats.totalRows % batchSize === 0) {\r\n onProgress({ phase: 'read', sheetName: ws.name, rowsProcessed: stats.totalRows });\r\n }\r\n });\r\n\r\n sheets.push(sheetMeta);\r\n }\r\n\r\n stats.durationMs = Date.now() - startedAt;\r\n\r\n return {\r\n ok: errors.length === 0,\r\n data: [{ workbook: undefined, sheets }],\r\n errors,\r\n stats\r\n };\r\n}\r\n\r\n/* \u2500\u2500\u2500\u2500\u2500\u2500 helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\r\n\r\nfunction readHeaderRow(row) {\r\n const headers = [];\r\n // exceljs row.values is sparse: index 0 unused, headers start at 1\r\n const values = row.values;\r\n if (!Array.isArray(values)) return headers;\r\n for (let i = 1; i < values.length; i++) {\r\n const v = values[i];\r\n headers.push(v == null ? null : String(v).trim());\r\n }\r\n return headers;\r\n}\r\n\r\nfunction mkRowError(ctx, code, message, column) {\r\n return {\r\n workbook: ctx.workbookIndex,\r\n sheet: ctx.sheetName,\r\n row: ctx.rowNumber,\r\n column: column ?? null,\r\n code,\r\n message\r\n };\r\n}\r\n", "/**\r\n * Custom error type for excelio. No external dependencies \u2014 keeps the package\r\n * portable to any Node project.\r\n *\r\n * Codes:\r\n * INVALID_SPEC \u2014 caller passed a malformed spec\r\n * IO_ERROR \u2014 corrupt input file, write failure, etc.\r\n * ABORTED \u2014 operation cancelled via AbortController\r\n * WORKER_ERROR \u2014 worker thread crashed or returned an error\r\n * ROW_VALIDATION \u2014 a row failed validation (only thrown when onRowError === 'fail')\r\n */\r\nexport class ExcelIoError extends Error {\r\n constructor(message, { code = 'IO_ERROR', cause, details } = {}) {\r\n super(message);\r\n this.name = 'ExcelIoError';\r\n this.code = code;\r\n if (cause !== undefined) this.cause = cause;\r\n if (details !== undefined) this.details = details;\r\n }\r\n}\r\n", "/**\r\n * Cell value coercion in both directions.\r\n *\r\n * Write side: accept a JS value + optional column type, normalise to what exceljs\r\n * expects. Excel-native types are Number, String, Boolean, Date, formula objects,\r\n * and null.\r\n *\r\n * Read side: take a cell from exceljs and turn it into a portable JS value. Dates\r\n * default to ISO 8601 strings; configurable via `dateFormat`.\r\n */\r\n\r\nconst ISO_DATE_PATTERN = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?)?$/;\r\n\r\n/**\r\n * Normalise a JS value for writing into a cell. Returns the value as-is for most\r\n * types; converts ISO date strings + epoch ms to Date when the column declares\r\n * `type: 'date'`.\r\n */\r\nexport function valueForWrite(value, columnType) {\r\n if (value === null || value === undefined) return null;\r\n\r\n if (columnType === 'date') {\r\n if (value instanceof Date) return value;\r\n if (typeof value === 'number') return new Date(value);\r\n if (typeof value === 'string' && ISO_DATE_PATTERN.test(value)) {\r\n const d = new Date(value);\r\n return isNaN(d.getTime()) ? value : d;\r\n }\r\n return value;\r\n }\r\n\r\n if (columnType === 'number' && typeof value === 'string' && value !== '') {\r\n const n = Number(value);\r\n return Number.isFinite(n) ? n : value;\r\n }\r\n\r\n if (columnType === 'boolean') {\r\n if (typeof value === 'boolean') return value;\r\n if (value === 'true' || value === 1) return true;\r\n if (value === 'false' || value === 0) return false;\r\n }\r\n\r\n return value;\r\n}\r\n\r\n/**\r\n * Convert an exceljs cell value into a portable JS value.\r\n *\r\n * options:\r\n * nullForBlank: boolean \u2014 empty cells become null (default true)\r\n * trimStrings: boolean \u2014 strip leading/trailing whitespace from strings\r\n * dateFormat: 'iso' | 'date' | 'epoch'\r\n */\r\nexport function valueForRead(cell, { nullForBlank = true, trimStrings = true, dateFormat = 'iso' } = {}) {\r\n if (cell === undefined || cell === null) return nullForBlank ? null : '';\r\n\r\n // exceljs returns CellValue which can be primitive or object; cell.value is the\r\n // canonical accessor. When called with a raw value (e.g. from streaming), it's\r\n // already the primitive.\r\n const raw = (cell && typeof cell === 'object' && 'value' in cell) ? cell.value : cell;\r\n\r\n if (raw === null || raw === undefined || raw === '') return nullForBlank ? null : '';\r\n\r\n // Date cells\r\n if (raw instanceof Date) return formatDate(raw, dateFormat);\r\n\r\n // Hyperlink object: { text, hyperlink, ... } \u2014 return the visible text\r\n if (typeof raw === 'object' && raw.text !== undefined && raw.hyperlink !== undefined) {\r\n return trimStrings ? String(raw.text).trim() : String(raw.text);\r\n }\r\n\r\n // Rich text object: { richText: [{ text, font }, ...] }\r\n if (typeof raw === 'object' && Array.isArray(raw.richText)) {\r\n const joined = raw.richText.map(r => r.text).join('');\r\n return trimStrings ? joined.trim() : joined;\r\n }\r\n\r\n // Formula object: { formula, result }\r\n if (typeof raw === 'object' && raw.formula !== undefined) {\r\n return raw.result !== undefined ? raw.result : null;\r\n }\r\n\r\n // Error cell: { error: '#N/A' }\r\n if (typeof raw === 'object' && raw.error !== undefined) return null;\r\n\r\n if (typeof raw === 'string') return trimStrings ? raw.trim() : raw;\r\n return raw;\r\n}\r\n\r\nfunction formatDate(d, fmt) {\r\n switch (fmt) {\r\n case 'date': return d;\r\n case 'epoch': return d.getTime();\r\n case 'iso':\r\n default: return d.toISOString();\r\n }\r\n}\r\n"],
|
|
5
|
-
"mappings": ";AAAA,SAAS,YAAY,kBAAkB;;;ACCvC,SAAS,cAAc;AAGvB,OAAO,aAAa;;;
|
|
4
|
+
"sourcesContent": ["import { parentPort, workerData } from 'node:worker_threads';\r\nimport { readSource } from '../reader.js';\r\n\r\n(async () => {\r\n try {\r\n const { payload, options } = workerData;\r\n const result = await readSource(payload, options);\r\n parentPort.postMessage({ ok: true, result });\r\n } catch (err) {\r\n parentPort.postMessage({\r\n ok: false,\r\n error: { message: err.message, code: err.code, stack: err.stack, details: err.details }\r\n });\r\n }\r\n})();\r\n", "import { Readable } from 'node:stream';\r\nimport { Buffer } from 'node:buffer';\r\nimport { createReadStream } from 'node:fs';\r\nimport { stat } from 'node:fs/promises';\r\nimport ExcelJS from 'exceljs';\r\n\r\nimport { ExcelIoError } from './errors.js';\r\nimport { valueForRead } from './coerce.js';\r\n\r\nconst DEFAULT_BATCH = 5000;\r\n\r\n/**\r\n * Read a workbook from a Buffer, file path, or readable stream.\r\n *\r\n * Currently uses the non-streaming `xlsx.load` / `xlsx.read` API for reliability.\r\n * Large files may exceed available memory. Worker-thread offload keeps parsing\r\n * off the main thread, but does not reduce total process memory or isolate it.\r\n * A future optimisation can swap to `stream.xlsx.WorkbookReader` once exceljs\r\n * stabilises its async iterator semantics across versions.\r\n */\r\nexport async function readSource(input, options = {}) {\r\n const startedAt = Date.now();\r\n const stats = { totalRows: 0, totalSheets: 0, durationMs: 0 };\r\n const errors = [];\r\n\r\n const {\r\n headerRow = 1,\r\n nullForBlank = true,\r\n trimStrings = true,\r\n dateFormat = 'iso',\r\n validateRow,\r\n afterRead,\r\n onRowError = 'collect',\r\n batchSize = DEFAULT_BATCH,\r\n onProgress,\r\n signal\r\n } = options;\r\n\r\n const wb = new ExcelJS.Workbook();\r\n try {\r\n if (Buffer.isBuffer(input)) {\r\n await wb.xlsx.load(input);\r\n } else if (input instanceof Uint8Array) {\r\n // Worker boundary downgrades Buffer to Uint8Array; rewrap.\r\n await wb.xlsx.load(Buffer.from(input.buffer, input.byteOffset, input.byteLength));\r\n } else if (typeof input === 'string') {\r\n await wb.xlsx.readFile(input);\r\n } else if (input && typeof input.pipe === 'function') {\r\n await wb.xlsx.read(input);\r\n } else {\r\n throw new ExcelIoError('Invalid input \u2014 expected Buffer, file path, or readable stream', { code: 'INVALID_SPEC' });\r\n }\r\n } catch (err) {\r\n if (err instanceof ExcelIoError) throw err;\r\n throw new ExcelIoError(`Failed to parse workbook: ${err.message}`, { code: 'IO_ERROR', cause: err });\r\n }\r\n\r\n const sheets = [];\r\n\r\n for (let s = 0; s < wb.worksheets.length; s++) {\r\n if (signal?.aborted) throw new ExcelIoError('Aborted', { code: 'ABORTED' });\r\n\r\n const ws = wb.worksheets[s];\r\n stats.totalSheets++;\r\n\r\n const sheetMeta = { sheet: ws.name, columns: [], data: [] };\r\n let columnKeys = null;\r\n\r\n ws.eachRow({ includeEmpty: false }, (row, rowNumber) => {\r\n // Header row\r\n if (rowNumber === headerRow) {\r\n columnKeys = readHeaderRow(row);\r\n sheetMeta.columns = columnKeys\r\n .filter(Boolean)\r\n .map(k => ({ key: k, header: k }));\r\n return;\r\n }\r\n if (rowNumber < headerRow || !columnKeys) return;\r\n if (signal?.aborted) throw new ExcelIoError('Aborted', { code: 'ABORTED' });\r\n\r\n const obj = {};\r\n let isEmpty = true;\r\n for (let i = 0; i < columnKeys.length; i++) {\r\n const key = columnKeys[i];\r\n if (!key) continue;\r\n const cell = row.getCell(i + 1);\r\n const v = valueForRead(cell, { nullForBlank, trimStrings, dateFormat });\r\n if (v !== null && v !== '' && v !== undefined) isEmpty = false;\r\n obj[key] = v;\r\n }\r\n if (isEmpty) return;\r\n\r\n const ctx = {\r\n workbookIndex: 0,\r\n workbookName: undefined,\r\n sheetIndex: s,\r\n sheetName: ws.name,\r\n rowNumber\r\n };\r\n\r\n let outRow = obj;\r\n if (afterRead) {\r\n try {\r\n outRow = afterRead(obj, ctx) ?? obj;\r\n } catch (err) {\r\n const e = mkRowError(ctx, 'TRANSFORM_ERROR', err.message);\r\n if (onRowError === 'fail') throw new ExcelIoError(e.message, { code: 'ROW_VALIDATION', details: e });\r\n errors.push(e);\r\n return;\r\n }\r\n }\r\n\r\n if (validateRow) {\r\n const issue = validateRow(outRow, ctx);\r\n if (issue) {\r\n const e = mkRowError(ctx, issue.code || 'VALIDATION_FAILED', issue.message, issue.column);\r\n if (onRowError === 'fail') throw new ExcelIoError(e.message, { code: 'ROW_VALIDATION', details: e });\r\n errors.push(e);\r\n return;\r\n }\r\n }\r\n\r\n sheetMeta.data.push(outRow);\r\n stats.totalRows++;\r\n\r\n if (onProgress && stats.totalRows % batchSize === 0) {\r\n onProgress({ phase: 'read', sheetName: ws.name, rowsProcessed: stats.totalRows });\r\n }\r\n });\r\n\r\n sheets.push(sheetMeta);\r\n }\r\n\r\n stats.durationMs = Date.now() - startedAt;\r\n\r\n return {\r\n ok: errors.length === 0,\r\n data: [{ workbook: undefined, sheets }],\r\n errors,\r\n stats\r\n };\r\n}\r\n\r\n/* \u2500\u2500\u2500\u2500\u2500\u2500 helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\r\n\r\nfunction readHeaderRow(row) {\r\n const headers = [];\r\n // exceljs row.values is sparse: index 0 unused, headers start at 1\r\n const values = row.values;\r\n if (!Array.isArray(values)) return headers;\r\n for (let i = 1; i < values.length; i++) {\r\n const v = values[i];\r\n headers.push(v == null ? null : String(v).trim());\r\n }\r\n return headers;\r\n}\r\n\r\nfunction mkRowError(ctx, code, message, column) {\r\n return {\r\n workbook: ctx.workbookIndex,\r\n sheet: ctx.sheetName,\r\n row: ctx.rowNumber,\r\n column: column ?? null,\r\n code,\r\n message\r\n };\r\n}\r\n", "/**\r\n * Custom error type for excelio. No external dependencies \u2014 keeps the package\r\n * portable to any Node project.\r\n *\r\n * Codes:\r\n * INVALID_SPEC \u2014 caller passed a malformed spec\r\n * IO_ERROR \u2014 corrupt input file, write failure, etc.\r\n * ABORTED \u2014 operation cancelled via AbortController\r\n * WORKER_ERROR \u2014 worker thread crashed or returned an error\r\n * ROW_VALIDATION \u2014 a row failed validation (only thrown when onRowError === 'fail')\r\n * SOURCE_ERROR \u2014 an iterable sheet's row source threw or returned an invalid result\r\n */\r\nexport class ExcelIoError extends Error {\r\n constructor(message, { code = 'IO_ERROR', cause, details } = {}) {\r\n super(message);\r\n this.name = 'ExcelIoError';\r\n this.code = code;\r\n if (cause !== undefined) this.cause = cause;\r\n if (details !== undefined) this.details = details;\r\n }\r\n}\r\n", "/**\r\n * Cell value coercion in both directions.\r\n *\r\n * Write side: accept a JS value + optional column type, normalise to what exceljs\r\n * expects. Excel-native types are Number, String, Boolean, Date, formula objects,\r\n * and null.\r\n *\r\n * Read side: take a cell from exceljs and turn it into a portable JS value. Dates\r\n * default to ISO 8601 strings; configurable via `dateFormat`.\r\n */\r\n\r\nconst ISO_DATE_PATTERN = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?)?$/;\r\n\r\n/**\r\n * Normalise a JS value for writing into a cell. Returns the value as-is for most\r\n * types; converts ISO date strings + epoch ms to Date when the column declares\r\n * `type: 'date'`.\r\n */\r\nexport function valueForWrite(value, columnType) {\r\n if (value === null || value === undefined) return null;\r\n\r\n if (columnType === 'date') {\r\n if (value instanceof Date) return value;\r\n if (typeof value === 'number') return new Date(value);\r\n if (typeof value === 'string' && ISO_DATE_PATTERN.test(value)) {\r\n const d = new Date(value);\r\n return isNaN(d.getTime()) ? value : d;\r\n }\r\n return value;\r\n }\r\n\r\n if (columnType === 'number' && typeof value === 'string' && value !== '') {\r\n const n = Number(value);\r\n return Number.isFinite(n) ? n : value;\r\n }\r\n\r\n if (columnType === 'boolean') {\r\n if (typeof value === 'boolean') return value;\r\n if (value === 'true' || value === 1) return true;\r\n if (value === 'false' || value === 0) return false;\r\n }\r\n\r\n return value;\r\n}\r\n\r\n/**\r\n * Convert an exceljs cell value into a portable JS value.\r\n *\r\n * options:\r\n * nullForBlank: boolean \u2014 empty cells become null (default true)\r\n * trimStrings: boolean \u2014 strip leading/trailing whitespace from strings\r\n * dateFormat: 'iso' | 'date' | 'epoch'\r\n */\r\nexport function valueForRead(cell, { nullForBlank = true, trimStrings = true, dateFormat = 'iso' } = {}) {\r\n if (cell === undefined || cell === null) return nullForBlank ? null : '';\r\n\r\n // exceljs returns CellValue which can be primitive or object; cell.value is the\r\n // canonical accessor. When called with a raw value (e.g. from streaming), it's\r\n // already the primitive.\r\n const raw = (cell && typeof cell === 'object' && 'value' in cell) ? cell.value : cell;\r\n\r\n if (raw === null || raw === undefined || raw === '') return nullForBlank ? null : '';\r\n\r\n // Date cells\r\n if (raw instanceof Date) return formatDate(raw, dateFormat);\r\n\r\n // Hyperlink object: { text, hyperlink, ... } \u2014 return the visible text\r\n if (typeof raw === 'object' && raw.text !== undefined && raw.hyperlink !== undefined) {\r\n return trimStrings ? String(raw.text).trim() : String(raw.text);\r\n }\r\n\r\n // Rich text object: { richText: [{ text, font }, ...] }\r\n if (typeof raw === 'object' && Array.isArray(raw.richText)) {\r\n const joined = raw.richText.map(r => r.text).join('');\r\n return trimStrings ? joined.trim() : joined;\r\n }\r\n\r\n // Formula object: { formula, result }\r\n if (typeof raw === 'object' && raw.formula !== undefined) {\r\n return raw.result !== undefined ? raw.result : null;\r\n }\r\n\r\n // Error cell: { error: '#N/A' }\r\n if (typeof raw === 'object' && raw.error !== undefined) return null;\r\n\r\n if (typeof raw === 'string') return trimStrings ? raw.trim() : raw;\r\n return raw;\r\n}\r\n\r\nfunction formatDate(d, fmt) {\r\n switch (fmt) {\r\n case 'date': return d;\r\n case 'epoch': return d.getTime();\r\n case 'iso':\r\n default: return d.toISOString();\r\n }\r\n}\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|